@cascade-flow/worker 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,99 @@
1
+ # @cascadeflow/worker
2
+
3
+ Distributed step-level workflow execution with queue-based processing.
4
+
5
+ ## Installation
6
+
7
+ The worker requires a backend implementation to persist workflow state. Install the worker along with your chosen backend:
8
+
9
+ ### With Filesystem Backend (Recommended for Development)
10
+
11
+ ```bash
12
+ npm install @cascadeflow/worker @cascadeflow/backend-filesystem
13
+ ```
14
+
15
+ ### With PostgreSQL Backend (Production)
16
+
17
+ ```bash
18
+ npm install @cascadeflow/worker @cascadeflow/backend-postgres
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ### CLI
24
+
25
+ ```bash
26
+ cf worker start [--mode unified|executor|scheduler] [--concurrency n]
27
+ ```
28
+
29
+ ### Programmatic
30
+
31
+ ```typescript
32
+ import { StepWorker } from "@cascade-flow/worker";
33
+ import { FileSystemBackend } from "@cascade-flow/backend-filesystem";
34
+
35
+ const worker = new StepWorker(new FileSystemBackend("./.runs"), {
36
+ mode: "unified",
37
+ concurrency: 5,
38
+ pollInterval: 1000,
39
+ });
40
+
41
+ await worker.start();
42
+ ```
43
+
44
+ **Note:** Worker automatically discovers workflows with support for nested step groups. Steps can be organized in arbitrary directory hierarchies (e.g., `steps/data-processing/extract/fetch-data/step.ts`). Step IDs in the registry will reflect the full path.
45
+
46
+ ## Architecture
47
+
48
+ **Events-as-queue pattern with 4 concurrent loops:**
49
+
50
+ 1. **Executor** - Claims & executes scheduled steps
51
+ 2. **Scheduler** - Schedules ready steps, detects completion
52
+ 3. **Heartbeat** - Proves worker liveness (5s interval)
53
+ 4. **Reclamation** - Reclaims steps from crashed workers (30s threshold)
54
+
55
+ ## Modes
56
+
57
+ - **Unified** (default) - All 4 loops in one process
58
+ - **Executor** - Execute + heartbeat only (needs separate scheduler)
59
+ - **Scheduler** - Schedule + reclamation only (needs separate executors)
60
+
61
+ ## Timeouts
62
+
63
+ **Step execution (3-tier fallback):**
64
+ 1. `defineStep({ timeoutMs })` - Highest priority
65
+ 2. `submit({ timeout })` - Workflow-wide default
66
+ 3. `300000ms` (5 min) - System default
67
+
68
+ **Worker health monitoring:**
69
+ - Stale threshold (default 30s) - Detects crashed workers via missing heartbeats
70
+
71
+ ## Failure Recovery
72
+
73
+ - **Worker crash** → Stale heartbeat → Step reclaimed → Rescheduled
74
+ - **Step timeout** → `StepFailed` event → Retry with delay (if configured)
75
+ - **Terminal failure** → Scheduler stops scheduling → `WorkflowFailed`
76
+
77
+ ## API
78
+
79
+ ```typescript
80
+ interface StepWorkerOptions {
81
+ workerId?: string;
82
+ mode?: "unified" | "executor" | "scheduler";
83
+ concurrency?: number;
84
+ pollInterval?: number;
85
+ heartbeatInterval?: number;
86
+ staleThreshold?: number;
87
+ schedulerInterval?: number;
88
+ shutdownTimeout?: number;
89
+ workflowsDir?: string;
90
+ baseDir?: string;
91
+ }
92
+
93
+ class StepWorker {
94
+ constructor(backend?: Backend, options?: StepWorkerOptions);
95
+ async start(): Promise<void>;
96
+ async stop(): Promise<void>;
97
+ getStats(): StepWorkerStats;
98
+ }
99
+ ```
@@ -0,0 +1,20 @@
1
+ import type { Backend } from "@cascade-flow/backend-interface";
2
+ import { type LoadedStep } from "@cascade-flow/runner";
3
+ /**
4
+ * Check if all dependencies for a step are satisfied
5
+ * Returns true if the step can be scheduled
6
+ */
7
+ export declare function checkDependenciesSatisfied(step: LoadedStep, backend: Backend, workflowSlug: string, runId: string): Promise<boolean>;
8
+ /**
9
+ * Load outputs from all dependencies
10
+ * Returns a map of dependency alias to output value
11
+ */
12
+ export declare function loadDependencyOutputs(step: LoadedStep, backend: Backend, workflowSlug: string, runId: string): Promise<Record<string, any>>;
13
+ /**
14
+ * Find all steps that depend on a given step
15
+ * @param targetStepId - The stepId (unique identifier) to find dependents for
16
+ * @param allSteps - All steps in the workflow
17
+ * @param requiredOnly - If true, only return steps with required dependencies
18
+ */
19
+ export declare function findDependentSteps(targetStepId: string, allSteps: LoadedStep[], requiredOnly?: boolean): LoadedStep[];
20
+ //# sourceMappingURL=dependency-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-resolver.d.ts","sourceRoot":"","sources":["../../src/execution/dependency-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AAE/D,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAIvD;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC,CA+BlB;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAoC9B;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,UAAU,EAAE,EACtB,YAAY,GAAE,OAAe,GAC5B,UAAU,EAAE,CAed"}
@@ -0,0 +1,3 @@
1
+ export { StepWorker } from "./step-worker.ts";
2
+ export type { StepWorkerOptions, StepWorkerStats, WorkerMode } from "./types.ts";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}