@realastrox11/chronoflow
v0.0.2
Published
ChronoFlow — declare asynchronous tasks with explicit dependencies as a graph; run them with controlled concurrency, retries, and automatic ordering. Type-safe wiring between tasks.
Downloads
15
Readme
ChronoFlow
ChronoFlow lets you declare asynchronous tasks as a dependency graph. It runs them with controlled concurrency, retries, and automatic ordering — with type-safe wiring between tasks.
Installation
npm install @realastrox11/chronoflowExample
import { defineTask, Flow } from "@realastrox11/chronoflow";
const defs = {
fetchUsers: defineTask([], async () => {
await new Promise(r => setTimeout(r, 100));
return [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }];
}),
fetchPosts: defineTask(["fetchUsers"], async ({ get }) => {
const users = await get("fetchUsers");
const posts = await Promise.all(
users.map(u => ({ userId: u.id, posts: [{ title: `Post by ${u.name}` }] }))
);
return posts;
}),
combine: defineTask(["fetchUsers", "fetchPosts"], async ({ get }) => {
const users = await get("fetchUsers");
const posts = await get("fetchPosts");
return users.map(u => ({
...u,
posts: posts.find(p => p.userId === u.id)?.posts ?? [],
}));
}),
};
const flow = new Flow(defs, {
concurrency: 4,
onTaskStart: key => console.log("▶", key),
onTaskComplete: (key, _res, dur) => console.log("✓", key, dur + "ms"),
});
const result = await flow.run();
console.log(result.combine);Output:
▶ fetchUsers
✓ fetchUsers 103ms
▶ fetchPosts
✓ fetchPosts 55ms
▶ combine
✓ combine 7ms
[ { id: 1, name: 'Alice', posts: [Array] }, { id: 2, name: 'Bob', posts: [Array] } ]Features
- Declarative async dependency graphs
- Type-safe access to dependent results
- Automatic concurrency control
- Retry and timeout options per task
- Lifecycle hooks (
onTaskStart,onTaskComplete,onTaskError) - Cycle and missing dependency detection
- Race-safe memoized execution
- Zero external dependencies
Task Options
Each task can specify:
| Option | Type | Description |
| ----------- | --------- | --------------------------------------- |
| retry | number | Number of retries before failing |
| timeoutMs | number | Milliseconds before task aborts |
| cache | boolean | Whether to reuse result within same run |
Example:
defineTask(["depA"], async ({ get }) => {
const a = await get("depA");
return a + 1;
}, { retry: 2, timeoutMs: 5000 });Hooks
You can listen to lifecycle events:
| Hook | Description |
| ----------------------------------------- | ----------------------------------------- |
| onTaskStart(key) | Fires when a task begins |
| onTaskComplete(key, result, durationMs) | Fires when a task succeeds |
| onTaskError(key, error) | Fires when a task fails after all retries |
Testing
npm testor with coverage:
npm run test:coverageThe test suite validates:
- Concurrency limits
- Hook lifecycle events
- Retry logic
- Timeout enforcement
- Race-condition safety
CI and Coverage
The repository includes a GitHub Actions workflow (.github/workflows/ci.yml) that runs:
- TypeScript build
- Vitest tests
- Coverage reporting (LCOV + Codecov)
Roadmap
| Status | Feature | | :----: | :---------------------- | | ✅ | Dependency validation | | ✅ | Retries and timeouts | | ✅ | Concurrency control | | ✅ | Lifecycle hooks | | 🔜 | Caching and persistence | | 🔜 | Graph visualizer CLI | | 🔜 | Tracing and telemetry |
License
MIT © AstroX11
ChronoFlow — deterministic async orchestration for humans.
