@dudousxd/nestjs-durable-core 0.11.0 → 0.13.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/dist/codec-state-store.d.ts +2 -0
- package/dist/codec-state-store.d.ts.map +1 -1
- package/dist/codec-state-store.js +6 -0
- package/dist/codec-state-store.js.map +1 -1
- package/dist/engine.d.ts +60 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +171 -5
- package/dist/engine.js.map +1 -1
- package/dist/events.d.ts +9 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +41 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +64 -1
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/search-attributes.d.ts +17 -0
- package/dist/search-attributes.d.ts.map +1 -0
- package/dist/search-attributes.js +47 -0
- package/dist/search-attributes.js.map +1 -0
- package/dist/test-helpers.d.ts +11 -0
- package/dist/test-helpers.d.ts.map +1 -0
- package/dist/test-helpers.js +15 -0
- package/dist/test-helpers.js.map +1 -0
- package/dist/testing/in-memory-state-store.d.ts +2 -0
- package/dist/testing/in-memory-state-store.d.ts.map +1 -1
- package/dist/testing/in-memory-state-store.js +15 -0
- package/dist/testing/in-memory-state-store.js.map +1 -1
- package/dist/workflow-ctx.d.ts +4 -2
- package/dist/workflow-ctx.d.ts.map +1 -1
- package/dist/workflow-ctx.js +52 -2
- package/dist/workflow-ctx.js.map +1 -1
- package/package.json +1 -1
|
@@ -35,11 +35,13 @@ export declare class CodecStateStore implements StateStore {
|
|
|
35
35
|
getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null>;
|
|
36
36
|
saveCheckpoint(checkpoint: StepCheckpoint): Promise<void>;
|
|
37
37
|
listIncompleteRuns(): Promise<WorkflowRun[]>;
|
|
38
|
+
listPendingRuns(limit: number): Promise<WorkflowRun[]>;
|
|
38
39
|
listDueTimers(nowMs: number): Promise<WorkflowRun[]>;
|
|
39
40
|
tryLockRun(runId: string, owner: string, leaseUntilMs: number, nowMs: number): Promise<boolean>;
|
|
40
41
|
releaseRunLock(runId: string): Promise<void>;
|
|
41
42
|
putSignalWaiter(waiter: SignalWaiter): Promise<void>;
|
|
42
43
|
takeSignalWaiter(token: string): Promise<SignalWaiter | null>;
|
|
44
|
+
listSignalWaiters(prefix: string): Promise<SignalWaiter[]>;
|
|
43
45
|
listRuns(query: RunQuery): Promise<WorkflowRun[]>;
|
|
44
46
|
listCheckpoints(runId: string): Promise<StepCheckpoint[]>;
|
|
45
47
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codec-state-store.d.ts","sourceRoot":"","sources":["../src/codec-state-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEpG;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IAChC,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;CACjC;AAED;;;;;;;;;GASG;AACH,qBAAa,eAAgB,YAAW,UAAU;IAE9C,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBADL,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,YAAY;IAGtC,OAAO,CAAC,GAAG;IAGX,OAAO,CAAC,GAAG;IAIX,OAAO,CAAC,MAAM;IAGd,OAAO,CAAC,MAAM;IAGd,OAAO,CAAC,KAAK;IAGb,OAAO,CAAC,KAAK;IAIb,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,SAAS,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAG1C,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAM9D,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAGlD,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAG/E,cAAc,CAAC,UAAU,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAGnD,kBAAkB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAG5C,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAG1D,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAG/F,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAG5C,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAGpD,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"codec-state-store.d.ts","sourceRoot":"","sources":["../src/codec-state-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEpG;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;IAChC,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC;CACjC;AAED;;;;;;;;;GASG;AACH,qBAAa,eAAgB,YAAW,UAAU;IAE9C,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBADL,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,YAAY;IAGtC,OAAO,CAAC,GAAG;IAGX,OAAO,CAAC,GAAG;IAIX,OAAO,CAAC,MAAM;IAGd,OAAO,CAAC,MAAM;IAGd,OAAO,CAAC,KAAK;IAGb,OAAO,CAAC,KAAK;IAIb,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,SAAS,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAG1C,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAM9D,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAGlD,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAG/E,cAAc,CAAC,UAAU,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAGnD,kBAAkB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAG5C,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAGtD,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAG1D,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAG/F,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAG5C,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAGpD,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAG7D,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAGpD,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAGjD,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;CAGhE"}
|
|
@@ -62,6 +62,9 @@ class CodecStateStore {
|
|
|
62
62
|
async listIncompleteRuns() {
|
|
63
63
|
return (await this.inner.listIncompleteRuns()).map((r) => this.decRun(r));
|
|
64
64
|
}
|
|
65
|
+
async listPendingRuns(limit) {
|
|
66
|
+
return (await this.inner.listPendingRuns(limit)).map((r) => this.decRun(r));
|
|
67
|
+
}
|
|
65
68
|
async listDueTimers(nowMs) {
|
|
66
69
|
return (await this.inner.listDueTimers(nowMs)).map((r) => this.decRun(r));
|
|
67
70
|
}
|
|
@@ -77,6 +80,9 @@ class CodecStateStore {
|
|
|
77
80
|
takeSignalWaiter(token) {
|
|
78
81
|
return this.inner.takeSignalWaiter(token);
|
|
79
82
|
}
|
|
83
|
+
listSignalWaiters(prefix) {
|
|
84
|
+
return this.inner.listSignalWaiters(prefix);
|
|
85
|
+
}
|
|
80
86
|
async listRuns(query) {
|
|
81
87
|
return (await this.inner.listRuns(query)).map((r) => this.decRun(r));
|
|
82
88
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codec-state-store.js","sourceRoot":"","sources":["../src/codec-state-store.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"codec-state-store.js","sourceRoot":"","sources":["../src/codec-state-store.ts"],"names":[],"mappings":"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"}
|
package/dist/engine.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ControlPlane, EngineListener, NamedTransport, RunResult, StateStore, StepError, Transport, UpdateResult, UpdateValidator, WorkflowCtx, WorkflowRun } from './interfaces';
|
|
1
|
+
import type { ControlPlane, EngineListener, NamedTransport, RunDispatcher, RunResult, SearchAttributes, StateStore, StepError, StepInterceptor, Transport, UpdateResult, UpdateValidator, WorkflowCtx, WorkflowRun } from './interfaces';
|
|
2
2
|
import { type QueueConfig } from './queue';
|
|
3
3
|
import { type WorkflowClass, type WorkflowInputOf } from './workflow-ref';
|
|
4
4
|
type WorkflowFn = (ctx: WorkflowCtx, input: unknown) => Promise<unknown>;
|
|
@@ -6,6 +6,8 @@ type WorkflowFn = (ctx: WorkflowCtx, input: unknown) => Promise<unknown>;
|
|
|
6
6
|
export interface StartOptions {
|
|
7
7
|
/** Run-scoped tags, merged with the workflow's static `@Workflow({ tags })` onto the run. */
|
|
8
8
|
tags?: string[];
|
|
9
|
+
/** Typed, queryable run data stamped on the run (e.g. `{ amount: 200, tier: 'pro' }`). */
|
|
10
|
+
searchAttributes?: SearchAttributes;
|
|
9
11
|
}
|
|
10
12
|
/**
|
|
11
13
|
* Serialize runs of a workflow that share a key — a durable, FIFO mutex (e.g. one pipeline per base).
|
|
@@ -64,6 +66,13 @@ export interface WorkflowEngineDeps {
|
|
|
64
66
|
* hiccup — gets another try). Default 1 (no retry). Compensations must be idempotent.
|
|
65
67
|
*/
|
|
66
68
|
compensationRetries?: number;
|
|
69
|
+
/**
|
|
70
|
+
* Where a freshly-`start`ed run executes (see {@link RunDispatcher}). Defaults to in-process: the
|
|
71
|
+
* run executes on this instance asynchronously (a microtask), so `start` returns without blocking.
|
|
72
|
+
* Pass a no-op dispatcher on a caller that must NOT run workflows (e.g. an API/dashboard pod), and
|
|
73
|
+
* run `runPending` on a worker pod to pick those up; or a broker-backed one for a worker pool.
|
|
74
|
+
*/
|
|
75
|
+
runDispatcher?: RunDispatcher;
|
|
67
76
|
}
|
|
68
77
|
/**
|
|
69
78
|
* The orchestrator. Owns workflow state and replays runs deterministically: each step's
|
|
@@ -83,15 +92,21 @@ export declare class WorkflowEngine {
|
|
|
83
92
|
private readonly webhookUrl?;
|
|
84
93
|
private readonly traceparent?;
|
|
85
94
|
private readonly compensationRetries;
|
|
95
|
+
/** Where a freshly-started run executes — in-process by default (see {@link RunDispatcher}). */
|
|
96
|
+
private readonly runDispatcher;
|
|
86
97
|
/** Every registered workflow, keyed by `name@version` — so old versions stay runnable. */
|
|
87
98
|
private readonly workflows;
|
|
88
99
|
/** The newest registered version per workflow name — used to `start` new runs. */
|
|
89
100
|
private readonly latest;
|
|
101
|
+
/** Event name → workflow names started when that event is published (see `onEvent`). */
|
|
102
|
+
private readonly eventTriggers;
|
|
90
103
|
/** In-flight remote steps awaiting a worker result, keyed by stepId. */
|
|
91
104
|
private readonly pending;
|
|
92
105
|
/** Per-step "reset the liveness timer" callbacks, called when a heartbeat arrives. */
|
|
93
106
|
private readonly heartbeatResets;
|
|
94
107
|
private readonly listeners;
|
|
108
|
+
/** Step interceptors (onion middleware around real local-step execution), first = outermost. */
|
|
109
|
+
private readonly interceptors;
|
|
95
110
|
/** Callbacks notified (on any instance) when a run is cancelled — for cooperative cancellation. */
|
|
96
111
|
private readonly cancelListeners;
|
|
97
112
|
/** Notified when a run is dead-lettered (moved to `dead`) — a hook for a DLQ handler. */
|
|
@@ -119,6 +134,8 @@ export declare class WorkflowEngine {
|
|
|
119
134
|
tags?: string[];
|
|
120
135
|
singleton?: SingletonConfig;
|
|
121
136
|
executionTimeout?: string | number;
|
|
137
|
+
validateInput?: (input: unknown) => void | Promise<void>;
|
|
138
|
+
onEvent?: string[];
|
|
122
139
|
}): void;
|
|
123
140
|
/**
|
|
124
141
|
* Register a flow-control queue referenced by `ctx.call(step, input, { queue })`. Caps concurrent
|
|
@@ -128,6 +145,15 @@ export declare class WorkflowEngine {
|
|
|
128
145
|
registerQueue(config: QueueConfig): void;
|
|
129
146
|
/** Subscribe to lifecycle events. Returns an unsubscribe function. */
|
|
130
147
|
subscribe(listener: EngineListener): () => void;
|
|
148
|
+
/**
|
|
149
|
+
* Register a {@link StepInterceptor} — onion middleware run around the real execution of every
|
|
150
|
+
* local `ctx.step` (timing, logging, tracing, error enrichment, context propagation). First
|
|
151
|
+
* registered is outermost; interceptors fire only when a step executes, never on replay. Returns
|
|
152
|
+
* an unsubscribe function.
|
|
153
|
+
*/
|
|
154
|
+
use(interceptor: StepInterceptor): () => void;
|
|
155
|
+
/** Fold the registered interceptors around a local step body (identity when there are none). */
|
|
156
|
+
private interceptStep;
|
|
131
157
|
/**
|
|
132
158
|
* Be notified when a run is cancelled — on ANY instance, via the transport control plane. A
|
|
133
159
|
* worker bridge can use this for cooperative cancellation: abort the in-flight work for `runId`
|
|
@@ -184,6 +210,28 @@ export declare class WorkflowEngine {
|
|
|
184
210
|
* boot. A run still not due re-suspends cheaply without running new work.
|
|
185
211
|
*/
|
|
186
212
|
resumeDueTimers(nowMs?: number): Promise<RunResult[]>;
|
|
213
|
+
/**
|
|
214
|
+
* Lease and execute one run by id — the worker side of dispatch. Acquires the recovery lease (so
|
|
215
|
+
* exactly one instance runs it), then resumes the body. Returns the result, or null if another
|
|
216
|
+
* instance holds the lease or the engine is draining. The default in-process dispatcher calls this;
|
|
217
|
+
* a broker-backed worker calls it per consumed run id.
|
|
218
|
+
*/
|
|
219
|
+
runOne(runId: string): Promise<RunResult | null>;
|
|
220
|
+
/**
|
|
221
|
+
* Pick up and execute every `pending` run — the poll-based side of dispatch for a worker pod with
|
|
222
|
+
* no broker. Runs enqueued by other pods (or by a caller using a no-op dispatcher) sit `pending`
|
|
223
|
+
* in the store until polled; leasing ensures exactly one pod runs each. Call periodically alongside
|
|
224
|
+
* {@link resumeDueTimers}.
|
|
225
|
+
*/
|
|
226
|
+
runPending(nowMs?: number): Promise<RunResult[]>;
|
|
227
|
+
/**
|
|
228
|
+
* Resolve once `runId` reaches a settled state — terminal (completed/failed/cancelled/dead) or
|
|
229
|
+
* suspended (handed off to a timer/signal/event). The async counterpart to dispatch: pair it with
|
|
230
|
+
* `start` when a call site needs the outcome — `await start(...); const r = await waitForRun(id)`.
|
|
231
|
+
*/
|
|
232
|
+
waitForRun(runId: string, opts?: {
|
|
233
|
+
timeoutMs?: number;
|
|
234
|
+
}): Promise<RunResult>;
|
|
187
235
|
/**
|
|
188
236
|
* Resume each run only if this instance can acquire its recovery lease — so when several
|
|
189
237
|
* replicas recover or poll at once, each run is picked up by exactly one of them.
|
|
@@ -193,6 +241,17 @@ export declare class WorkflowEngine {
|
|
|
193
241
|
* Deliver an external signal to the run waiting on `token` and resume it with `payload`.
|
|
194
242
|
* Returns the run result, or null if no run is waiting for that token.
|
|
195
243
|
*/
|
|
244
|
+
/**
|
|
245
|
+
* Publish a named event. It does two things, and returns how many runs it touched (the sum):
|
|
246
|
+
* 1. **Resumes** every in-flight run waiting on it via `ctx.waitForEvent(name, { match })` whose
|
|
247
|
+
* match the payload satisfies (fan-out, vs `signal`'s point-to-point token).
|
|
248
|
+
* 2. **Starts** a fresh run of every workflow registered with `onEvent: [name]`, passing the
|
|
249
|
+
* payload as input. Idempotent by `evt:<id>:<workflow>` — pass `opts.id` to dedupe redeliveries
|
|
250
|
+
* of the same logical event (default: a fresh uuid, so each publish triggers once).
|
|
251
|
+
*/
|
|
252
|
+
publishEvent(name: string, payload: unknown, opts?: {
|
|
253
|
+
id?: string;
|
|
254
|
+
}): Promise<number>;
|
|
196
255
|
signal(token: string, payload: unknown): Promise<RunResult | null>;
|
|
197
256
|
/**
|
|
198
257
|
* Report the result of a `ctx.task(name, …)` back to its run (async completion). The external
|
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/engine.js
CHANGED
|
@@ -5,6 +5,7 @@ const backoff_1 = require("./backoff");
|
|
|
5
5
|
const checkpoints_1 = require("./checkpoints");
|
|
6
6
|
const duration_1 = require("./duration");
|
|
7
7
|
const errors_1 = require("./errors");
|
|
8
|
+
const events_1 = require("./events");
|
|
8
9
|
const protocol_1 = require("./protocol");
|
|
9
10
|
const queue_1 = require("./queue");
|
|
10
11
|
const transport_pool_1 = require("./transport-pool");
|
|
@@ -56,15 +57,21 @@ class WorkflowEngine {
|
|
|
56
57
|
webhookUrl;
|
|
57
58
|
traceparent;
|
|
58
59
|
compensationRetries;
|
|
60
|
+
/** Where a freshly-started run executes — in-process by default (see {@link RunDispatcher}). */
|
|
61
|
+
runDispatcher;
|
|
59
62
|
/** Every registered workflow, keyed by `name@version` — so old versions stay runnable. */
|
|
60
63
|
workflows = new Map();
|
|
61
64
|
/** The newest registered version per workflow name — used to `start` new runs. */
|
|
62
65
|
latest = new Map();
|
|
66
|
+
/** Event name → workflow names started when that event is published (see `onEvent`). */
|
|
67
|
+
eventTriggers = new Map();
|
|
63
68
|
/** In-flight remote steps awaiting a worker result, keyed by stepId. */
|
|
64
69
|
pending = new Map();
|
|
65
70
|
/** Per-step "reset the liveness timer" callbacks, called when a heartbeat arrives. */
|
|
66
71
|
heartbeatResets = new Map();
|
|
67
72
|
listeners = new Set();
|
|
73
|
+
/** Step interceptors (onion middleware around real local-step execution), first = outermost. */
|
|
74
|
+
interceptors = [];
|
|
68
75
|
/** Callbacks notified (on any instance) when a run is cancelled — for cooperative cancellation. */
|
|
69
76
|
cancelListeners = new Set();
|
|
70
77
|
/** Notified when a run is dead-lettered (moved to `dead`) — a hook for a DLQ handler. */
|
|
@@ -91,6 +98,12 @@ class WorkflowEngine {
|
|
|
91
98
|
this.webhookUrl = deps.webhookUrl;
|
|
92
99
|
this.traceparent = deps.traceparent;
|
|
93
100
|
this.compensationRetries = Math.max(1, deps.compensationRetries ?? 1);
|
|
101
|
+
// Default: execute the run on this instance, asynchronously, so `start` never blocks on the body.
|
|
102
|
+
// A failed pickup is swallowed here (the run stays `pending` for a `runPending` poll to retry);
|
|
103
|
+
// run failures themselves are handled inside `execute` and surfaced as the run's `failed` state.
|
|
104
|
+
this.runDispatcher = deps.runDispatcher ?? {
|
|
105
|
+
dispatch: (runId) => queueMicrotask(() => void this.runOne(runId).catch(() => { })),
|
|
106
|
+
};
|
|
94
107
|
this.pool.bind(async (result) => {
|
|
95
108
|
// In-memory path (a `timeoutMs` step awaiting on THIS instance): resolve its pending promise.
|
|
96
109
|
const waiter = this.pending.get(result.stepId);
|
|
@@ -155,11 +168,18 @@ class WorkflowEngine {
|
|
|
155
168
|
tags: opts?.tags,
|
|
156
169
|
singleton: opts?.singleton,
|
|
157
170
|
executionTimeoutMs: opts?.executionTimeout != null ? (0, duration_1.parseDuration)(opts.executionTimeout) : undefined,
|
|
171
|
+
validateInput: opts?.validateInput,
|
|
172
|
+
onEvent: opts?.onEvent,
|
|
158
173
|
};
|
|
159
174
|
this.workflows.set(versionKey(name, version), registered);
|
|
160
175
|
const current = this.latest.get(name);
|
|
161
176
|
if (!current || isNewerVersion(version, current.version))
|
|
162
177
|
this.latest.set(name, registered);
|
|
178
|
+
for (const event of opts?.onEvent ?? []) {
|
|
179
|
+
const subscribers = this.eventTriggers.get(event) ?? new Set();
|
|
180
|
+
subscribers.add(name);
|
|
181
|
+
this.eventTriggers.set(event, subscribers);
|
|
182
|
+
}
|
|
163
183
|
}
|
|
164
184
|
/**
|
|
165
185
|
* Register a flow-control queue referenced by `ctx.call(step, input, { queue })`. Caps concurrent
|
|
@@ -174,6 +194,27 @@ class WorkflowEngine {
|
|
|
174
194
|
this.listeners.add(listener);
|
|
175
195
|
return () => this.listeners.delete(listener);
|
|
176
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* Register a {@link StepInterceptor} — onion middleware run around the real execution of every
|
|
199
|
+
* local `ctx.step` (timing, logging, tracing, error enrichment, context propagation). First
|
|
200
|
+
* registered is outermost; interceptors fire only when a step executes, never on replay. Returns
|
|
201
|
+
* an unsubscribe function.
|
|
202
|
+
*/
|
|
203
|
+
use(interceptor) {
|
|
204
|
+
this.interceptors.push(interceptor);
|
|
205
|
+
return () => {
|
|
206
|
+
const i = this.interceptors.indexOf(interceptor);
|
|
207
|
+
if (i >= 0)
|
|
208
|
+
this.interceptors.splice(i, 1);
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
/** Fold the registered interceptors around a local step body (identity when there are none). */
|
|
212
|
+
interceptStep(invocation, body) {
|
|
213
|
+
if (this.interceptors.length === 0)
|
|
214
|
+
return body();
|
|
215
|
+
const chain = this.interceptors.reduceRight((next, interceptor) => () => interceptor(invocation, next), body);
|
|
216
|
+
return chain();
|
|
217
|
+
}
|
|
177
218
|
/**
|
|
178
219
|
* Be notified when a run is cancelled — on ANY instance, via the transport control plane. A
|
|
179
220
|
* worker bridge can use this for cooperative cancellation: abort the in-flight work for `runId`
|
|
@@ -234,6 +275,8 @@ class WorkflowEngine {
|
|
|
234
275
|
const registered = this.latest.get(name);
|
|
235
276
|
if (!registered)
|
|
236
277
|
throw new Error(`workflow ${name} is not registered`);
|
|
278
|
+
// Validate the input up front — a bad payload is rejected before any run is created.
|
|
279
|
+
await registered.validateInput?.(input);
|
|
237
280
|
// Idempotent by run id: a redelivered trigger (at-least-once queues) or a scheduler re-tick for
|
|
238
281
|
// the same id is a no-op, returning the existing run's state instead of starting a duplicate.
|
|
239
282
|
const prior = await this.store.getRun(runId);
|
|
@@ -250,15 +293,18 @@ class WorkflowEngine {
|
|
|
250
293
|
id: runId,
|
|
251
294
|
workflow: name,
|
|
252
295
|
workflowVersion: registered.version,
|
|
253
|
-
status: '
|
|
296
|
+
status: 'pending',
|
|
254
297
|
input,
|
|
255
298
|
tags,
|
|
299
|
+
searchAttributes: opts?.searchAttributes,
|
|
256
300
|
createdAt: now,
|
|
257
301
|
updatedAt: now,
|
|
258
302
|
};
|
|
259
303
|
await this.store.createRun(run);
|
|
260
|
-
|
|
261
|
-
|
|
304
|
+
// The run is durably enqueued; a dispatcher (in-process by default) executes it — `start` does
|
|
305
|
+
// NOT run the body inline. Await the terminal/suspended state with `waitForRun(runId)` if needed.
|
|
306
|
+
await this.runDispatcher.dispatch(runId);
|
|
307
|
+
return { runId, status: 'pending' };
|
|
262
308
|
}
|
|
263
309
|
/** Read a run's current persisted state (or null if unknown). A thin pass-through to the store. */
|
|
264
310
|
getRun(runId) {
|
|
@@ -362,6 +408,83 @@ class WorkflowEngine {
|
|
|
362
408
|
async resumeDueTimers(nowMs = this.clock()) {
|
|
363
409
|
return this.resumeLeased(await this.store.listDueTimers(nowMs), nowMs);
|
|
364
410
|
}
|
|
411
|
+
/**
|
|
412
|
+
* Lease and execute one run by id — the worker side of dispatch. Acquires the recovery lease (so
|
|
413
|
+
* exactly one instance runs it), then resumes the body. Returns the result, or null if another
|
|
414
|
+
* instance holds the lease or the engine is draining. The default in-process dispatcher calls this;
|
|
415
|
+
* a broker-backed worker calls it per consumed run id.
|
|
416
|
+
*/
|
|
417
|
+
async runOne(runId) {
|
|
418
|
+
if (this.draining)
|
|
419
|
+
return null;
|
|
420
|
+
const nowMs = this.clock();
|
|
421
|
+
const acquired = await this.store.tryLockRun(runId, this.instanceId, nowMs + this.leaseMs, nowMs);
|
|
422
|
+
if (!acquired)
|
|
423
|
+
return null;
|
|
424
|
+
return this.resume(runId);
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Pick up and execute every `pending` run — the poll-based side of dispatch for a worker pod with
|
|
428
|
+
* no broker. Runs enqueued by other pods (or by a caller using a no-op dispatcher) sit `pending`
|
|
429
|
+
* in the store until polled; leasing ensures exactly one pod runs each. Call periodically alongside
|
|
430
|
+
* {@link resumeDueTimers}.
|
|
431
|
+
*/
|
|
432
|
+
async runPending(nowMs = this.clock()) {
|
|
433
|
+
// Oldest-first (FIFO), capped per call so a backlog drains over several polls without one sweep
|
|
434
|
+
// fetching unboundedly. A run not picked up this tick is picked up the next.
|
|
435
|
+
return this.resumeLeased(await this.store.listPendingRuns(100), nowMs);
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Resolve once `runId` reaches a settled state — terminal (completed/failed/cancelled/dead) or
|
|
439
|
+
* suspended (handed off to a timer/signal/event). The async counterpart to dispatch: pair it with
|
|
440
|
+
* `start` when a call site needs the outcome — `await start(...); const r = await waitForRun(id)`.
|
|
441
|
+
*/
|
|
442
|
+
waitForRun(runId, opts) {
|
|
443
|
+
const isSettled = (s) => s !== 'pending' && s !== 'running';
|
|
444
|
+
const toResult = (run) => ({
|
|
445
|
+
runId,
|
|
446
|
+
status: run.status,
|
|
447
|
+
output: run.output,
|
|
448
|
+
error: run.error,
|
|
449
|
+
});
|
|
450
|
+
return new Promise((resolve, reject) => {
|
|
451
|
+
let done = false;
|
|
452
|
+
let off = () => { };
|
|
453
|
+
const timer = opts?.timeoutMs != null
|
|
454
|
+
? setTimeout(() => {
|
|
455
|
+
if (done)
|
|
456
|
+
return;
|
|
457
|
+
done = true;
|
|
458
|
+
off();
|
|
459
|
+
reject(new Error(`waitForRun(${runId}) timed out after ${opts.timeoutMs}ms`));
|
|
460
|
+
}, opts.timeoutMs)
|
|
461
|
+
: undefined;
|
|
462
|
+
const finish = (run) => {
|
|
463
|
+
if (done)
|
|
464
|
+
return;
|
|
465
|
+
done = true;
|
|
466
|
+
if (timer)
|
|
467
|
+
clearTimeout(timer);
|
|
468
|
+
off();
|
|
469
|
+
resolve(toResult(run));
|
|
470
|
+
};
|
|
471
|
+
const check = () => {
|
|
472
|
+
void this.store.getRun(runId).then((run) => {
|
|
473
|
+
if (run && isSettled(run.status))
|
|
474
|
+
finish(run);
|
|
475
|
+
});
|
|
476
|
+
};
|
|
477
|
+
// React only to this run's settling events (not its every step event), and subscribe BEFORE the
|
|
478
|
+
// initial read so a run that settles in between isn't missed.
|
|
479
|
+
off = this.subscribe((ev) => {
|
|
480
|
+
if (ev.runId === runId &&
|
|
481
|
+
(ev.type === 'run.completed' || ev.type === 'run.failed' || ev.type === 'run.suspended')) {
|
|
482
|
+
check();
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
check();
|
|
486
|
+
});
|
|
487
|
+
}
|
|
365
488
|
/**
|
|
366
489
|
* Resume each run only if this instance can acquire its recovery lease — so when several
|
|
367
490
|
* replicas recover or poll at once, each run is picked up by exactly one of them.
|
|
@@ -384,6 +507,40 @@ class WorkflowEngine {
|
|
|
384
507
|
* Deliver an external signal to the run waiting on `token` and resume it with `payload`.
|
|
385
508
|
* Returns the run result, or null if no run is waiting for that token.
|
|
386
509
|
*/
|
|
510
|
+
/**
|
|
511
|
+
* Publish a named event. It does two things, and returns how many runs it touched (the sum):
|
|
512
|
+
* 1. **Resumes** every in-flight run waiting on it via `ctx.waitForEvent(name, { match })` whose
|
|
513
|
+
* match the payload satisfies (fan-out, vs `signal`'s point-to-point token).
|
|
514
|
+
* 2. **Starts** a fresh run of every workflow registered with `onEvent: [name]`, passing the
|
|
515
|
+
* payload as input. Idempotent by `evt:<id>:<workflow>` — pass `opts.id` to dedupe redeliveries
|
|
516
|
+
* of the same logical event (default: a fresh uuid, so each publish triggers once).
|
|
517
|
+
*/
|
|
518
|
+
async publishEvent(name, payload, opts) {
|
|
519
|
+
let touched = 0;
|
|
520
|
+
const waiters = await this.store.listSignalWaiters((0, events_1.eventPrefix)(name));
|
|
521
|
+
for (const w of waiters) {
|
|
522
|
+
if ((0, events_1.eventMatches)(payload, (0, events_1.eventMatchOf)(w.token))) {
|
|
523
|
+
await this.signal(w.token, payload);
|
|
524
|
+
touched += 1;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
const subscribers = this.eventTriggers.get(name);
|
|
528
|
+
if (subscribers?.size) {
|
|
529
|
+
const eventId = opts?.id ?? globalThis.crypto.randomUUID();
|
|
530
|
+
for (const workflow of subscribers) {
|
|
531
|
+
// A subscriber that rejects the payload (validateInput) must not block the others or the
|
|
532
|
+
// waiters — its run simply never starts, mirroring fire-and-forget dead-letter routing.
|
|
533
|
+
try {
|
|
534
|
+
await this.start(workflow, payload, `evt:${eventId}:${workflow}`);
|
|
535
|
+
touched += 1;
|
|
536
|
+
}
|
|
537
|
+
catch {
|
|
538
|
+
// skip this subscriber
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
return touched;
|
|
543
|
+
}
|
|
387
544
|
async signal(token, payload) {
|
|
388
545
|
const waiter = await this.store.takeSignalWaiter(token);
|
|
389
546
|
if (!waiter)
|
|
@@ -530,9 +687,17 @@ class WorkflowEngine {
|
|
|
530
687
|
return idx >= 0 && idx < (cfg.limit ?? 1);
|
|
531
688
|
}
|
|
532
689
|
async execute(run, fn) {
|
|
690
|
+
const registered = this.workflows.get(versionKey(run.workflow, run.workflowVersion));
|
|
691
|
+
// First execution of an enqueued run: mark it running and announce the start, BEFORE the singleton
|
|
692
|
+
// gate — `admitSingleton` only counts `running`/`suspended` runs, so a still-`pending` run could
|
|
693
|
+
// never be admitted. A resumed run is already past `pending`, so this fires exactly once.
|
|
694
|
+
if (run.status === 'pending') {
|
|
695
|
+
await this.store.updateRun(run.id, { status: 'running', updatedAt: new Date() });
|
|
696
|
+
run.status = 'running';
|
|
697
|
+
this.emit({ type: 'run.started', runId: run.id, workflow: run.workflow });
|
|
698
|
+
}
|
|
533
699
|
// Singleton admission gate: if this run shares its key with `limit` older in-flight runs, wait
|
|
534
700
|
// (suspend on a short timer) until a slot frees instead of running now. Re-checked on each resume.
|
|
535
|
-
const registered = this.workflows.get(versionKey(run.workflow, run.workflowVersion));
|
|
536
701
|
if (registered?.singleton && !(await this.admitSingleton(run, registered.singleton))) {
|
|
537
702
|
const wakeAt = this.clock() + SINGLETON_RETRY_MS;
|
|
538
703
|
await this.store.updateRun(run.id, { status: 'suspended', wakeAt, updatedAt: new Date() });
|
|
@@ -542,7 +707,7 @@ class WorkflowEngine {
|
|
|
542
707
|
}
|
|
543
708
|
// Saga compensations registered by completed steps; run in reverse if the run later fails.
|
|
544
709
|
const compensations = [];
|
|
545
|
-
const ctx = (0, workflow_ctx_1.createWorkflowCtx)(this.ctxHost, run.id, compensations);
|
|
710
|
+
const ctx = (0, workflow_ctx_1.createWorkflowCtx)(this.ctxHost, run.id, compensations, run.workflow);
|
|
546
711
|
try {
|
|
547
712
|
const output = await fn(ctx, run.input);
|
|
548
713
|
// Clear any error from an earlier failed-then-retried attempt: a completed run is a success
|
|
@@ -674,6 +839,7 @@ class WorkflowEngine {
|
|
|
674
839
|
startChild: (workflow, input, id) => {
|
|
675
840
|
queueMicrotask(() => void this.start(workflow, input, id).catch(() => undefined));
|
|
676
841
|
},
|
|
842
|
+
interceptStep: (invocation, body) => this.interceptStep(invocation, body),
|
|
677
843
|
};
|
|
678
844
|
}
|
|
679
845
|
/**
|