bunqueue 2.7.0 → 2.7.2
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 +11 -0
- package/dist/client/workflow/emitter.d.ts +18 -0
- package/dist/client/workflow/emitter.d.ts.map +1 -0
- package/dist/client/workflow/emitter.js +75 -0
- package/dist/client/workflow/emitter.js.map +1 -0
- package/dist/client/workflow/engine.d.ts +18 -1
- package/dist/client/workflow/engine.d.ts.map +1 -1
- package/dist/client/workflow/engine.js +51 -1
- package/dist/client/workflow/engine.js.map +1 -1
- package/dist/client/workflow/executor.d.ts +17 -15
- package/dist/client/workflow/executor.d.ts.map +1 -1
- package/dist/client/workflow/executor.js +141 -126
- package/dist/client/workflow/executor.js.map +1 -1
- package/dist/client/workflow/index.d.ts +2 -1
- package/dist/client/workflow/index.d.ts.map +1 -1
- package/dist/client/workflow/index.js +1 -0
- package/dist/client/workflow/index.js.map +1 -1
- package/dist/client/workflow/loops.d.ts +15 -0
- package/dist/client/workflow/loops.d.ts.map +1 -0
- package/dist/client/workflow/loops.js +76 -0
- package/dist/client/workflow/loops.js.map +1 -0
- package/dist/client/workflow/runner.d.ts +21 -0
- package/dist/client/workflow/runner.d.ts.map +1 -0
- package/dist/client/workflow/runner.js +180 -0
- package/dist/client/workflow/runner.js.map +1 -0
- package/dist/client/workflow/store.d.ts +6 -0
- package/dist/client/workflow/store.d.ts.map +1 -1
- package/dist/client/workflow/store.js +55 -0
- package/dist/client/workflow/store.js.map +1 -1
- package/dist/client/workflow/types.d.ts +95 -0
- package/dist/client/workflow/types.d.ts.map +1 -1
- package/dist/client/workflow/workflow.d.ts +19 -1
- package/dist/client/workflow/workflow.d.ts.map +1 -1
- package/dist/client/workflow/workflow.js +93 -0
- package/dist/client/workflow/workflow.js.map +1 -1
- package/package.json +13 -2
package/README.md
CHANGED
|
@@ -519,7 +519,18 @@ await engine.start('order-pipeline', { orderId: 'ORD-1', amount: 99.99 });
|
|
|
519
519
|
|
|
520
520
|
- **Saga pattern** — Compensation handlers run in reverse when a step fails
|
|
521
521
|
- **Branching** — Route to different paths based on runtime conditions
|
|
522
|
+
- **Parallel steps** — Run independent steps concurrently with `.parallel()`
|
|
522
523
|
- **Human-in-the-loop** — `waitFor('event')` pauses execution, `engine.signal()` resumes it
|
|
524
|
+
- **Signal timeout** — `waitFor('event', { timeout })` fails if signal doesn't arrive in time
|
|
525
|
+
- **Step retry** — Automatic retry with exponential backoff and jitter
|
|
526
|
+
- **Nested workflows** — Compose workflows with `.subWorkflow()`, child results passed back
|
|
527
|
+
- **Loops** — `doUntil()` and `doWhile()` for conditional iteration with safety limits
|
|
528
|
+
- **forEach** — Iterate over dynamic item lists with indexed step results (`step:0`, `step:1`, ...)
|
|
529
|
+
- **Map** — Synchronous data transforms between steps with `.map()`
|
|
530
|
+
- **Schema validation** — Validate step input/output with Zod, ArkType, Valibot, or any `.parse()` schema
|
|
531
|
+
- **Subscribe** — `engine.subscribe(id, callback)` to monitor a specific execution's events
|
|
532
|
+
- **Observability** — Typed event emitter with 11 event types (`engine.on/onAny`)
|
|
533
|
+
- **Cleanup & archival** — `engine.cleanup()` / `engine.archive()` for execution history management
|
|
523
534
|
- **Step timeouts** — Prevent steps from running indefinitely
|
|
524
535
|
- **Context passing** — Each step accesses input and all previous step results
|
|
525
536
|
- **SQLite persistence** — Execution state survives restarts
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WorkflowEmitter - Typed event system for workflow observability
|
|
3
|
+
*/
|
|
4
|
+
import type { WorkflowEventType, StepEvent, WorkflowLifecycleEvent, WorkflowEventListener, ExecutionState } from './types';
|
|
5
|
+
export declare class WorkflowEmitter {
|
|
6
|
+
private readonly listeners;
|
|
7
|
+
private readonly globalListeners;
|
|
8
|
+
on(type: WorkflowEventType, listener: WorkflowEventListener): this;
|
|
9
|
+
onAny(listener: WorkflowEventListener): this;
|
|
10
|
+
off(type: WorkflowEventType, listener: WorkflowEventListener): this;
|
|
11
|
+
offAny(listener: WorkflowEventListener): this;
|
|
12
|
+
emitStep(type: 'step:started' | 'step:completed' | 'step:failed' | 'step:retry', executionId: string, workflowName: string, stepName: string, extra?: Partial<Omit<StepEvent, 'type' | 'executionId' | 'workflowName' | 'timestamp' | 'stepName'>>): void;
|
|
13
|
+
emitWorkflow(type: 'workflow:started' | 'workflow:completed' | 'workflow:failed' | 'workflow:compensating' | 'workflow:waiting', executionId: string, workflowName: string, state: ExecutionState, extra?: Partial<Omit<WorkflowLifecycleEvent, 'type' | 'executionId' | 'workflowName' | 'timestamp' | 'state'>>): void;
|
|
14
|
+
emitSignal(type: 'signal:received' | 'signal:timeout', executionId: string, workflowName: string, event: string, payload?: unknown): void;
|
|
15
|
+
removeAllListeners(): void;
|
|
16
|
+
private dispatch;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=emitter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emitter.d.ts","sourceRoot":"","sources":["../../../src/client/workflow/emitter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,iBAAiB,EAEjB,SAAS,EACT,sBAAsB,EAEtB,qBAAqB,EACrB,cAAc,EACf,MAAM,SAAS,CAAC;AAEjB,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4D;IACtF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoC;IAEpE,EAAE,CAAC,IAAI,EAAE,iBAAiB,EAAE,QAAQ,EAAE,qBAAqB,GAAG,IAAI;IAUlE,KAAK,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI;IAK5C,GAAG,CAAC,IAAI,EAAE,iBAAiB,EAAE,QAAQ,EAAE,qBAAqB,GAAG,IAAI;IAKnE,MAAM,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI;IAK7C,QAAQ,CACN,IAAI,EAAE,cAAc,GAAG,gBAAgB,GAAG,aAAa,GAAG,YAAY,EACtE,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,OAAO,CACb,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,GAAG,cAAc,GAAG,WAAW,GAAG,UAAU,CAAC,CACpF,GACA,IAAI;IAYP,YAAY,CACV,IAAI,EACA,kBAAkB,GAClB,oBAAoB,GACpB,iBAAiB,GACjB,uBAAuB,GACvB,kBAAkB,EACtB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,cAAc,EACrB,KAAK,CAAC,EAAE,OAAO,CACb,IAAI,CAAC,sBAAsB,EAAE,MAAM,GAAG,aAAa,GAAG,cAAc,GAAG,WAAW,GAAG,OAAO,CAAC,CAC9F,GACA,IAAI;IAYP,UAAU,CACR,IAAI,EAAE,iBAAiB,GAAG,gBAAgB,EAC1C,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,OAAO,GAChB,IAAI;IAYP,kBAAkB,IAAI,IAAI;IAK1B,OAAO,CAAC,QAAQ;CAOjB"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WorkflowEmitter - Typed event system for workflow observability
|
|
3
|
+
*/
|
|
4
|
+
export class WorkflowEmitter {
|
|
5
|
+
listeners = new Map();
|
|
6
|
+
globalListeners = new Set();
|
|
7
|
+
on(type, listener) {
|
|
8
|
+
let set = this.listeners.get(type);
|
|
9
|
+
if (!set) {
|
|
10
|
+
set = new Set();
|
|
11
|
+
this.listeners.set(type, set);
|
|
12
|
+
}
|
|
13
|
+
set.add(listener);
|
|
14
|
+
return this;
|
|
15
|
+
}
|
|
16
|
+
onAny(listener) {
|
|
17
|
+
this.globalListeners.add(listener);
|
|
18
|
+
return this;
|
|
19
|
+
}
|
|
20
|
+
off(type, listener) {
|
|
21
|
+
this.listeners.get(type)?.delete(listener);
|
|
22
|
+
return this;
|
|
23
|
+
}
|
|
24
|
+
offAny(listener) {
|
|
25
|
+
this.globalListeners.delete(listener);
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
emitStep(type, executionId, workflowName, stepName, extra) {
|
|
29
|
+
const event = {
|
|
30
|
+
type,
|
|
31
|
+
executionId,
|
|
32
|
+
workflowName,
|
|
33
|
+
timestamp: Date.now(),
|
|
34
|
+
stepName,
|
|
35
|
+
...extra,
|
|
36
|
+
};
|
|
37
|
+
this.dispatch(type, event);
|
|
38
|
+
}
|
|
39
|
+
emitWorkflow(type, executionId, workflowName, state, extra) {
|
|
40
|
+
const event = {
|
|
41
|
+
type,
|
|
42
|
+
executionId,
|
|
43
|
+
workflowName,
|
|
44
|
+
timestamp: Date.now(),
|
|
45
|
+
state,
|
|
46
|
+
...extra,
|
|
47
|
+
};
|
|
48
|
+
this.dispatch(type, event);
|
|
49
|
+
}
|
|
50
|
+
emitSignal(type, executionId, workflowName, event, payload) {
|
|
51
|
+
const evt = {
|
|
52
|
+
type,
|
|
53
|
+
executionId,
|
|
54
|
+
workflowName,
|
|
55
|
+
timestamp: Date.now(),
|
|
56
|
+
event,
|
|
57
|
+
payload,
|
|
58
|
+
};
|
|
59
|
+
this.dispatch(type, evt);
|
|
60
|
+
}
|
|
61
|
+
removeAllListeners() {
|
|
62
|
+
this.listeners.clear();
|
|
63
|
+
this.globalListeners.clear();
|
|
64
|
+
}
|
|
65
|
+
dispatch(type, event) {
|
|
66
|
+
const typed = this.listeners.get(type);
|
|
67
|
+
if (typed) {
|
|
68
|
+
for (const fn of typed)
|
|
69
|
+
fn(event);
|
|
70
|
+
}
|
|
71
|
+
for (const fn of this.globalListeners)
|
|
72
|
+
fn(event);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=emitter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emitter.js","sourceRoot":"","sources":["../../../src/client/workflow/emitter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH,MAAM,OAAO,eAAe;IACT,SAAS,GAAG,IAAI,GAAG,EAAiD,CAAC;IACrE,eAAe,GAAG,IAAI,GAAG,EAAyB,CAAC;IAEpE,EAAE,CAAC,IAAuB,EAAE,QAA+B;QACzD,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;YAChB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAChC,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,QAA+B;QACnC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAC,IAAuB,EAAE,QAA+B;QAC1D,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC3C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,QAA+B;QACpC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,QAAQ,CACN,IAAsE,EACtE,WAAmB,EACnB,YAAoB,EACpB,QAAgB,EAChB,KAEC;QAED,MAAM,KAAK,GAAc;YACvB,IAAI;YACJ,WAAW;YACX,YAAY;YACZ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,QAAQ;YACR,GAAG,KAAK;SACT,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED,YAAY,CACV,IAKsB,EACtB,WAAmB,EACnB,YAAoB,EACpB,KAAqB,EACrB,KAEC;QAED,MAAM,KAAK,GAA2B;YACpC,IAAI;YACJ,WAAW;YACX,YAAY;YACZ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,KAAK;YACL,GAAG,KAAK;SACT,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED,UAAU,CACR,IAA0C,EAC1C,WAAmB,EACnB,YAAoB,EACpB,KAAa,EACb,OAAiB;QAEjB,MAAM,GAAG,GAAgB;YACvB,IAAI;YACJ,WAAW;YACX,YAAY;YACZ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,KAAK;YACL,OAAO;SACR,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,kBAAkB;QAChB,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;IAC/B,CAAC;IAEO,QAAQ,CAAC,IAAuB,EAAE,KAAoB;QAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,MAAM,EAAE,IAAI,KAAK;gBAAE,EAAE,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC;QACD,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,eAAe;YAAE,EAAE,CAAC,KAAK,CAAC,CAAC;IACnD,CAAC;CACF"}
|
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
* Manages lifecycle of internal Queue, Worker, and Store.
|
|
4
4
|
*/
|
|
5
5
|
import type { Workflow } from './workflow';
|
|
6
|
-
import type { EngineOptions, RunHandle, Execution, ExecutionState } from './types';
|
|
6
|
+
import type { EngineOptions, RunHandle, Execution, ExecutionState, WorkflowEventType, WorkflowEventListener } from './types';
|
|
7
7
|
export declare class Engine {
|
|
8
8
|
private readonly queue;
|
|
9
9
|
private readonly worker;
|
|
10
10
|
private readonly store;
|
|
11
11
|
private readonly executor;
|
|
12
|
+
private readonly emitter;
|
|
12
13
|
constructor(opts?: EngineOptions);
|
|
13
14
|
/** Register a workflow definition */
|
|
14
15
|
register(workflow: Workflow): this;
|
|
@@ -20,6 +21,22 @@ export declare class Engine {
|
|
|
20
21
|
listExecutions(workflowName?: string, state?: ExecutionState): Execution[];
|
|
21
22
|
/** Send a signal to a waiting execution */
|
|
22
23
|
signal(executionId: string, event: string, payload?: unknown): Promise<void>;
|
|
24
|
+
/** Subscribe to a specific workflow event type */
|
|
25
|
+
on(type: WorkflowEventType, listener: WorkflowEventListener): this;
|
|
26
|
+
/** Subscribe to all workflow events */
|
|
27
|
+
onAny(listener: WorkflowEventListener): this;
|
|
28
|
+
/** Unsubscribe from a specific event type */
|
|
29
|
+
off(type: WorkflowEventType, listener: WorkflowEventListener): this;
|
|
30
|
+
/** Unsubscribe a catch-all listener */
|
|
31
|
+
offAny(listener: WorkflowEventListener): this;
|
|
32
|
+
/** Subscribe to all events for a specific execution */
|
|
33
|
+
subscribe(executionId: string, callback: WorkflowEventListener): () => void;
|
|
34
|
+
/** Remove old completed/failed executions */
|
|
35
|
+
cleanup(maxAgeMs: number, states?: ExecutionState[]): number;
|
|
36
|
+
/** Archive old executions to a separate table */
|
|
37
|
+
archive(maxAgeMs: number, states?: ExecutionState[]): number;
|
|
38
|
+
/** Get archived execution count */
|
|
39
|
+
getArchivedCount(): number;
|
|
23
40
|
/** Shut down the engine */
|
|
24
41
|
close(force?: boolean): Promise<void>;
|
|
25
42
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/client/workflow/engine.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/client/workflow/engine.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EACV,aAAa,EACb,SAAS,EACT,SAAS,EACT,cAAc,EAEd,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,SAAS,CAAC;AAIjB,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;gBAE9B,IAAI,GAAE,aAAkB;IAiCpC,qCAAqC;IACrC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAKlC,qCAAqC;IAC/B,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC;IAItE,gCAAgC;IAChC,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAI1C,4CAA4C;IAC5C,cAAc,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,cAAc,GAAG,SAAS,EAAE;IAI1E,2CAA2C;IACrC,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlF,kDAAkD;IAClD,EAAE,CAAC,IAAI,EAAE,iBAAiB,EAAE,QAAQ,EAAE,qBAAqB,GAAG,IAAI;IAKlE,uCAAuC;IACvC,KAAK,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI;IAK5C,6CAA6C;IAC7C,GAAG,CAAC,IAAI,EAAE,iBAAiB,EAAE,QAAQ,EAAE,qBAAqB,GAAG,IAAI;IAKnE,uCAAuC;IACvC,MAAM,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI;IAK7C,uDAAuD;IACvD,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,qBAAqB,GAAG,MAAM,IAAI;IAU3E,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,EAAE,GAAG,MAAM;IAI5D,iDAAiD;IACjD,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,EAAE,GAAG,MAAM;IAI5D,mCAAmC;IACnC,gBAAgB,IAAI,MAAM;IAI1B,2BAA2B;IACrB,KAAK,CAAC,KAAK,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAM1C"}
|
|
@@ -6,12 +6,14 @@ import { Queue } from '../queue/queue';
|
|
|
6
6
|
import { Worker } from '../worker/worker';
|
|
7
7
|
import { WorkflowStore } from './store';
|
|
8
8
|
import { WorkflowExecutor } from './executor';
|
|
9
|
+
import { WorkflowEmitter } from './emitter';
|
|
9
10
|
const DEFAULT_QUEUE_NAME = '__wf:steps';
|
|
10
11
|
export class Engine {
|
|
11
12
|
queue;
|
|
12
13
|
worker;
|
|
13
14
|
store;
|
|
14
15
|
executor;
|
|
16
|
+
emitter;
|
|
15
17
|
constructor(opts = {}) {
|
|
16
18
|
const queueName = opts.queueName ?? DEFAULT_QUEUE_NAME;
|
|
17
19
|
this.queue = new Queue(queueName, {
|
|
@@ -20,7 +22,11 @@ export class Engine {
|
|
|
20
22
|
dataPath: opts.dataPath,
|
|
21
23
|
});
|
|
22
24
|
this.store = new WorkflowStore(opts.dataPath);
|
|
23
|
-
this.
|
|
25
|
+
this.emitter = new WorkflowEmitter();
|
|
26
|
+
if (opts.onEvent) {
|
|
27
|
+
this.emitter.onAny(opts.onEvent);
|
|
28
|
+
}
|
|
29
|
+
this.executor = new WorkflowExecutor(this.store, this.queue, this.emitter);
|
|
24
30
|
this.worker = new Worker(queueName, async (job) => {
|
|
25
31
|
const data = job.data;
|
|
26
32
|
return this.executor.processStep(data);
|
|
@@ -52,11 +58,55 @@ export class Engine {
|
|
|
52
58
|
async signal(executionId, event, payload) {
|
|
53
59
|
return this.executor.signal(executionId, event, payload);
|
|
54
60
|
}
|
|
61
|
+
// ============ Observability ============
|
|
62
|
+
/** Subscribe to a specific workflow event type */
|
|
63
|
+
on(type, listener) {
|
|
64
|
+
this.emitter.on(type, listener);
|
|
65
|
+
return this;
|
|
66
|
+
}
|
|
67
|
+
/** Subscribe to all workflow events */
|
|
68
|
+
onAny(listener) {
|
|
69
|
+
this.emitter.onAny(listener);
|
|
70
|
+
return this;
|
|
71
|
+
}
|
|
72
|
+
/** Unsubscribe from a specific event type */
|
|
73
|
+
off(type, listener) {
|
|
74
|
+
this.emitter.off(type, listener);
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
77
|
+
/** Unsubscribe a catch-all listener */
|
|
78
|
+
offAny(listener) {
|
|
79
|
+
this.emitter.offAny(listener);
|
|
80
|
+
return this;
|
|
81
|
+
}
|
|
82
|
+
/** Subscribe to all events for a specific execution */
|
|
83
|
+
subscribe(executionId, callback) {
|
|
84
|
+
const filter = (event) => {
|
|
85
|
+
if (event.executionId === executionId)
|
|
86
|
+
callback(event);
|
|
87
|
+
};
|
|
88
|
+
this.emitter.onAny(filter);
|
|
89
|
+
return () => this.emitter.offAny(filter);
|
|
90
|
+
}
|
|
91
|
+
// ============ Cleanup ============
|
|
92
|
+
/** Remove old completed/failed executions */
|
|
93
|
+
cleanup(maxAgeMs, states) {
|
|
94
|
+
return this.store.cleanup(maxAgeMs, states);
|
|
95
|
+
}
|
|
96
|
+
/** Archive old executions to a separate table */
|
|
97
|
+
archive(maxAgeMs, states) {
|
|
98
|
+
return this.store.archive(maxAgeMs, states);
|
|
99
|
+
}
|
|
100
|
+
/** Get archived execution count */
|
|
101
|
+
getArchivedCount() {
|
|
102
|
+
return this.store.getArchivedCount();
|
|
103
|
+
}
|
|
55
104
|
/** Shut down the engine */
|
|
56
105
|
async close(force = false) {
|
|
57
106
|
await this.worker.close(force);
|
|
58
107
|
this.queue.close();
|
|
59
108
|
this.store.close();
|
|
109
|
+
this.emitter.removeAllListeners();
|
|
60
110
|
}
|
|
61
111
|
}
|
|
62
112
|
//# sourceMappingURL=engine.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/client/workflow/engine.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/client/workflow/engine.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAY5C,MAAM,kBAAkB,GAAG,YAAY,CAAC;AAExC,MAAM,OAAO,MAAM;IACA,KAAK,CAAQ;IACb,MAAM,CAAS;IACf,KAAK,CAAgB;IACrB,QAAQ,CAAmB;IAC3B,OAAO,CAAkB;IAE1C,YAAY,OAAsB,EAAE;QAClC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,kBAAkB,CAAC;QAEvD,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,SAAS,EAAE;YAChC,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,CAAC,OAAO,GAAG,IAAI,eAAe,EAAE,CAAC;QAErC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnC,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAE3E,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CACtB,SAAS,EACT,KAAK,EAAE,GAAG,EAAE,EAAE;YACZ,MAAM,IAAI,GAAG,GAAG,CAAC,IAA8B,CAAC;YAChD,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC,EACD;YACE,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,CAAC;SACnC,CACF,CAAC;IACJ,CAAC;IAED,qCAAqC;IACrC,QAAQ,CAAC,QAAkB;QACzB,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,qCAAqC;IACrC,KAAK,CAAC,KAAK,CAAC,YAAoB,EAAE,KAAe;QAC/C,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC;IAED,gCAAgC;IAChC,YAAY,CAAC,EAAU;QACrB,OAAO,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,4CAA4C;IAC5C,cAAc,CAAC,YAAqB,EAAE,KAAsB;QAC1D,OAAO,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IAC3D,CAAC;IAED,2CAA2C;IAC3C,KAAK,CAAC,MAAM,CAAC,WAAmB,EAAE,KAAa,EAAE,OAAiB;QAChE,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAC3D,CAAC;IAED,0CAA0C;IAE1C,kDAAkD;IAClD,EAAE,CAAC,IAAuB,EAAE,QAA+B;QACzD,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,uCAAuC;IACvC,KAAK,CAAC,QAA+B;QACnC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6CAA6C;IAC7C,GAAG,CAAC,IAAuB,EAAE,QAA+B;QAC1D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,uCAAuC;IACvC,MAAM,CAAC,QAA+B;QACpC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,uDAAuD;IACvD,SAAS,CAAC,WAAmB,EAAE,QAA+B;QAC5D,MAAM,MAAM,GAA0B,CAAC,KAAK,EAAE,EAAE;YAC9C,IAAI,KAAK,CAAC,WAAW,KAAK,WAAW;gBAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;QACzD,CAAC,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC3B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC;IAED,oCAAoC;IAEpC,6CAA6C;IAC7C,OAAO,CAAC,QAAgB,EAAE,MAAyB;QACjD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC;IAED,iDAAiD;IACjD,OAAO,CAAC,QAAgB,EAAE,MAAyB;QACjD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC;IAED,mCAAmC;IACnC,gBAAgB;QACd,OAAO,IAAI,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC;IACvC,CAAC;IAED,2BAA2B;IAC3B,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK;QACvB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,CAAC;IACpC,CAAC;CACF"}
|
|
@@ -1,32 +1,34 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WorkflowExecutor - Core execution logic
|
|
3
|
-
* Processes steps as bunqueue jobs, handles transitions, branching, compensation.
|
|
4
|
-
*/
|
|
1
|
+
/** WorkflowExecutor - Core execution logic */
|
|
5
2
|
import type { Queue } from '../queue/queue';
|
|
6
3
|
import type { Workflow } from './workflow';
|
|
7
4
|
import type { WorkflowStore } from './store';
|
|
5
|
+
import type { WorkflowEmitter } from './emitter';
|
|
8
6
|
import type { Execution, StepJobData, RunHandle } from './types';
|
|
9
7
|
export declare class WorkflowExecutor {
|
|
10
8
|
private readonly store;
|
|
11
9
|
private readonly queue;
|
|
10
|
+
private readonly emitter;
|
|
12
11
|
private readonly workflows;
|
|
13
|
-
|
|
12
|
+
private readonly timeoutTimers;
|
|
13
|
+
constructor(store: WorkflowStore, queue: Queue, emitter?: WorkflowEmitter | null);
|
|
14
14
|
register(workflow: Workflow): void;
|
|
15
15
|
start(workflowName: string, input: unknown): Promise<RunHandle>;
|
|
16
|
-
/** Process a step job — this is the Worker processor function */
|
|
17
16
|
processStep(data: StepJobData): Promise<unknown>;
|
|
18
17
|
signal(executionId: string, event: string, payload: unknown): Promise<void>;
|
|
19
18
|
getExecution(id: string): Execution | null;
|
|
20
19
|
listExecutions(workflowName?: string, state?: Execution['state']): Execution[];
|
|
21
20
|
private executeNode;
|
|
22
|
-
private
|
|
23
|
-
private
|
|
24
|
-
private
|
|
25
|
-
private
|
|
26
|
-
private
|
|
27
|
-
private
|
|
28
|
-
private
|
|
29
|
-
private
|
|
30
|
-
private
|
|
21
|
+
private runStep;
|
|
22
|
+
private runBranch;
|
|
23
|
+
private runParallel;
|
|
24
|
+
private runSubWorkflow;
|
|
25
|
+
private runWaitFor;
|
|
26
|
+
private runLoop;
|
|
27
|
+
private runForEach;
|
|
28
|
+
private runMap;
|
|
29
|
+
private advance;
|
|
30
|
+
private enqueue;
|
|
31
|
+
private scheduleTimeoutCheck;
|
|
32
|
+
private compensate;
|
|
31
33
|
}
|
|
32
34
|
//# sourceMappingURL=executor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../src/client/workflow/executor.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../src/client/workflow/executor.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAgC,MAAM,SAAS,CAAC;AAgB/F,qBAAa,gBAAgB;IAKzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAN1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+B;IACzD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAoD;gBAG/D,KAAK,EAAE,aAAa,EACpB,KAAK,EAAE,KAAK,EACZ,OAAO,GAAE,eAAe,GAAG,IAAW;IAGzD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAS5B,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC;IAwB/D,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IA8BhD,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBjF,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAI1C,cAAc,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,GAAG,SAAS,EAAE;YAIhE,WAAW;YAiBX,OAAO;YAQP,SAAS;YAkBT,WAAW;YAYX,cAAc;YAiBd,UAAU;YA2CV,OAAO;YAaP,UAAU;YAYV,MAAM;YAWN,OAAO;YAYP,OAAO;IASrB,OAAO,CAAC,oBAAoB;YASd,UAAU;CAwBzB"}
|