@dudousxd/nestjs-durable-core 0.44.1 → 0.46.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/index.cjs +214 -58
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +373 -73
- package/dist/index.d.ts +373 -73
- package/dist/index.js +208 -57
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Flow control for
|
|
4
|
+
* Flow control for dispatched steps. A queue caps how much work `ctx.step(step, input, { queue })`
|
|
5
5
|
* admits at once — a concurrency limit and/or a fixed-window rate limit. When a call can't be
|
|
6
6
|
* admitted it doesn't dispatch: the run re-suspends with a near-future wake time, and the timer
|
|
7
7
|
* poller re-tries admission later — so flow control is durable (survives crashes) without holding
|
|
@@ -25,7 +25,7 @@ import { z } from 'zod';
|
|
|
25
25
|
* blocked, and on a later retry only admits the one that is rightful-next under the policy.
|
|
26
26
|
*/
|
|
27
27
|
interface QueueConfig {
|
|
28
|
-
/** Queue name, referenced by `ctx.
|
|
28
|
+
/** Queue name, referenced by `ctx.step(step, input, { queue: name })`. */
|
|
29
29
|
name: string;
|
|
30
30
|
/** Max steps in flight at once for this queue (this instance). Omit for unlimited. */
|
|
31
31
|
concurrency?: number;
|
|
@@ -114,7 +114,7 @@ declare class QueueController {
|
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
/**
|
|
117
|
-
* Pluggable backend for the
|
|
117
|
+
* Pluggable backend for the step flow-control gate (`ctx.step(step, input, { queue })`). The
|
|
118
118
|
* engine asks it whether a queued call may be admitted now (concurrency / rate / ordering) and tells
|
|
119
119
|
* it when an admitted slot is released.
|
|
120
120
|
*
|
|
@@ -167,6 +167,69 @@ declare class InMemoryAdmissionBackend implements AdmissionBackend {
|
|
|
167
167
|
*/
|
|
168
168
|
declare function parseDuration(duration: string | number): number;
|
|
169
169
|
|
|
170
|
+
/**
|
|
171
|
+
* Cross-package step-name stamp. The `@Step` decorator (`@dudousxd/nestjs-durable`) writes a
|
|
172
|
+
* method's derived routing name under this key; core's `ctx.step` reads it (via {@link stepNameOf})
|
|
173
|
+
* to route a method-reference call to the same handler a worker registers by name.
|
|
174
|
+
*
|
|
175
|
+
* `Symbol.for` (the GLOBAL registry), NOT a plain `Symbol()` — so a duplicate copy of this module
|
|
176
|
+
* (pnpm peer-dependency multiplexing, or a dual ESM/CJS load) still reads the SAME key. A plain
|
|
177
|
+
* `Symbol()` would mint a distinct token per copy, so a decorator running against one core instance
|
|
178
|
+
* could stamp a name core's `ctx.step` (a different instance) can never read back. Mirrors the
|
|
179
|
+
* `STATE_STORE` token fix in `./tokens.ts`.
|
|
180
|
+
*/
|
|
181
|
+
declare const DURABLE_STEP_NAME: unique symbol;
|
|
182
|
+
/**
|
|
183
|
+
* Cross-package step-DISPATCH-POLICY stamp. `@Step({ retries, backoff, backoffMs, backoffMaxMs,
|
|
184
|
+
* jitter, timeoutMs })` (`@dudousxd/nestjs-durable`) writes the def-level durable-retry/liveness
|
|
185
|
+
* policy under this key; core's `ctx.step` reads it (via {@link stepConfigOf}) and merges it with any
|
|
186
|
+
* per-call {@link StepDispatchOpts} override to build the dispatched {@link StepDef}. Same
|
|
187
|
+
* `Symbol.for` rationale as {@link DURABLE_STEP_NAME} — a duplicate copy of this module (pnpm
|
|
188
|
+
* peer-dependency multiplexing, dual ESM/CJS) must still read back the SAME key.
|
|
189
|
+
*/
|
|
190
|
+
declare const DURABLE_STEP_CONFIG: unique symbol;
|
|
191
|
+
/**
|
|
192
|
+
* The def-level durable-dispatch policy a `@Step(...)` can stamp on a method: retry/backoff and the
|
|
193
|
+
* remote-liveness `timeoutMs` — the dispatch-relevant subset of the engine's `StepOptions`. Read off
|
|
194
|
+
* a handler reference via {@link stepConfigOf}; a per-call {@link StepDispatchOpts} passed to
|
|
195
|
+
* `ctx.step(ref, input, opts)` overrides these field-by-field.
|
|
196
|
+
*/
|
|
197
|
+
interface StepConfig {
|
|
198
|
+
/** Max attempts before the step (and run) fails. */
|
|
199
|
+
retries?: number | undefined;
|
|
200
|
+
/** How the delay between retries grows: `fixed` (constant) or `exp` (doubles each attempt). */
|
|
201
|
+
backoff?: 'fixed' | 'exp' | undefined;
|
|
202
|
+
/** Base delay in ms between retries. Omit (or 0) to retry with no delay. */
|
|
203
|
+
backoffMs?: number | undefined;
|
|
204
|
+
/** Upper bound on the (exponential) backoff delay. */
|
|
205
|
+
backoffMaxMs?: number | undefined;
|
|
206
|
+
/** Add random jitter (50–100% of the computed delay) to avoid thundering-herd retries. */
|
|
207
|
+
jitter?: boolean | undefined;
|
|
208
|
+
/** Liveness window for the dispatched step: no result/heartbeat within this many ms presumes the
|
|
209
|
+
* worker dead and fails the dispatch with a `RemoteStepTimeout` (retryable — re-dispatches per
|
|
210
|
+
* `retries`). Omit to wait indefinitely. */
|
|
211
|
+
timeoutMs?: number | undefined;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* A method carrying its `@Step`-stamped routing name (and, optionally, its dispatch policy).
|
|
215
|
+
* `ctx.step(ref, input)` reads the name via {@link stepNameOf} — the reference itself is never
|
|
216
|
+
* invoked directly by the caller's process (the worker serving that name re-resolves the real
|
|
217
|
+
* handler from DI), so an unbound `this` on `ref` is irrelevant; `ref` is purely a typed,
|
|
218
|
+
* refactor-safe handle onto the stamped name (and policy).
|
|
219
|
+
*/
|
|
220
|
+
type StepRef<TInput = unknown, TOutput = unknown> = ((input: TInput) => Promise<TOutput> | TOutput) & {
|
|
221
|
+
[DURABLE_STEP_NAME]?: string | undefined;
|
|
222
|
+
[DURABLE_STEP_CONFIG]?: StepConfig | undefined;
|
|
223
|
+
};
|
|
224
|
+
/** Read the `@Step`-stamped routing name off a function ref. `undefined` for anything unstamped
|
|
225
|
+
* (including a plain string — {@link stepNameOf} only reads function refs; a caller passing a
|
|
226
|
+
* string already has the routing name and dispatches it directly). */
|
|
227
|
+
declare function stepNameOf(ref: unknown): string | undefined;
|
|
228
|
+
/** Read the `@Step`-stamped dispatch policy off a function ref. `undefined` for anything unstamped
|
|
229
|
+
* (including a plain string — a cross-runtime string-name call has no def-level policy to read; pass
|
|
230
|
+
* it via {@link StepDispatchOpts} instead). */
|
|
231
|
+
declare function stepConfigOf(ref: unknown): StepConfig | undefined;
|
|
232
|
+
|
|
170
233
|
/**
|
|
171
234
|
* A **workflow reference** is how one workflow names another to call it: either a registered workflow
|
|
172
235
|
* **name** (a string — the only option across runtimes, e.g. a Python workflow) or, for a same-runtime
|
|
@@ -297,7 +360,7 @@ interface StepCheckpoint {
|
|
|
297
360
|
* simply re-runs on replay (only `completed` short-circuits).
|
|
298
361
|
*/
|
|
299
362
|
status: 'pending' | 'running' | 'completed' | 'failed';
|
|
300
|
-
/** What the step was called with — the `ctx.
|
|
363
|
+
/** What the step was called with — the `ctx.step` (dispatched) args for a remote step (a local step has none). */
|
|
301
364
|
input?: unknown;
|
|
302
365
|
output?: unknown;
|
|
303
366
|
error?: StepError | undefined;
|
|
@@ -594,6 +657,85 @@ interface SignalWaiter {
|
|
|
594
657
|
*/
|
|
595
658
|
parallelGroup?: string | undefined;
|
|
596
659
|
}
|
|
660
|
+
/**
|
|
661
|
+
* A DB-less tenant worker → control plane request to start a run. Published by a worker that has
|
|
662
|
+
* no direct DB access (the hosted-control-plane tenant model) onto the
|
|
663
|
+
* `<effectivePrefix>-start-run` queue; the control plane consumes it and turns it into a durable
|
|
664
|
+
* run (P4 of the tenants plan).
|
|
665
|
+
*
|
|
666
|
+
* The `tenant` identifies the namespace that owns the run (maps to the engine's `namespace`); it
|
|
667
|
+
* is separate from the wire-level key prefix so a single transport can serve multiple tenants.
|
|
668
|
+
*/
|
|
669
|
+
interface StartRunMessage {
|
|
670
|
+
tenant: string;
|
|
671
|
+
/** Registered workflow name. */
|
|
672
|
+
workflow: string;
|
|
673
|
+
input: unknown;
|
|
674
|
+
/** Optional caller-supplied run id (idempotency key). The engine generates one if absent. */
|
|
675
|
+
runId?: string | undefined;
|
|
676
|
+
/** Tags to stamp on the run (merged with the workflow's static @Workflow tags). */
|
|
677
|
+
tags?: string[] | undefined;
|
|
678
|
+
/** Typed, queryable run data to stamp on the run (same as {@link StartOptions.searchAttributes}). */
|
|
679
|
+
searchAttributes?: SearchAttributes | undefined;
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* A tenant worker → control plane read/control request over the shared transport. Enqueued on
|
|
683
|
+
* `<effectivePrefix>-run-request`; the control plane's `onRunRequest` consumer answers it, scoped to
|
|
684
|
+
* `tenant`, and publishes a {@link RunReply} on `<effectivePrefix>-run-reply` correlated by `requestId`.
|
|
685
|
+
*/
|
|
686
|
+
interface RunRequest {
|
|
687
|
+
/** Correlation id minted by the tenant; the matching {@link RunReply} carries it back. */
|
|
688
|
+
requestId: string;
|
|
689
|
+
/** The requesting tenant — the operator scopes the run's namespace to this. */
|
|
690
|
+
tenant: string;
|
|
691
|
+
body: RunRequestKind;
|
|
692
|
+
}
|
|
693
|
+
/** The discriminated verb + args of a {@link RunRequest}. Mirrors the tenant-facing `RunGateway`. */
|
|
694
|
+
type RunRequestKind = {
|
|
695
|
+
kind: 'getRunDetail';
|
|
696
|
+
runId: string;
|
|
697
|
+
} | {
|
|
698
|
+
kind: 'listRuns';
|
|
699
|
+
query: RunQuery;
|
|
700
|
+
} | {
|
|
701
|
+
kind: 'cancel';
|
|
702
|
+
runId: string;
|
|
703
|
+
opts?: {
|
|
704
|
+
compensate?: boolean;
|
|
705
|
+
};
|
|
706
|
+
} | {
|
|
707
|
+
kind: 'retry';
|
|
708
|
+
runId: string;
|
|
709
|
+
} | {
|
|
710
|
+
kind: 'continue';
|
|
711
|
+
runId: string;
|
|
712
|
+
} | {
|
|
713
|
+
kind: 'retryWithInput';
|
|
714
|
+
runId: string;
|
|
715
|
+
input: unknown;
|
|
716
|
+
};
|
|
717
|
+
/** The control plane's answer to a {@link RunRequest}, correlated by `requestId`. */
|
|
718
|
+
interface RunReply {
|
|
719
|
+
requestId: string;
|
|
720
|
+
result: RunReplyResult;
|
|
721
|
+
}
|
|
722
|
+
/** Success carries the verb's payload (JSON-serialised); failure carries a re-throwable error. */
|
|
723
|
+
type RunReplyResult = {
|
|
724
|
+
ok: true;
|
|
725
|
+
data: unknown;
|
|
726
|
+
} | {
|
|
727
|
+
ok: false;
|
|
728
|
+
error: {
|
|
729
|
+
message: string;
|
|
730
|
+
code?: string;
|
|
731
|
+
};
|
|
732
|
+
};
|
|
733
|
+
/** A lifecycle event re-published to a single tenant's channel (`<effectivePrefix>-tenant-events-<tenant>`)
|
|
734
|
+
* so a store-less tenant can live-tail ITS OWN runs. Scoped by the run's namespace at publish time. */
|
|
735
|
+
interface TenantEvent {
|
|
736
|
+
tenant: string;
|
|
737
|
+
event: EngineEvent;
|
|
738
|
+
}
|
|
597
739
|
/** A unit of work dispatched to a remote worker. This is the documented wire payload. */
|
|
598
740
|
interface RemoteTask {
|
|
599
741
|
runId: string;
|
|
@@ -622,7 +764,7 @@ interface RemoteTask {
|
|
|
622
764
|
/**
|
|
623
765
|
* Admission priority carried through to the broker (BullMQ job `priority`) so a transport that
|
|
624
766
|
* supports priority ordering lets an urgent task jump ahead of already-enqueued lower-priority
|
|
625
|
-
* ones at the worker. Mirrors the per-call `priority` from `ctx.
|
|
767
|
+
* ones at the worker. Mirrors the per-call `priority` from `ctx.step(..., { priority })`. Higher
|
|
626
768
|
* wins; absent means default/unprioritised. Transports without priority support ignore it.
|
|
627
769
|
*/
|
|
628
770
|
priority?: number | undefined;
|
|
@@ -693,10 +835,10 @@ interface HistoryEvent {
|
|
|
693
835
|
}
|
|
694
836
|
/** A decision the workflow function produced at a `seq` that was not yet in history. */
|
|
695
837
|
type WorkflowCommand =
|
|
696
|
-
/** `ctx.
|
|
697
|
-
* `ctx.gather_calls([...])` fan-out tags every dispatched call with the same
|
|
698
|
-
* dashboard renders the
|
|
699
|
-
* `startChild` tags). Undefined for a lone sequential `ctx.
|
|
838
|
+
/** `ctx.step(handlerOrName, input)` — dispatch a step (by typed handler reference or by name) and
|
|
839
|
+
* await it. A worker's `ctx.gather_calls([...])` fan-out tags every dispatched call with the same
|
|
840
|
+
* `parallelGroup` so the dashboard renders the dispatched steps as one parallel fan (parity with
|
|
841
|
+
* the gathered `recordStep` / `startChild` tags). Undefined for a lone sequential `ctx.step`. */
|
|
700
842
|
{
|
|
701
843
|
kind: 'call';
|
|
702
844
|
seq: number;
|
|
@@ -816,7 +958,7 @@ interface WorkflowExecutor {
|
|
|
816
958
|
}
|
|
817
959
|
/**
|
|
818
960
|
* A transport in an ordered pool, identified by `id`. The engine dispatches on the first by default
|
|
819
|
-
* and fails over to the next on a dispatch error; a step can pin one via `ctx.
|
|
961
|
+
* and fails over to the next on a dispatch error; a step can pin one via `ctx.step(…, { transport })`.
|
|
820
962
|
* The chosen `id` is stamped on the {@link RemoteTask} so a worker replies through the matching one.
|
|
821
963
|
*/
|
|
822
964
|
interface NamedTransport {
|
|
@@ -840,6 +982,13 @@ interface Transport {
|
|
|
840
982
|
onResult(handler: (result: StepResult) => Promise<void>): void;
|
|
841
983
|
/** worker → engine: liveness signal for an in-flight long step. */
|
|
842
984
|
onHeartbeat(handler: (beat: Heartbeat) => Promise<void>): void;
|
|
985
|
+
/**
|
|
986
|
+
* Partition this transport's queues/keys by `namespace` (matching the engine's store namespace), so
|
|
987
|
+
* multiple logical deployments can share one broker. Idempotent. An explicit namespace passed to the
|
|
988
|
+
* transport's constructor TAKES PRECEDENCE over this. No-op when `namespace === "default"`. Optional —
|
|
989
|
+
* transports that don't partition simply omit it.
|
|
990
|
+
*/
|
|
991
|
+
useNamespace?(namespace: string): void;
|
|
843
992
|
/** Release the transport's resources (broker workers, queues, connections) for a clean shutdown.
|
|
844
993
|
* Optional — an in-process transport has nothing to close. Called on `onApplicationShutdown`
|
|
845
994
|
* after the engine drains, so a deploy hands off instead of leaving the broker to time out. */
|
|
@@ -864,6 +1013,35 @@ interface Transport {
|
|
|
864
1013
|
* keyspace, so a group with workers but no engine-side registration (e.g. a local-step group)
|
|
865
1014
|
* still surfaces. Pairs with {@link groupHealth}. */
|
|
866
1015
|
listWorkerGroups?(): Promise<string[]>;
|
|
1016
|
+
/**
|
|
1017
|
+
* DB-less tenant worker → control plane: publish a {@link StartRunMessage} requesting a new run.
|
|
1018
|
+
* Optional — only transports that carry the hosted-control-plane protocol (P4) implement this.
|
|
1019
|
+
* The message is enqueued on `<effectivePrefix>-start-run`; the control plane's
|
|
1020
|
+
* `onStartRun` consumer turns it into a durable run.
|
|
1021
|
+
*/
|
|
1022
|
+
dispatchStartRun?(msg: StartRunMessage): Promise<void>;
|
|
1023
|
+
/**
|
|
1024
|
+
* control plane ← tenant worker: consume {@link StartRunMessage}s and start runs. Pair with
|
|
1025
|
+
* {@link dispatchStartRun}. Optional — only control-plane-side transports implement this.
|
|
1026
|
+
*/
|
|
1027
|
+
onStartRun?(handler: (msg: StartRunMessage) => Promise<void>): void;
|
|
1028
|
+
/**
|
|
1029
|
+
* Tenant worker → control plane: publish a {@link RunRequest} (read/control) on
|
|
1030
|
+
* `<effectivePrefix>-run-request`. Optional — only broker transports carry it.
|
|
1031
|
+
*/
|
|
1032
|
+
dispatchRunRequest?(msg: RunRequest): Promise<void>;
|
|
1033
|
+
/** control plane ← tenant worker: consume {@link RunRequest}s. Pair with {@link dispatchRunRequest}. */
|
|
1034
|
+
onRunRequest?(handler: (msg: RunRequest) => Promise<void>): void;
|
|
1035
|
+
/** control plane → tenant worker: publish a correlated {@link RunReply} on `<effectivePrefix>-run-reply`
|
|
1036
|
+
* (pub/sub; every tenant subscribes and filters by `requestId`). */
|
|
1037
|
+
publishRunReply?(reply: RunReply): Promise<void>;
|
|
1038
|
+
/** tenant worker ← control plane: consume {@link RunReply}s (filter by `requestId` client-side). */
|
|
1039
|
+
onRunReply?(handler: (reply: RunReply) => void): void;
|
|
1040
|
+
/** control plane → tenant worker: re-publish a lifecycle {@link TenantEvent} on the run's per-tenant
|
|
1041
|
+
* channel `<effectivePrefix>-tenant-events-<tenant>`. */
|
|
1042
|
+
publishTenantEvent?(evt: TenantEvent): Promise<void>;
|
|
1043
|
+
/** tenant worker ← control plane: subscribe to THIS tenant's event channel. Returns an unsubscribe fn. */
|
|
1044
|
+
onTenantEvent?(tenant: string, handler: (evt: TenantEvent) => void): () => void;
|
|
867
1045
|
}
|
|
868
1046
|
/** How a worker decides its concurrency, carried in {@link WorkerStatus} so a dashboard can tell a
|
|
869
1047
|
* fixed knob from a self-regulating one (and, for the latter, where the controller currently sits). */
|
|
@@ -997,10 +1175,10 @@ interface StepOptions {
|
|
|
997
1175
|
/** Add random jitter (50–100% of the computed delay) to avoid thundering-herd retries. */
|
|
998
1176
|
jitter?: boolean;
|
|
999
1177
|
/**
|
|
1000
|
-
* Liveness window for a
|
|
1178
|
+
* Liveness window for a dispatched step (`ctx.step`): if the worker produces no result and no
|
|
1001
1179
|
* heartbeat within this many ms, the engine presumes it dead and fails the dispatch with a
|
|
1002
1180
|
* `RemoteStepTimeout` (retryable — it re-dispatches per `retries`). Each heartbeat resets the
|
|
1003
|
-
* window.
|
|
1181
|
+
* window. Omit to wait indefinitely.
|
|
1004
1182
|
*/
|
|
1005
1183
|
timeoutMs?: number;
|
|
1006
1184
|
/**
|
|
@@ -1012,17 +1190,22 @@ interface StepOptions {
|
|
|
1012
1190
|
compensate?: () => Promise<void>;
|
|
1013
1191
|
}
|
|
1014
1192
|
/**
|
|
1015
|
-
*
|
|
1016
|
-
* the worker registers a handler under the same name
|
|
1193
|
+
* The structural carrier a dispatched `ctx.step` call resolves to and hands the engine: `name` is
|
|
1194
|
+
* the routing contract (the worker registers a handler under the same name, and routing is BY that
|
|
1195
|
+
* name — a worker subscribes per registered handler name, not a hand-declared group). There is no
|
|
1196
|
+
* public factory for this anymore — a `ctx.step(ref, input)` call builds one internally from the
|
|
1197
|
+
* `@Step`-stamped name (see {@link StepRef}/`stepNameOf`); a `ctx.step(name, input)` call builds one
|
|
1198
|
+
* from the literal string. `input`/`output` are optional runtime zod schemas an authoring layer MAY
|
|
1199
|
+
* attach (e.g. `@Step({ input, output })`) for validation at the dispatch boundary — a bare `@Step()`
|
|
1200
|
+
* carries neither, and the engine skips validation when they're absent.
|
|
1017
1201
|
*/
|
|
1018
|
-
interface
|
|
1202
|
+
interface StepDef<TInput = unknown, TOutput = unknown> extends StepOptions {
|
|
1019
1203
|
name: string;
|
|
1020
|
-
/**
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
readonly __remote: true;
|
|
1204
|
+
/** Optional isolation partition; routing is by `name`. Suffixes the routing token as
|
|
1205
|
+
* `<name>@<partition>` (via {@link tenantGroup}) — omit to route by the bare (sanitized) `name`. */
|
|
1206
|
+
partition?: string | undefined;
|
|
1207
|
+
input?: z.ZodType<TInput> | undefined;
|
|
1208
|
+
output?: z.ZodType<TOutput> | undefined;
|
|
1026
1209
|
}
|
|
1027
1210
|
/**
|
|
1028
1211
|
* A durable webhook handle minted by {@link WorkflowCtx.webhook}. Hand `url` to a third party,
|
|
@@ -1041,6 +1224,45 @@ interface DurableWebhook<TPayload = unknown> {
|
|
|
1041
1224
|
/** Suspend until the callback arrives, then resume with its payload. */
|
|
1042
1225
|
wait(): Promise<TPayload>;
|
|
1043
1226
|
}
|
|
1227
|
+
/**
|
|
1228
|
+
* Options for a dispatched {@link WorkflowCtx.step} call. `retries`/`backoff`/`backoffMs`/
|
|
1229
|
+
* `backoffMaxMs`/`jitter`/`timeoutMs` are a PER-CALL override of the `@Step`-declared
|
|
1230
|
+
* {@link StepConfig} (see `stepConfigOf`) — the effective policy `ctx.step` builds into the dispatched
|
|
1231
|
+
* {@link StepDef} is `{ ...stepConfigOf(ref), ...opts }`, so a call-site value wins field-by-field. The
|
|
1232
|
+
* string (cross-runtime) form of `ctx.step` has no stamped `@Step` to read, so it uses these fields
|
|
1233
|
+
* as-is.
|
|
1234
|
+
*/
|
|
1235
|
+
interface StepDispatchOpts {
|
|
1236
|
+
/** Subject the dispatch to a registered flow-control queue (concurrency / rate limit). */
|
|
1237
|
+
queue?: string;
|
|
1238
|
+
/** Admission priority within `queue`; higher is admitted first when a slot is contended
|
|
1239
|
+
* (default 0). No effect without a `queue`. */
|
|
1240
|
+
priority?: number;
|
|
1241
|
+
/** The fairness bucket for a queue with `fairness: 'key'` (e.g. a tenant id) — the queue
|
|
1242
|
+
* round-robins across distinct keys so one key can't monopolize the budget. Defaults to the run
|
|
1243
|
+
* id when omitted. No effect without a `queue`. */
|
|
1244
|
+
fairnessKey?: string;
|
|
1245
|
+
/** Pin the dispatch to a named transport in the pool (else the pool's first, with failover to the
|
|
1246
|
+
* rest). See `engine.registerQueue` / the engine's `transports` option. */
|
|
1247
|
+
transport?: string;
|
|
1248
|
+
/** Max attempts before the step (and run) fails. Overrides the `@Step`-declared value. */
|
|
1249
|
+
retries?: number;
|
|
1250
|
+
/** How the delay between retries grows: `fixed` (constant) or `exp` (doubles each attempt).
|
|
1251
|
+
* Overrides the `@Step`-declared value. */
|
|
1252
|
+
backoff?: BackoffStrategy;
|
|
1253
|
+
/** Base delay in ms between retries. Omit (or 0) to retry with no delay. Overrides the
|
|
1254
|
+
* `@Step`-declared value. */
|
|
1255
|
+
backoffMs?: number;
|
|
1256
|
+
/** Upper bound on the (exponential) backoff delay. Overrides the `@Step`-declared value. */
|
|
1257
|
+
backoffMaxMs?: number;
|
|
1258
|
+
/** Add random jitter (50–100% of the computed delay) to avoid thundering-herd retries. Overrides
|
|
1259
|
+
* the `@Step`-declared value. */
|
|
1260
|
+
jitter?: boolean;
|
|
1261
|
+
/** Liveness window for this dispatched step: no result/heartbeat within this many ms presumes the
|
|
1262
|
+
* worker dead and fails the dispatch with a `RemoteStepTimeout` (retryable — re-dispatches per
|
|
1263
|
+
* `retries`). Omit to wait indefinitely. Overrides the `@Step`-declared value. */
|
|
1264
|
+
timeoutMs?: number;
|
|
1265
|
+
}
|
|
1044
1266
|
/**
|
|
1045
1267
|
* The context handed to a workflow function. Every interaction with the outside world goes
|
|
1046
1268
|
* through it so the engine can checkpoint — the workflow body itself stays deterministic.
|
|
@@ -1048,11 +1270,25 @@ interface DurableWebhook<TPayload = unknown> {
|
|
|
1048
1270
|
interface WorkflowCtx {
|
|
1049
1271
|
readonly runId: string;
|
|
1050
1272
|
/**
|
|
1051
|
-
* Run a
|
|
1052
|
-
*
|
|
1053
|
-
*
|
|
1273
|
+
* Run a durable step — always dispatched, always engine-scheduled: the ONE step primitive (no
|
|
1274
|
+
* local/remote placement choice). Pass the step's method **reference** (a `@Step`-decorated
|
|
1275
|
+
* method, typed by its own signature — refactor-safe, autocompleted):
|
|
1276
|
+
*
|
|
1277
|
+
* ```ts
|
|
1278
|
+
* const r = await ctx.step(this.extraction.runExtractionPage, { page, key });
|
|
1279
|
+
* ```
|
|
1280
|
+
*
|
|
1281
|
+
* or its **name** for a cross-runtime handler (no JS reference to import, e.g. a Python `@step`):
|
|
1282
|
+
*
|
|
1283
|
+
* ```ts
|
|
1284
|
+
* const out = await ctx.step<ProcResult>('processing:proc', input);
|
|
1285
|
+
* ```
|
|
1286
|
+
*
|
|
1287
|
+
* Both forms dispatch identically — a step runs on whatever worker serves that name and the run
|
|
1288
|
+
* suspends (zero compute) until the result lands, then resumes with it (durable, replay-safe).
|
|
1054
1289
|
*/
|
|
1055
|
-
step<TOutput>(
|
|
1290
|
+
step<TInput, TOutput>(handler: StepRef<TInput, TOutput>, input: TInput, opts?: StepDispatchOpts): Promise<TOutput>;
|
|
1291
|
+
step<TOutput = unknown>(name: string, input: unknown, opts?: StepDispatchOpts): Promise<TOutput>;
|
|
1056
1292
|
/**
|
|
1057
1293
|
* **Exactly-once** durable step for DB work: runs `fn` and writes the step's checkpoint in ONE
|
|
1058
1294
|
* store transaction, so the business write and the "done" marker commit atomically — a crash can
|
|
@@ -1069,23 +1305,6 @@ interface WorkflowCtx {
|
|
|
1069
1305
|
callEntity<TResult = unknown>(name: string, key: string, op: string, arg?: unknown): Promise<TResult>;
|
|
1070
1306
|
/** Send a durable entity op without awaiting a result (fire-and-forget, dispatched once). */
|
|
1071
1307
|
signalEntity(name: string, key: string, op: string, arg?: unknown): Promise<void>;
|
|
1072
|
-
/**
|
|
1073
|
-
* Dispatch a typed remote step and await its checkpointed result. Options:
|
|
1074
|
-
* - `queue` — subject the dispatch to a registered flow-control queue (concurrency / rate limit).
|
|
1075
|
-
* - `priority` — admission priority within that queue; higher is admitted first when a slot is
|
|
1076
|
-
* contended (default 0). No effect without a `queue`.
|
|
1077
|
-
* - `fairnessKey` — the fairness bucket for a queue with `fairness: 'key'` (e.g. a tenant id);
|
|
1078
|
-
* the queue round-robins across distinct keys so one key can't monopolize the budget. Defaults
|
|
1079
|
-
* to the run id when omitted. No effect without a `queue`.
|
|
1080
|
-
* - `transport` — pin the dispatch to a named transport in the pool (else the pool's first, with
|
|
1081
|
-
* failover to the rest). See `engine.registerQueue` / the engine's `transports` option.
|
|
1082
|
-
*/
|
|
1083
|
-
call<TInput, TOutput>(step: RemoteStepDef<TInput, TOutput>, input: TInput, opts?: {
|
|
1084
|
-
queue?: string;
|
|
1085
|
-
priority?: number;
|
|
1086
|
-
fairnessKey?: string;
|
|
1087
|
-
transport?: string;
|
|
1088
|
-
}): Promise<TOutput>;
|
|
1089
1308
|
/**
|
|
1090
1309
|
* Durable sleep: suspends the run for `duration` (e.g. `'30s'`, `'2h'`, `'7 days'`, or ms as a
|
|
1091
1310
|
* number) without consuming resources, resuming automatically once the timer is due — even
|
|
@@ -1215,18 +1434,25 @@ interface WorkflowCtx {
|
|
|
1215
1434
|
*/
|
|
1216
1435
|
patched(id: string): Promise<boolean>;
|
|
1217
1436
|
/**
|
|
1218
|
-
* Deterministic wall-clock
|
|
1219
|
-
* value afterwards. Use this instead of `Date.now()
|
|
1220
|
-
* a different value on every replay, which silently
|
|
1437
|
+
* Deterministic wall-clock, epoch **milliseconds** (like `Date.now()`): records the time on the
|
|
1438
|
+
* first run and replays the SAME value afterwards. Use this instead of `Date.now()`/`new Date()`
|
|
1439
|
+
* inside a workflow — a raw clock read returns a different value on every replay, which silently
|
|
1440
|
+
* corrupts a durable run. Returns a number so it composes in arithmetic (deadlines, elapsed);
|
|
1441
|
+
* for an ISO string do `new Date(await ctx.now()).toISOString()`. Every step is dispatched now
|
|
1442
|
+
* (see {@link step}), so a trivial timestamp capture gets this lightweight deterministic helper
|
|
1443
|
+
* instead of a full `@Step` + worker round-trip.
|
|
1221
1444
|
*/
|
|
1222
1445
|
now(): Promise<number>;
|
|
1223
1446
|
/**
|
|
1224
|
-
* Deterministic
|
|
1225
|
-
*
|
|
1447
|
+
* **Deterministic capture.** Run `fn` once, checkpoint its result, and on replay return the SAME
|
|
1448
|
+
* value WITHOUT re-running `fn` — the durable way to bring a non-deterministic value into a workflow
|
|
1449
|
+
* where you control the generator: `ctx.sideEffect(() => uuidv7())`, `() => ulid()`,
|
|
1450
|
+
* `() => Math.random()`, a config/env read. Prefer a {@link step} for real work with side effects
|
|
1451
|
+
* (a DB write, an API call): `fn` here runs only once and MUST be effectively pure (it produces a
|
|
1452
|
+
* value; it is not re-executed on replay), like Temporal's `sideEffect`. For a plain timestamp use
|
|
1453
|
+
* {@link now}.
|
|
1226
1454
|
*/
|
|
1227
|
-
|
|
1228
|
-
/** Deterministic UUID v4: recorded once, then replayed. Use instead of `crypto.randomUUID()`. */
|
|
1229
|
-
uuid(): Promise<string>;
|
|
1455
|
+
sideEffect<TValue>(fn: () => TValue | Promise<TValue>): Promise<TValue>;
|
|
1230
1456
|
/**
|
|
1231
1457
|
* Merge `attrs` into THIS run's {@link WorkflowRun.searchAttributes} — the indexed metadata the
|
|
1232
1458
|
* dashboard and {@link RunQuery} filter on. Shallow merge: keys you don't pass are kept. Durable +
|
|
@@ -1267,6 +1493,10 @@ interface EngineEvent {
|
|
|
1267
1493
|
type: EngineEventType;
|
|
1268
1494
|
runId: string;
|
|
1269
1495
|
workflow?: string | undefined;
|
|
1496
|
+
/** The run's worker-pool partition (see {@link WorkflowRun.namespace}), stamped on the `run.*`
|
|
1497
|
+
* lifecycle events (where the emitting call site already has the run in hand) so a tenant-event
|
|
1498
|
+
* re-publisher can scope without a per-event store read. Absent on `step.*` events. */
|
|
1499
|
+
namespace?: string | undefined;
|
|
1270
1500
|
seq?: number | undefined;
|
|
1271
1501
|
name?: string | undefined;
|
|
1272
1502
|
kind?: StepKind | undefined;
|
|
@@ -1302,6 +1532,17 @@ interface StepInvocation {
|
|
|
1302
1532
|
*/
|
|
1303
1533
|
type StepInterceptor = (invocation: StepInvocation, next: () => Promise<unknown>) => Promise<unknown>;
|
|
1304
1534
|
|
|
1535
|
+
/**
|
|
1536
|
+
* {@link WorkflowCtx} plus the internal in-process local-step primitive — used ONLY by the library's
|
|
1537
|
+
* own built-in workflows (the durable-entity runner) that need a checkpointed, in-process step the
|
|
1538
|
+
* public `ctx.step` (always-dispatched, no in-process placement) no longer provides. Every
|
|
1539
|
+
* `createWorkflowCtx` result actually carries `localStep` at runtime; this type just names the wider
|
|
1540
|
+
* shape for the internal consumers that need it, without widening the public {@link WorkflowCtx}.
|
|
1541
|
+
*/
|
|
1542
|
+
interface InternalWorkflowCtx extends WorkflowCtx {
|
|
1543
|
+
localStep<TOutput>(name: string, fn: (log: StepLogger) => Promise<TOutput>, options?: StepOptions): Promise<TOutput>;
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1305
1546
|
/** One operation on a durable entity: mutate `state` in place and/or return a result. */
|
|
1306
1547
|
type EntityHandler<S = unknown> = (state: S, arg: unknown) => unknown | Promise<unknown>;
|
|
1307
1548
|
/** A durable keyed entity (a virtual object): per-key serialized handlers over durable state. */
|
|
@@ -1313,7 +1554,7 @@ interface EntityConfig<S = unknown> {
|
|
|
1313
1554
|
}
|
|
1314
1555
|
/** The slice of the engine the entity subsystem needs (so it stays a standalone module). */
|
|
1315
1556
|
interface EntityHost {
|
|
1316
|
-
register(name: string, version: string, fn: (ctx:
|
|
1557
|
+
register(name: string, version: string, fn: (ctx: InternalWorkflowCtx, input: unknown) => Promise<unknown>): void;
|
|
1317
1558
|
signalWithStart(workflow: string, input: unknown, runId: string, signal: {
|
|
1318
1559
|
token: string;
|
|
1319
1560
|
payload?: unknown;
|
|
@@ -1383,7 +1624,7 @@ declare class EventAccumulators {
|
|
|
1383
1624
|
private batch;
|
|
1384
1625
|
}
|
|
1385
1626
|
|
|
1386
|
-
type WorkflowFn = (ctx:
|
|
1627
|
+
type WorkflowFn = (ctx: InternalWorkflowCtx, input: unknown) => Promise<unknown>;
|
|
1387
1628
|
/** Options for {@link WorkflowEngine.start}. */
|
|
1388
1629
|
interface StartOptions {
|
|
1389
1630
|
/** Run-scoped tags, merged with the workflow's static `@Workflow({ tags })` onto the run. */
|
|
@@ -1395,6 +1636,12 @@ interface StartOptions {
|
|
|
1395
1636
|
* the engine dispatches to advance it. Higher wins; absent = unprioritised. See {@link WorkflowRun.priority}.
|
|
1396
1637
|
*/
|
|
1397
1638
|
priority?: number | undefined;
|
|
1639
|
+
/**
|
|
1640
|
+
* Override the namespace stamped on the run. Defaults to the engine's own `namespace`. Set by the
|
|
1641
|
+
* control plane when it starts a run on behalf of a tenant (a {@link StartRunMessage}'s `tenant`
|
|
1642
|
+
* maps here), so one DB-less-tenant-facing engine can create runs across many namespaces.
|
|
1643
|
+
*/
|
|
1644
|
+
namespace?: string | undefined;
|
|
1398
1645
|
}
|
|
1399
1646
|
/**
|
|
1400
1647
|
* Serialize runs of a workflow that share a key — a durable, FIFO mutex (e.g. one pipeline per base).
|
|
@@ -1421,7 +1668,7 @@ interface WorkflowEngineDeps {
|
|
|
1421
1668
|
transport?: Transport | undefined;
|
|
1422
1669
|
/**
|
|
1423
1670
|
* An ordered pool of named transports. The engine dispatches on the first and fails over to the
|
|
1424
|
-
* next on a dispatch error; a step pins one via `ctx.
|
|
1671
|
+
* next on a dispatch error; a step pins one via `ctx.step(step, input, { transport: id })`. Use
|
|
1425
1672
|
* this instead of `transport` for failover / multi-broker setups.
|
|
1426
1673
|
*/
|
|
1427
1674
|
transports?: NamedTransport[] | undefined;
|
|
@@ -1434,7 +1681,7 @@ interface WorkflowEngineDeps {
|
|
|
1434
1681
|
/** Epoch-ms clock; injectable for tests. Defaults to `Date.now`. */
|
|
1435
1682
|
clock?: (() => number) | undefined;
|
|
1436
1683
|
/**
|
|
1437
|
-
* Flow-control admission backend for `ctx.
|
|
1684
|
+
* Flow-control admission backend for `ctx.step(step, input, { queue })`. Defaults to an in-process
|
|
1438
1685
|
* {@link InMemoryAdmissionBackend} (per-instance caps). Inject a store/Redis-backed backend to make
|
|
1439
1686
|
* concurrency / rate-limit / ordering GLOBAL across engine replicas.
|
|
1440
1687
|
*/
|
|
@@ -1444,8 +1691,11 @@ interface WorkflowEngineDeps {
|
|
|
1444
1691
|
/**
|
|
1445
1692
|
* Worker-pool partition for this engine. Stamped on every run it creates; the poll paths
|
|
1446
1693
|
* (`runPending`/`recoverIncomplete`/`resumeDueTimers`/`sweepTimeouts`) only act on runs in this
|
|
1447
|
-
* namespace.
|
|
1448
|
-
*
|
|
1694
|
+
* namespace. Set distinct values to safely share ONE state store across non-interchangeable pools
|
|
1695
|
+
* (e.g. local dev vs a cluster). **Omit it to make this engine an OPERATOR** — an unset namespace
|
|
1696
|
+
* drives/recovers/resumes runs of EVERY namespace (the poll filters no-op, the resume/decision
|
|
1697
|
+
* guards fall through) and leaves the transport on its bare prefix. This is the hosted control
|
|
1698
|
+
* plane: "ver tudo = ausência de namespace".
|
|
1449
1699
|
*/
|
|
1450
1700
|
namespace?: string | undefined;
|
|
1451
1701
|
/** Recovery lease duration in ms — how long this instance owns a run it picked up. Default 30s. */
|
|
@@ -1688,7 +1938,7 @@ declare class WorkflowEngine {
|
|
|
1688
1938
|
validateInput?: (input: unknown) => void | Promise<void>;
|
|
1689
1939
|
}): void;
|
|
1690
1940
|
/**
|
|
1691
|
-
* Register a flow-control queue referenced by `ctx.
|
|
1941
|
+
* Register a flow-control queue referenced by `ctx.step(step, input, { queue })`. Caps concurrent
|
|
1692
1942
|
* in-flight steps and/or the admission rate; blocked calls re-suspend and retry, so the limit is
|
|
1693
1943
|
* durable. Per engine instance (see {@link QueueConfig}). Registering the same name replaces it.
|
|
1694
1944
|
*/
|
|
@@ -1760,6 +2010,17 @@ declare class WorkflowEngine {
|
|
|
1760
2010
|
* its identity stays its own.
|
|
1761
2011
|
*/
|
|
1762
2012
|
private synthesizeRemoteChild;
|
|
2013
|
+
/**
|
|
2014
|
+
* Attempt to route an unregistered workflow to the live worker group of the same name: if the
|
|
2015
|
+
* transport reports a live heartbeat for group `run.workflow`, synthesize a throwaway
|
|
2016
|
+
* {@link RegisteredWorkflow} that dispatches to that group over the primary transport. Returns
|
|
2017
|
+
* `undefined` when the group is not live. Always attempted — there is no opt-in flag; an explicit
|
|
2018
|
+
* `register`/`registerRemote` still takes precedence (this only runs when nothing is registered).
|
|
2019
|
+
*
|
|
2020
|
+
* Recomputed per call (never memoized into `this.workflows`) so it stays correct if group
|
|
2021
|
+
* liveness changes between calls, exactly as {@link synthesizeRemoteChild} does.
|
|
2022
|
+
*/
|
|
2023
|
+
private resolveRemoteByConvention;
|
|
1763
2024
|
/**
|
|
1764
2025
|
* Walk the parent chain of `childRunId` to the nearest ancestor registered as REMOTE, returning its
|
|
1765
2026
|
* registration (or `undefined` if there is none). The parent of an awaited child is found via its
|
|
@@ -2229,25 +2490,17 @@ type StepHandler = (input: unknown, log: StepLogger) => Promise<unknown> | unkno
|
|
|
2229
2490
|
*/
|
|
2230
2491
|
declare function runStepHandler(task: RemoteTask, handler: StepHandler | undefined): Promise<StepResult>;
|
|
2231
2492
|
|
|
2232
|
-
interface RemoteStepConfig<TInput, TOutput> extends StepOptions {
|
|
2233
|
-
name: string;
|
|
2234
|
-
/** Worker group expected to handle this step. Defaults to the `name` prefix before the first dot. */
|
|
2235
|
-
group?: string;
|
|
2236
|
-
input: z.ZodType<TInput>;
|
|
2237
|
-
output: z.ZodType<TOutput>;
|
|
2238
|
-
}
|
|
2239
|
-
/**
|
|
2240
|
-
* Defines a typed handle to a step that runs on a remote worker. Call it from a workflow with
|
|
2241
|
-
* `ctx.call(step, input)`; a worker registers a handler under the same `name`.
|
|
2242
|
-
*/
|
|
2243
|
-
declare function remoteStep<TInput, TOutput>(config: RemoteStepConfig<TInput, TOutput>): RemoteStepDef<TInput, TOutput>;
|
|
2244
|
-
|
|
2245
2493
|
/**
|
|
2246
2494
|
* A {@link WorkflowExecutor} backed by a {@link Transport}: it advances a remote workflow by
|
|
2247
2495
|
* DISPATCHING a {@link WorkflowTask} over the broker under the ENGINE-SUPPLIED `taskId`, WITHOUT
|
|
2248
2496
|
* awaiting the decision. Pass one to `engine.registerRemote(name, version, { group, executor })` so a
|
|
2249
2497
|
* workflow authored in another SDK (e.g. the Python `durable-worker`) is driven over Redis/BullMQ.
|
|
2250
2498
|
*
|
|
2499
|
+
* Routes by NAME, not a hand-declared group: the dispatched task's routing token is
|
|
2500
|
+
* `tenantGroup(sanitizeQueueToken(name), partition)` — the same formula a {@link import('./interfaces').StepDef}
|
|
2501
|
+
* uses — so `partition` is an optional isolation suffix, not a separate identity. Omit it to route by
|
|
2502
|
+
* the bare (sanitized) `name`.
|
|
2503
|
+
*
|
|
2251
2504
|
* Multi-instance safe by construction: the executor holds NO in-memory state correlating a dispatched
|
|
2252
2505
|
* turn to its decision. The engine records the `taskId` on the run as the awaited marker AND releases
|
|
2253
2506
|
* the run's lease BEFORE calling `dispatch`, so the worker's {@link import('./interfaces').WorkflowDecision},
|
|
@@ -2264,8 +2517,9 @@ declare function remoteStep<TInput, TOutput>(config: RemoteStepConfig<TInput, TO
|
|
|
2264
2517
|
*/
|
|
2265
2518
|
declare class RemoteWorkflowExecutor implements WorkflowExecutor {
|
|
2266
2519
|
private readonly transport;
|
|
2267
|
-
private readonly
|
|
2268
|
-
|
|
2520
|
+
private readonly name;
|
|
2521
|
+
private readonly partition?;
|
|
2522
|
+
constructor(transport: Transport, name: string, partition?: string | undefined, _opts?: {
|
|
2269
2523
|
timeoutMs?: number;
|
|
2270
2524
|
});
|
|
2271
2525
|
/**
|
|
@@ -2275,6 +2529,35 @@ declare class RemoteWorkflowExecutor implements WorkflowExecutor {
|
|
|
2275
2529
|
dispatch(run: WorkflowRun, history: HistoryEvent[], taskId: string, pendingSignals?: WorkflowTask['pendingSignals']): Promise<void>;
|
|
2276
2530
|
}
|
|
2277
2531
|
|
|
2532
|
+
/** A run + its timeline + child ids — the detail view. Mirrors the dashboard's `RunDetail`. */
|
|
2533
|
+
interface RunDetail {
|
|
2534
|
+
run: WorkflowRun;
|
|
2535
|
+
/** Steps in execution order (local + remote). */
|
|
2536
|
+
timeline: StepCheckpoint[];
|
|
2537
|
+
/** Ids of runs this run spawned (parent→children tree). */
|
|
2538
|
+
children: string[];
|
|
2539
|
+
}
|
|
2540
|
+
/**
|
|
2541
|
+
* The bounded read/control/stream surface a consumer (e.g. a controller) needs, satisfied by BOTH
|
|
2542
|
+
* topologies: the control plane binds a store-backed impl (reuses `DashboardService`); a tenant binds
|
|
2543
|
+
* a `ProxyRunGateway` that round-trips over the transport. Deliberately smaller than the full dashboard
|
|
2544
|
+
* (no metrics/bulk/workerHealth/update/signal) — those stay control-plane-only.
|
|
2545
|
+
*/
|
|
2546
|
+
interface RunGateway {
|
|
2547
|
+
getRunDetail(runId: string): Promise<RunDetail | null>;
|
|
2548
|
+
listRuns(query: RunQuery): Promise<WorkflowRun[]>;
|
|
2549
|
+
cancel(runId: string, opts?: {
|
|
2550
|
+
compensate?: boolean;
|
|
2551
|
+
}): Promise<RunResult | null>;
|
|
2552
|
+
retry(runId: string): Promise<RunResult | null>;
|
|
2553
|
+
continue(runId: string): Promise<RunResult | null>;
|
|
2554
|
+
retryWithInput(runId: string, input: unknown): Promise<{
|
|
2555
|
+
runId: string;
|
|
2556
|
+
} | null>;
|
|
2557
|
+
/** Live lifecycle events for one run; returns an unsubscribe fn. Framework-agnostic (no rxjs). */
|
|
2558
|
+
subscribe(runId: string, onEvent: (event: EngineEvent) => void): () => void;
|
|
2559
|
+
}
|
|
2560
|
+
|
|
2278
2561
|
/**
|
|
2279
2562
|
* Transforms a payload value as it crosses the store boundary — e.g. encrypt-at-rest, compress, or
|
|
2280
2563
|
* redact PII. `decode` must be the exact inverse of `encode`. Both are synchronous (use a local
|
|
@@ -2505,6 +2788,23 @@ declare function attributeColumnFor(filter: AttributeFilter): 'numValue' | 'strV
|
|
|
2505
2788
|
/** The literal a side-table predicate compares against (booleans → `"true"`/`"false"` strings). */
|
|
2506
2789
|
declare function attributeOperand(filter: AttributeFilter): string | number;
|
|
2507
2790
|
|
|
2791
|
+
/**
|
|
2792
|
+
* Compute the worker group a tenant's run dispatches to. Mirrors the transport's
|
|
2793
|
+
* default-is-bare rule (see {@link TransportPool.useNamespace}'s `'default'` no-op): a
|
|
2794
|
+
* `tenant` of `undefined`, `''`, or `'default'` is the bare `baseGroup`, so a single-tenant
|
|
2795
|
+
* deployment (or the `'default'` tenant of a multi-tenant one) stays byte-identical to today.
|
|
2796
|
+
* Any other tenant suffixes the group as `<baseGroup>@<tenant>`, so an operator control plane
|
|
2797
|
+
* (namespace: undefined) can route each tenant's run to its own worker pool.
|
|
2798
|
+
*/
|
|
2799
|
+
declare function tenantGroup(baseGroup: string, tenant: string | undefined): string;
|
|
2800
|
+
/**
|
|
2801
|
+
* Sanitize a handler/workflow name for use as a BullMQ queue token: BullMQ forbids `:` in queue
|
|
2802
|
+
* names (it uses the colon internally as a key separator), so every `:` is replaced with `-`. `.`
|
|
2803
|
+
* is legal in a BullMQ queue name and is left as-is — step/workflow names commonly use it as a
|
|
2804
|
+
* namespacing separator (e.g. `payments.charge-card`).
|
|
2805
|
+
*/
|
|
2806
|
+
declare function sanitizeQueueToken(name: string): string;
|
|
2807
|
+
|
|
2508
2808
|
/**
|
|
2509
2809
|
* Dependency-injection tokens. Adapters bind their implementations to these so `core` and
|
|
2510
2810
|
* `@dudousxd/nestjs-durable` depend only on the interfaces in `./interfaces`.
|
|
@@ -2635,4 +2935,4 @@ declare class InMemoryTransport implements Transport, ControlPlane {
|
|
|
2635
2935
|
onControl(handler: (msg: ControlMessage) => void): void;
|
|
2636
2936
|
}
|
|
2637
2937
|
|
|
2638
|
-
export { type AccumulatorHost, type Admission, type AdmissionBackend, type AdmissionItem, type AttributeFilter, type AttributeOp, type BackoffStrategy, type ChildCallOptions, CodecStateStore, ContinueAsNew, type ControlMessage, type ControlPlane, DURABLE_OPTIONS, DURABLE_OPTIONS_CANONICAL, type DurableWebhook, type EngineEvent, type EngineEventType, type EngineListener, Entities, type EntityConfig, type EntityHandler, type EntityHost, EventAccumulators, type EventBatchConfig, FatalError, GatherError, type GroupHealth, type Heartbeat, type HistoryEvent, InMemoryAdmissionBackend, InMemoryStateStore, InMemoryTransport, type MetricsCollector, type MetricsSnapshot, type NamedTransport, NonDeterminismError, type PayloadCodec, type QueueConfig, QueueController,
|
|
2938
|
+
export { type AccumulatorHost, type Admission, type AdmissionBackend, type AdmissionItem, type AttributeFilter, type AttributeOp, type BackoffStrategy, type ChildCallOptions, CodecStateStore, ContinueAsNew, type ControlMessage, type ControlPlane, DURABLE_OPTIONS, DURABLE_OPTIONS_CANONICAL, DURABLE_STEP_CONFIG, DURABLE_STEP_NAME, type DurableWebhook, type EngineEvent, type EngineEventType, type EngineListener, Entities, type EntityConfig, type EntityHandler, type EntityHost, EventAccumulators, type EventBatchConfig, FatalError, GatherError, type GroupHealth, type Heartbeat, type HistoryEvent, InMemoryAdmissionBackend, InMemoryStateStore, InMemoryTransport, type MetricsCollector, type MetricsSnapshot, type NamedTransport, NonDeterminismError, type PayloadCodec, type QueueConfig, QueueController, RemoteStepError, RemoteStepTimeout, type RemoteTask, RemoteWorkflowExecutor, RemoteWorkflowTimeout, type RetentionPolicy, type RunAttributeRow, type RunDetail, type RunDispatcher, type RunGateway, type RunQuery, type RunReply, type RunReplyResult, type RunRequest, type RunRequestKind, type RunResult, type RunSchedulesOptions, type RunStatus, STATE_STORE, STATE_STORE_CANONICAL, type ScheduledWorkflow, type SearchAttributes, SignalTimeoutError, type SignalWaiter, type SingletonConfig, SingletonQueueFullError, type StartOptions, type StartRunMessage, type StateStore, type StepCheckpoint, type StepConfig, type StepDef, type StepDispatchOpts, type StepError, type StepEvent, type StepHandler, type StepInterceptor, type StepInvocation, type StepKind, type StepLogger, type StepOptions, type StepRef, type StepResult, type StoreTransaction, type SubProcessHandle, TERMINAL_RUN_STATUSES, TRANSPORT, TRANSPORT_CANONICAL, type TenantEvent, type Transport, type UpdateResult, type UpdateValidator, WORKFLOW_NAME_KEY, type WorkerAdjust, type WorkerConcurrencyStatus, type WorkerHeartbeat, type WorkerStatus, type WorkflowClass, type WorkflowCommand, type WorkflowCtx, type WorkflowDecision, WorkflowEngine, type WorkflowEngineDeps, type WorkflowExecutor, type WorkflowInputOf, type WorkflowOutputOf, type WorkflowRef, type WorkflowRun, type WorkflowStepEvent, WorkflowSuspended, type WorkflowTask, applyAttributeQuery, attributeColumnFor, attributeOperand, breakpointToken, collectMetrics, createStepLogger, eventMatchOf, eventMatches, eventPrefix, eventToken, matchesAttributes, normalizeAttributeRows, parseDuration, prevCronFireMs, runSchedules, runStepHandler, sanitizeQueueToken, scheduledRunId, sqlComparator, stepConfigOf, stepId, stepNameOf, tenantGroup, workflowName };
|