@dudousxd/nestjs-durable-core 0.32.0 → 0.33.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 +121 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +97 -2
- package/dist/index.d.ts +97 -2
- package/dist/index.js +118 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -283,6 +283,13 @@ interface StepCheckpoint {
|
|
|
283
283
|
events?: StepEvent[] | undefined;
|
|
284
284
|
/** For sleep steps: epoch ms the sleep elapses at. */
|
|
285
285
|
wakeAt?: number | undefined;
|
|
286
|
+
/**
|
|
287
|
+
* Set on the running placeholder checkpoints of the children dispatched by one `ctx.all` call —
|
|
288
|
+
* a shared tag (`all:<firstSeq>`) grouping the N siblings so the dashboard can render them as one
|
|
289
|
+
* parallel fan-out. Optional and additive: absent on every non-`all` checkpoint. Mirrors the
|
|
290
|
+
* Python SDK's `parallelGroup`.
|
|
291
|
+
*/
|
|
292
|
+
parallelGroup?: string | undefined;
|
|
286
293
|
/**
|
|
287
294
|
* When the step entered the system: for a remote step, when the engine dispatched it to the
|
|
288
295
|
* transport; for a local step, when it began. Queue-wait time = `startedAt − enqueuedAt`.
|
|
@@ -636,6 +643,9 @@ type WorkflowCommand =
|
|
|
636
643
|
startedAt?: number;
|
|
637
644
|
finishedAt?: number;
|
|
638
645
|
events?: StepEvent[];
|
|
646
|
+
/** A worker's `ctx.gather([...])` tags every step in the parallel fan with the same group, so the
|
|
647
|
+
* engine carries it onto the checkpoint and the dashboard renders the fan as one group. */
|
|
648
|
+
parallelGroup?: string;
|
|
639
649
|
}
|
|
640
650
|
/** `ctx.sleep(ms)` — a durable timer of `ms` duration. The engine computes the absolute deadline
|
|
641
651
|
* (now + ms) when it applies the command, so the worker never reads the clock (determinism). */
|
|
@@ -650,12 +660,15 @@ type WorkflowCommand =
|
|
|
650
660
|
seq: number;
|
|
651
661
|
signal: string;
|
|
652
662
|
}
|
|
653
|
-
/** `ctx.start_child(workflow, input)` — start a child run with its own lifecycle.
|
|
663
|
+
/** `ctx.start_child(workflow, input)` — start a child run with its own lifecycle. A worker's
|
|
664
|
+
* `ctx.all([...])` fan-out tags every dispatched child with the same `parallelGroup` so the
|
|
665
|
+
* dashboard can render the fan as one group (parity with the gathered `recordStep` tag). */
|
|
654
666
|
| {
|
|
655
667
|
kind: 'startChild';
|
|
656
668
|
seq: number;
|
|
657
669
|
workflow: string;
|
|
658
670
|
input: unknown;
|
|
671
|
+
parallelGroup?: string;
|
|
659
672
|
};
|
|
660
673
|
/** workflow worker → engine: the result of replaying one turn of a remote workflow. */
|
|
661
674
|
interface WorkflowDecision {
|
|
@@ -693,6 +706,9 @@ interface WorkflowStepEvent {
|
|
|
693
706
|
error?: StepError;
|
|
694
707
|
/** Sub-process + log trail the step emitted so far (the handler's p-processes). */
|
|
695
708
|
events?: StepEvent[];
|
|
709
|
+
/** A worker's `ctx.gather([...])` fan tags every step's lifecycle with the same group so the
|
|
710
|
+
* dashboard renders the live fan-out as one group (parity with the `recordStep` tag). */
|
|
711
|
+
parallelGroup?: string | undefined;
|
|
696
712
|
}
|
|
697
713
|
/**
|
|
698
714
|
* Advances a workflow run one turn. The engine has one per workflow: the default {@link InProcess}
|
|
@@ -988,6 +1004,24 @@ interface WorkflowCtx {
|
|
|
988
1004
|
*/
|
|
989
1005
|
startChild<C extends WorkflowClass>(workflow: C, input: WorkflowInputOf<C>, options?: string | ChildCallOptions): Promise<string>;
|
|
990
1006
|
startChild(workflow: string, input: unknown, options?: string | ChildCallOptions): Promise<string>;
|
|
1007
|
+
/**
|
|
1008
|
+
* Run N children of the SAME workflow **in parallel** and wait for ALL of them: dispatches one
|
|
1009
|
+
* child per entry in `inputs` (concurrently, each with its own durable lifecycle), suspends — zero
|
|
1010
|
+
* compute — until every child reaches a terminal state, then resumes with their outputs in **input
|
|
1011
|
+
* order**. Child ids are group-scoped and stable (`<runId>.all.<firstSeq>.<i>`), and the running
|
|
1012
|
+
* placeholders share a `parallelGroup` tag so the dashboard renders the fan-out as one group.
|
|
1013
|
+
*
|
|
1014
|
+
* `mode` (default `waitAll`): `waitAll` waits for all then throws an aggregate {@link GatherError}
|
|
1015
|
+
* if any failed; `failFast` throws as soon as a failed child is seen (siblings are not cancelled in
|
|
1016
|
+
* v1 — their eventual results are ignored). Empty `inputs` returns `[]` with no side effects. The
|
|
1017
|
+
* wait-all / fan-out counterpart to {@link child}; parity with the Python SDK's `gather_children`.
|
|
1018
|
+
*/
|
|
1019
|
+
all<C extends WorkflowClass>(workflow: C, inputs: WorkflowInputOf<C>[], opts?: {
|
|
1020
|
+
mode?: 'waitAll' | 'failFast';
|
|
1021
|
+
}): Promise<WorkflowOutputOf<C>[]>;
|
|
1022
|
+
all<TOutput = unknown>(workflow: string, inputs: unknown[], opts?: {
|
|
1023
|
+
mode?: 'waitAll' | 'failFast';
|
|
1024
|
+
}): Promise<TOutput[]>;
|
|
991
1025
|
/**
|
|
992
1026
|
* Pause the run at this point until a human resumes it from the dashboard (or
|
|
993
1027
|
* `engine.continue(runId)`). Records a visible `pending` checkpoint so the breakpoint shows up
|
|
@@ -1803,6 +1837,29 @@ declare class RemoteStepTimeout extends Error {
|
|
|
1803
1837
|
readonly timeoutMs: number;
|
|
1804
1838
|
constructor(stepId: string, timeoutMs: number);
|
|
1805
1839
|
}
|
|
1840
|
+
/**
|
|
1841
|
+
* Thrown by a remote {@link WorkflowExecutor} (e.g. {@link RemoteWorkflowExecutor}) when an `advance`
|
|
1842
|
+
* does not produce its decision within the configured `timeoutMs` — i.e. the worker is presumed gone
|
|
1843
|
+
* (the decision was dropped by a stall/redelivery or an instance restart spanning the in-memory waiter
|
|
1844
|
+
* map). Crucially this is NOT a run failure: the work may have actually completed and only the decision
|
|
1845
|
+
* was lost. The engine treats it as RECOVERABLE — it releases the run lease and leaves the run
|
|
1846
|
+
* `running` so `recoverIncomplete` re-drives it deterministically (replaying completed steps from
|
|
1847
|
+
* history). Distinct from a real executor error, which still fails the run.
|
|
1848
|
+
*
|
|
1849
|
+
* OPT-IN: only thrown when the executor was constructed with a `timeoutMs`. Absent a timeout, the
|
|
1850
|
+
* engine awaits the decision with its prior (unbounded) behavior — so existing users see no change.
|
|
1851
|
+
*
|
|
1852
|
+
* Known hazard: a timeout that fires while a worker is LEGITIMATELY still executing a not-yet-
|
|
1853
|
+
* checkpointed step will re-drive and re-run that in-flight step → DUPLICATE side effects. Therefore
|
|
1854
|
+
* the timeout is only safe when set GENEROUSLY (longer than the longest legitimate single turn). The
|
|
1855
|
+
* robust fix — a liveness/heartbeat-rearmed deadline so only a genuinely-dead worker re-drives — is the
|
|
1856
|
+
* documented follow-up (see the Track A diagnosis doc, "Part B").
|
|
1857
|
+
*/
|
|
1858
|
+
declare class RemoteWorkflowTimeout extends Error {
|
|
1859
|
+
readonly taskId: string;
|
|
1860
|
+
readonly timeoutMs: number;
|
|
1861
|
+
constructor(taskId: string, timeoutMs: number);
|
|
1862
|
+
}
|
|
1806
1863
|
/**
|
|
1807
1864
|
* Thrown on resume when the workflow code no longer matches the recorded history: the step at a
|
|
1808
1865
|
* logical position has a different name/kind than the checkpoint saved there. This means the
|
|
@@ -1816,6 +1873,24 @@ declare class NonDeterminismError extends Error {
|
|
|
1816
1873
|
readonly seq: number;
|
|
1817
1874
|
constructor(runId: string, seq: number, expected: string, recorded: string);
|
|
1818
1875
|
}
|
|
1876
|
+
/**
|
|
1877
|
+
* Thrown by `ctx.all` when one or more parallel child workflows fail. Carries the per-item failures
|
|
1878
|
+
* (input index, child run id, error message) and presents an aggregate message summarizing the count
|
|
1879
|
+
* and the failing ids — the wait-all/fail-fast counterpart to a single child's FatalError. Mirrors
|
|
1880
|
+
* the Python SDK's `GatherFailed`.
|
|
1881
|
+
*/
|
|
1882
|
+
declare class GatherError extends Error {
|
|
1883
|
+
readonly failures: {
|
|
1884
|
+
index: number;
|
|
1885
|
+
id: string;
|
|
1886
|
+
error: string;
|
|
1887
|
+
}[];
|
|
1888
|
+
constructor(failures: {
|
|
1889
|
+
index: number;
|
|
1890
|
+
id: string;
|
|
1891
|
+
error: string;
|
|
1892
|
+
}[], total?: number);
|
|
1893
|
+
}
|
|
1819
1894
|
declare class WorkflowSuspended extends Error {
|
|
1820
1895
|
/** Epoch ms to auto-resume (durable sleep), or undefined when waiting on an external signal. */
|
|
1821
1896
|
readonly wakeAt?: number | undefined;
|
|
@@ -2059,6 +2134,14 @@ declare function prevCronFireMs(expr: string, nowMs: number, timezone?: string):
|
|
|
2059
2134
|
*/
|
|
2060
2135
|
declare function runSchedules(engine: Pick<WorkflowEngine, 'start' | 'getRun'>, schedules: readonly ScheduledWorkflow[], nowMs: number, opts?: RunSchedulesOptions): Promise<string[]>;
|
|
2061
2136
|
|
|
2137
|
+
/**
|
|
2138
|
+
* A {@link StepLogger} that appends to `events`, stamping each line with `now()`. Shared by the
|
|
2139
|
+
* local-step path (`ctx.step`) and the remote-worker path (`runStepHandler`) so a step records
|
|
2140
|
+
* the same {@link StepEvent} shape wherever it runs — the TypeScript twin of the Python SDK's
|
|
2141
|
+
* `StepContext`.
|
|
2142
|
+
*/
|
|
2143
|
+
declare function createStepLogger(events: StepEvent[], now: () => number): StepLogger;
|
|
2144
|
+
|
|
2062
2145
|
/**
|
|
2063
2146
|
* Does a run's search attributes satisfy EVERY filter (AND)? A missing key never matches (so `ne`
|
|
2064
2147
|
* on an absent key is false too — the attribute simply isn't there to compare). Empty/undefined
|
|
@@ -2119,8 +2202,20 @@ declare function attributeOperand(filter: AttributeFilter): string | number;
|
|
|
2119
2202
|
* (`STATE_STORE is not available in the DurableApiModule context`). A registered symbol collapses
|
|
2120
2203
|
* them to one. Mirrors the `CONTEXT_ACCESSOR` token in `@dudousxd/nestjs-durable`'s `tokens.ts`.
|
|
2121
2204
|
*/
|
|
2205
|
+
/**
|
|
2206
|
+
* @deprecated Use {@link STATE_STORE_CANONICAL} (`@dudousxd/nestjs-durable:state-store`). The legacy
|
|
2207
|
+
* token stays bound as a back-compat alias and still resolves; it will be removed in a future major.
|
|
2208
|
+
*/
|
|
2122
2209
|
declare const STATE_STORE: unique symbol;
|
|
2210
|
+
/**
|
|
2211
|
+
* @deprecated Use {@link TRANSPORT_CANONICAL} (`@dudousxd/nestjs-durable:transport`). The legacy
|
|
2212
|
+
* token stays bound as a back-compat alias and still resolves; it will be removed in a future major.
|
|
2213
|
+
*/
|
|
2123
2214
|
declare const TRANSPORT: unique symbol;
|
|
2215
|
+
/**
|
|
2216
|
+
* @deprecated Use {@link DURABLE_OPTIONS_CANONICAL} (`@dudousxd/nestjs-durable:options`). The legacy
|
|
2217
|
+
* token stays bound as a back-compat alias and still resolves; it will be removed in a future major.
|
|
2218
|
+
*/
|
|
2124
2219
|
declare const DURABLE_OPTIONS: unique symbol;
|
|
2125
2220
|
/**
|
|
2126
2221
|
* Canonical, cross-lib-discoverable aliases of the durable DI tokens, following the ecosystem
|
|
@@ -2220,4 +2315,4 @@ declare class InMemoryTransport implements Transport, ControlPlane {
|
|
|
2220
2315
|
onControl(handler: (msg: ControlMessage) => void): void;
|
|
2221
2316
|
}
|
|
2222
2317
|
|
|
2223
|
-
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, type GroupHealth, type Heartbeat, type HistoryEvent, InMemoryAdmissionBackend, InMemoryStateStore, InMemoryTransport, type MetricsCollector, type MetricsSnapshot, type NamedTransport, NonDeterminismError, type PayloadCodec, type QueueConfig, QueueController, type RemoteStepConfig, type RemoteStepDef, RemoteStepError, RemoteStepTimeout, type RemoteTask, RemoteWorkflowExecutor, type RunAttributeRow, type RunDispatcher, type RunQuery, type RunResult, type RunSchedulesOptions, type RunStatus, STATE_STORE, STATE_STORE_CANONICAL, type ScheduledWorkflow, type SearchAttributes, SignalTimeoutError, type SignalWaiter, type SingletonConfig, SingletonQueueFullError, type StartOptions, type StateStore, type StepCheckpoint, type StepError, type StepEvent, type StepHandler, type StepInterceptor, type StepInvocation, type StepKind, type StepLogger, type StepOptions, type StepResult, type StoreTransaction, type SubProcessHandle, TRANSPORT, TRANSPORT_CANONICAL, type Transport, type UpdateResult, type UpdateValidator, WORKFLOW_NAME_KEY, type WorkerHeartbeat, 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, eventMatchOf, eventMatches, eventPrefix, eventToken, matchesAttributes, normalizeAttributeRows, parseDuration, prevCronFireMs, remoteStep, runSchedules, runStepHandler, scheduledRunId, sqlComparator, stepId, workflowName };
|
|
2318
|
+
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, type RemoteStepConfig, type RemoteStepDef, RemoteStepError, RemoteStepTimeout, type RemoteTask, RemoteWorkflowExecutor, RemoteWorkflowTimeout, type RunAttributeRow, type RunDispatcher, type RunQuery, type RunResult, type RunSchedulesOptions, type RunStatus, STATE_STORE, STATE_STORE_CANONICAL, type ScheduledWorkflow, type SearchAttributes, SignalTimeoutError, type SignalWaiter, type SingletonConfig, SingletonQueueFullError, type StartOptions, type StateStore, type StepCheckpoint, type StepError, type StepEvent, type StepHandler, type StepInterceptor, type StepInvocation, type StepKind, type StepLogger, type StepOptions, type StepResult, type StoreTransaction, type SubProcessHandle, TRANSPORT, TRANSPORT_CANONICAL, type Transport, type UpdateResult, type UpdateValidator, WORKFLOW_NAME_KEY, type WorkerHeartbeat, 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, remoteStep, runSchedules, runStepHandler, scheduledRunId, sqlComparator, stepId, workflowName };
|
package/dist/index.d.ts
CHANGED
|
@@ -283,6 +283,13 @@ interface StepCheckpoint {
|
|
|
283
283
|
events?: StepEvent[] | undefined;
|
|
284
284
|
/** For sleep steps: epoch ms the sleep elapses at. */
|
|
285
285
|
wakeAt?: number | undefined;
|
|
286
|
+
/**
|
|
287
|
+
* Set on the running placeholder checkpoints of the children dispatched by one `ctx.all` call —
|
|
288
|
+
* a shared tag (`all:<firstSeq>`) grouping the N siblings so the dashboard can render them as one
|
|
289
|
+
* parallel fan-out. Optional and additive: absent on every non-`all` checkpoint. Mirrors the
|
|
290
|
+
* Python SDK's `parallelGroup`.
|
|
291
|
+
*/
|
|
292
|
+
parallelGroup?: string | undefined;
|
|
286
293
|
/**
|
|
287
294
|
* When the step entered the system: for a remote step, when the engine dispatched it to the
|
|
288
295
|
* transport; for a local step, when it began. Queue-wait time = `startedAt − enqueuedAt`.
|
|
@@ -636,6 +643,9 @@ type WorkflowCommand =
|
|
|
636
643
|
startedAt?: number;
|
|
637
644
|
finishedAt?: number;
|
|
638
645
|
events?: StepEvent[];
|
|
646
|
+
/** A worker's `ctx.gather([...])` tags every step in the parallel fan with the same group, so the
|
|
647
|
+
* engine carries it onto the checkpoint and the dashboard renders the fan as one group. */
|
|
648
|
+
parallelGroup?: string;
|
|
639
649
|
}
|
|
640
650
|
/** `ctx.sleep(ms)` — a durable timer of `ms` duration. The engine computes the absolute deadline
|
|
641
651
|
* (now + ms) when it applies the command, so the worker never reads the clock (determinism). */
|
|
@@ -650,12 +660,15 @@ type WorkflowCommand =
|
|
|
650
660
|
seq: number;
|
|
651
661
|
signal: string;
|
|
652
662
|
}
|
|
653
|
-
/** `ctx.start_child(workflow, input)` — start a child run with its own lifecycle.
|
|
663
|
+
/** `ctx.start_child(workflow, input)` — start a child run with its own lifecycle. A worker's
|
|
664
|
+
* `ctx.all([...])` fan-out tags every dispatched child with the same `parallelGroup` so the
|
|
665
|
+
* dashboard can render the fan as one group (parity with the gathered `recordStep` tag). */
|
|
654
666
|
| {
|
|
655
667
|
kind: 'startChild';
|
|
656
668
|
seq: number;
|
|
657
669
|
workflow: string;
|
|
658
670
|
input: unknown;
|
|
671
|
+
parallelGroup?: string;
|
|
659
672
|
};
|
|
660
673
|
/** workflow worker → engine: the result of replaying one turn of a remote workflow. */
|
|
661
674
|
interface WorkflowDecision {
|
|
@@ -693,6 +706,9 @@ interface WorkflowStepEvent {
|
|
|
693
706
|
error?: StepError;
|
|
694
707
|
/** Sub-process + log trail the step emitted so far (the handler's p-processes). */
|
|
695
708
|
events?: StepEvent[];
|
|
709
|
+
/** A worker's `ctx.gather([...])` fan tags every step's lifecycle with the same group so the
|
|
710
|
+
* dashboard renders the live fan-out as one group (parity with the `recordStep` tag). */
|
|
711
|
+
parallelGroup?: string | undefined;
|
|
696
712
|
}
|
|
697
713
|
/**
|
|
698
714
|
* Advances a workflow run one turn. The engine has one per workflow: the default {@link InProcess}
|
|
@@ -988,6 +1004,24 @@ interface WorkflowCtx {
|
|
|
988
1004
|
*/
|
|
989
1005
|
startChild<C extends WorkflowClass>(workflow: C, input: WorkflowInputOf<C>, options?: string | ChildCallOptions): Promise<string>;
|
|
990
1006
|
startChild(workflow: string, input: unknown, options?: string | ChildCallOptions): Promise<string>;
|
|
1007
|
+
/**
|
|
1008
|
+
* Run N children of the SAME workflow **in parallel** and wait for ALL of them: dispatches one
|
|
1009
|
+
* child per entry in `inputs` (concurrently, each with its own durable lifecycle), suspends — zero
|
|
1010
|
+
* compute — until every child reaches a terminal state, then resumes with their outputs in **input
|
|
1011
|
+
* order**. Child ids are group-scoped and stable (`<runId>.all.<firstSeq>.<i>`), and the running
|
|
1012
|
+
* placeholders share a `parallelGroup` tag so the dashboard renders the fan-out as one group.
|
|
1013
|
+
*
|
|
1014
|
+
* `mode` (default `waitAll`): `waitAll` waits for all then throws an aggregate {@link GatherError}
|
|
1015
|
+
* if any failed; `failFast` throws as soon as a failed child is seen (siblings are not cancelled in
|
|
1016
|
+
* v1 — their eventual results are ignored). Empty `inputs` returns `[]` with no side effects. The
|
|
1017
|
+
* wait-all / fan-out counterpart to {@link child}; parity with the Python SDK's `gather_children`.
|
|
1018
|
+
*/
|
|
1019
|
+
all<C extends WorkflowClass>(workflow: C, inputs: WorkflowInputOf<C>[], opts?: {
|
|
1020
|
+
mode?: 'waitAll' | 'failFast';
|
|
1021
|
+
}): Promise<WorkflowOutputOf<C>[]>;
|
|
1022
|
+
all<TOutput = unknown>(workflow: string, inputs: unknown[], opts?: {
|
|
1023
|
+
mode?: 'waitAll' | 'failFast';
|
|
1024
|
+
}): Promise<TOutput[]>;
|
|
991
1025
|
/**
|
|
992
1026
|
* Pause the run at this point until a human resumes it from the dashboard (or
|
|
993
1027
|
* `engine.continue(runId)`). Records a visible `pending` checkpoint so the breakpoint shows up
|
|
@@ -1803,6 +1837,29 @@ declare class RemoteStepTimeout extends Error {
|
|
|
1803
1837
|
readonly timeoutMs: number;
|
|
1804
1838
|
constructor(stepId: string, timeoutMs: number);
|
|
1805
1839
|
}
|
|
1840
|
+
/**
|
|
1841
|
+
* Thrown by a remote {@link WorkflowExecutor} (e.g. {@link RemoteWorkflowExecutor}) when an `advance`
|
|
1842
|
+
* does not produce its decision within the configured `timeoutMs` — i.e. the worker is presumed gone
|
|
1843
|
+
* (the decision was dropped by a stall/redelivery or an instance restart spanning the in-memory waiter
|
|
1844
|
+
* map). Crucially this is NOT a run failure: the work may have actually completed and only the decision
|
|
1845
|
+
* was lost. The engine treats it as RECOVERABLE — it releases the run lease and leaves the run
|
|
1846
|
+
* `running` so `recoverIncomplete` re-drives it deterministically (replaying completed steps from
|
|
1847
|
+
* history). Distinct from a real executor error, which still fails the run.
|
|
1848
|
+
*
|
|
1849
|
+
* OPT-IN: only thrown when the executor was constructed with a `timeoutMs`. Absent a timeout, the
|
|
1850
|
+
* engine awaits the decision with its prior (unbounded) behavior — so existing users see no change.
|
|
1851
|
+
*
|
|
1852
|
+
* Known hazard: a timeout that fires while a worker is LEGITIMATELY still executing a not-yet-
|
|
1853
|
+
* checkpointed step will re-drive and re-run that in-flight step → DUPLICATE side effects. Therefore
|
|
1854
|
+
* the timeout is only safe when set GENEROUSLY (longer than the longest legitimate single turn). The
|
|
1855
|
+
* robust fix — a liveness/heartbeat-rearmed deadline so only a genuinely-dead worker re-drives — is the
|
|
1856
|
+
* documented follow-up (see the Track A diagnosis doc, "Part B").
|
|
1857
|
+
*/
|
|
1858
|
+
declare class RemoteWorkflowTimeout extends Error {
|
|
1859
|
+
readonly taskId: string;
|
|
1860
|
+
readonly timeoutMs: number;
|
|
1861
|
+
constructor(taskId: string, timeoutMs: number);
|
|
1862
|
+
}
|
|
1806
1863
|
/**
|
|
1807
1864
|
* Thrown on resume when the workflow code no longer matches the recorded history: the step at a
|
|
1808
1865
|
* logical position has a different name/kind than the checkpoint saved there. This means the
|
|
@@ -1816,6 +1873,24 @@ declare class NonDeterminismError extends Error {
|
|
|
1816
1873
|
readonly seq: number;
|
|
1817
1874
|
constructor(runId: string, seq: number, expected: string, recorded: string);
|
|
1818
1875
|
}
|
|
1876
|
+
/**
|
|
1877
|
+
* Thrown by `ctx.all` when one or more parallel child workflows fail. Carries the per-item failures
|
|
1878
|
+
* (input index, child run id, error message) and presents an aggregate message summarizing the count
|
|
1879
|
+
* and the failing ids — the wait-all/fail-fast counterpart to a single child's FatalError. Mirrors
|
|
1880
|
+
* the Python SDK's `GatherFailed`.
|
|
1881
|
+
*/
|
|
1882
|
+
declare class GatherError extends Error {
|
|
1883
|
+
readonly failures: {
|
|
1884
|
+
index: number;
|
|
1885
|
+
id: string;
|
|
1886
|
+
error: string;
|
|
1887
|
+
}[];
|
|
1888
|
+
constructor(failures: {
|
|
1889
|
+
index: number;
|
|
1890
|
+
id: string;
|
|
1891
|
+
error: string;
|
|
1892
|
+
}[], total?: number);
|
|
1893
|
+
}
|
|
1819
1894
|
declare class WorkflowSuspended extends Error {
|
|
1820
1895
|
/** Epoch ms to auto-resume (durable sleep), or undefined when waiting on an external signal. */
|
|
1821
1896
|
readonly wakeAt?: number | undefined;
|
|
@@ -2059,6 +2134,14 @@ declare function prevCronFireMs(expr: string, nowMs: number, timezone?: string):
|
|
|
2059
2134
|
*/
|
|
2060
2135
|
declare function runSchedules(engine: Pick<WorkflowEngine, 'start' | 'getRun'>, schedules: readonly ScheduledWorkflow[], nowMs: number, opts?: RunSchedulesOptions): Promise<string[]>;
|
|
2061
2136
|
|
|
2137
|
+
/**
|
|
2138
|
+
* A {@link StepLogger} that appends to `events`, stamping each line with `now()`. Shared by the
|
|
2139
|
+
* local-step path (`ctx.step`) and the remote-worker path (`runStepHandler`) so a step records
|
|
2140
|
+
* the same {@link StepEvent} shape wherever it runs — the TypeScript twin of the Python SDK's
|
|
2141
|
+
* `StepContext`.
|
|
2142
|
+
*/
|
|
2143
|
+
declare function createStepLogger(events: StepEvent[], now: () => number): StepLogger;
|
|
2144
|
+
|
|
2062
2145
|
/**
|
|
2063
2146
|
* Does a run's search attributes satisfy EVERY filter (AND)? A missing key never matches (so `ne`
|
|
2064
2147
|
* on an absent key is false too — the attribute simply isn't there to compare). Empty/undefined
|
|
@@ -2119,8 +2202,20 @@ declare function attributeOperand(filter: AttributeFilter): string | number;
|
|
|
2119
2202
|
* (`STATE_STORE is not available in the DurableApiModule context`). A registered symbol collapses
|
|
2120
2203
|
* them to one. Mirrors the `CONTEXT_ACCESSOR` token in `@dudousxd/nestjs-durable`'s `tokens.ts`.
|
|
2121
2204
|
*/
|
|
2205
|
+
/**
|
|
2206
|
+
* @deprecated Use {@link STATE_STORE_CANONICAL} (`@dudousxd/nestjs-durable:state-store`). The legacy
|
|
2207
|
+
* token stays bound as a back-compat alias and still resolves; it will be removed in a future major.
|
|
2208
|
+
*/
|
|
2122
2209
|
declare const STATE_STORE: unique symbol;
|
|
2210
|
+
/**
|
|
2211
|
+
* @deprecated Use {@link TRANSPORT_CANONICAL} (`@dudousxd/nestjs-durable:transport`). The legacy
|
|
2212
|
+
* token stays bound as a back-compat alias and still resolves; it will be removed in a future major.
|
|
2213
|
+
*/
|
|
2123
2214
|
declare const TRANSPORT: unique symbol;
|
|
2215
|
+
/**
|
|
2216
|
+
* @deprecated Use {@link DURABLE_OPTIONS_CANONICAL} (`@dudousxd/nestjs-durable:options`). The legacy
|
|
2217
|
+
* token stays bound as a back-compat alias and still resolves; it will be removed in a future major.
|
|
2218
|
+
*/
|
|
2124
2219
|
declare const DURABLE_OPTIONS: unique symbol;
|
|
2125
2220
|
/**
|
|
2126
2221
|
* Canonical, cross-lib-discoverable aliases of the durable DI tokens, following the ecosystem
|
|
@@ -2220,4 +2315,4 @@ declare class InMemoryTransport implements Transport, ControlPlane {
|
|
|
2220
2315
|
onControl(handler: (msg: ControlMessage) => void): void;
|
|
2221
2316
|
}
|
|
2222
2317
|
|
|
2223
|
-
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, type GroupHealth, type Heartbeat, type HistoryEvent, InMemoryAdmissionBackend, InMemoryStateStore, InMemoryTransport, type MetricsCollector, type MetricsSnapshot, type NamedTransport, NonDeterminismError, type PayloadCodec, type QueueConfig, QueueController, type RemoteStepConfig, type RemoteStepDef, RemoteStepError, RemoteStepTimeout, type RemoteTask, RemoteWorkflowExecutor, type RunAttributeRow, type RunDispatcher, type RunQuery, type RunResult, type RunSchedulesOptions, type RunStatus, STATE_STORE, STATE_STORE_CANONICAL, type ScheduledWorkflow, type SearchAttributes, SignalTimeoutError, type SignalWaiter, type SingletonConfig, SingletonQueueFullError, type StartOptions, type StateStore, type StepCheckpoint, type StepError, type StepEvent, type StepHandler, type StepInterceptor, type StepInvocation, type StepKind, type StepLogger, type StepOptions, type StepResult, type StoreTransaction, type SubProcessHandle, TRANSPORT, TRANSPORT_CANONICAL, type Transport, type UpdateResult, type UpdateValidator, WORKFLOW_NAME_KEY, type WorkerHeartbeat, 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, eventMatchOf, eventMatches, eventPrefix, eventToken, matchesAttributes, normalizeAttributeRows, parseDuration, prevCronFireMs, remoteStep, runSchedules, runStepHandler, scheduledRunId, sqlComparator, stepId, workflowName };
|
|
2318
|
+
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, type RemoteStepConfig, type RemoteStepDef, RemoteStepError, RemoteStepTimeout, type RemoteTask, RemoteWorkflowExecutor, RemoteWorkflowTimeout, type RunAttributeRow, type RunDispatcher, type RunQuery, type RunResult, type RunSchedulesOptions, type RunStatus, STATE_STORE, STATE_STORE_CANONICAL, type ScheduledWorkflow, type SearchAttributes, SignalTimeoutError, type SignalWaiter, type SingletonConfig, SingletonQueueFullError, type StartOptions, type StateStore, type StepCheckpoint, type StepError, type StepEvent, type StepHandler, type StepInterceptor, type StepInvocation, type StepKind, type StepLogger, type StepOptions, type StepResult, type StoreTransaction, type SubProcessHandle, TRANSPORT, TRANSPORT_CANONICAL, type Transport, type UpdateResult, type UpdateValidator, WORKFLOW_NAME_KEY, type WorkerHeartbeat, 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, remoteStep, runSchedules, runStepHandler, scheduledRunId, sqlComparator, stepId, workflowName };
|
package/dist/index.js
CHANGED
|
@@ -385,6 +385,7 @@ function stepCheckpoint(p) {
|
|
|
385
385
|
attempts: p.attempts,
|
|
386
386
|
workerGroup: p.workerGroup,
|
|
387
387
|
wakeAt: p.wakeAt,
|
|
388
|
+
parallelGroup: p.parallelGroup,
|
|
388
389
|
enqueuedAt: p.enqueuedAt,
|
|
389
390
|
startedAt: p.startedAt,
|
|
390
391
|
finishedAt: p.finishedAt
|
|
@@ -402,6 +403,7 @@ function instantCheckpoint(p) {
|
|
|
402
403
|
status: p.status ?? "completed",
|
|
403
404
|
output: p.output,
|
|
404
405
|
wakeAt: p.wakeAt,
|
|
406
|
+
parallelGroup: p.parallelGroup,
|
|
405
407
|
attempts: 1,
|
|
406
408
|
enqueuedAt: at,
|
|
407
409
|
startedAt: at,
|
|
@@ -463,6 +465,19 @@ var RemoteStepTimeout = class extends Error {
|
|
|
463
465
|
this.timeoutMs = timeoutMs;
|
|
464
466
|
}
|
|
465
467
|
};
|
|
468
|
+
var RemoteWorkflowTimeout = class extends Error {
|
|
469
|
+
static {
|
|
470
|
+
__name(this, "RemoteWorkflowTimeout");
|
|
471
|
+
}
|
|
472
|
+
taskId;
|
|
473
|
+
timeoutMs;
|
|
474
|
+
constructor(taskId, timeoutMs) {
|
|
475
|
+
super(`remote workflow task ${taskId} produced no decision within ${timeoutMs}ms \u2014 presumed dropped; re-driving via recovery`);
|
|
476
|
+
this.name = "RemoteWorkflowTimeout";
|
|
477
|
+
this.taskId = taskId;
|
|
478
|
+
this.timeoutMs = timeoutMs;
|
|
479
|
+
}
|
|
480
|
+
};
|
|
466
481
|
var NonDeterminismError = class extends Error {
|
|
467
482
|
static {
|
|
468
483
|
__name(this, "NonDeterminismError");
|
|
@@ -476,6 +491,19 @@ var NonDeterminismError = class extends Error {
|
|
|
476
491
|
this.seq = seq;
|
|
477
492
|
}
|
|
478
493
|
};
|
|
494
|
+
var GatherError = class extends Error {
|
|
495
|
+
static {
|
|
496
|
+
__name(this, "GatherError");
|
|
497
|
+
}
|
|
498
|
+
failures;
|
|
499
|
+
constructor(failures, total) {
|
|
500
|
+
const ids = failures.map((f) => f.id).join(", ");
|
|
501
|
+
const denom = total ?? failures.length;
|
|
502
|
+
super(`ctx.all: ${failures.length} of ${denom} child(ren) failed: ${ids}`);
|
|
503
|
+
this.name = "GatherError";
|
|
504
|
+
this.failures = failures;
|
|
505
|
+
}
|
|
506
|
+
};
|
|
479
507
|
var WorkflowSuspended = class extends Error {
|
|
480
508
|
static {
|
|
481
509
|
__name(this, "WorkflowSuspended");
|
|
@@ -1145,6 +1173,72 @@ function createWorkflowCtx(host, runId, compensations, workflow = "") {
|
|
|
1145
1173
|
}
|
|
1146
1174
|
throw new WorkflowSuspended();
|
|
1147
1175
|
}, "child");
|
|
1176
|
+
const all = /* @__PURE__ */ __name(async (workflow2, inputs, opts) => {
|
|
1177
|
+
if (inputs.length === 0) return [];
|
|
1178
|
+
const mode = opts?.mode ?? "waitAll";
|
|
1179
|
+
const name = workflowName(workflow2);
|
|
1180
|
+
const positions = inputs.map(() => pos.next());
|
|
1181
|
+
const group = `all:${positions[0]}`;
|
|
1182
|
+
const id = /* @__PURE__ */ __name((i) => `${runId}.all.${positions[0]}.${i}`, "id");
|
|
1183
|
+
const existing = await Promise.all(positions.map((seq) => readCheckpoint(seq)));
|
|
1184
|
+
if (mode === "failFast") {
|
|
1185
|
+
for (let i = 0; i < inputs.length; i += 1) {
|
|
1186
|
+
const cp = existing[i];
|
|
1187
|
+
const c = cp?.status === "completed" ? cp.output : null;
|
|
1188
|
+
if (c && c.ok === false) {
|
|
1189
|
+
throw new GatherError([
|
|
1190
|
+
{
|
|
1191
|
+
index: i,
|
|
1192
|
+
id: id(i),
|
|
1193
|
+
error: c.error ?? "unknown"
|
|
1194
|
+
}
|
|
1195
|
+
], inputs.length);
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
let pending = false;
|
|
1200
|
+
for (let i = 0; i < inputs.length; i += 1) {
|
|
1201
|
+
const cp = existing[i];
|
|
1202
|
+
if (cp?.status === "completed") continue;
|
|
1203
|
+
pending = true;
|
|
1204
|
+
const seq = positions[i];
|
|
1205
|
+
const childId = id(i);
|
|
1206
|
+
await store.putSignalWaiter({
|
|
1207
|
+
token: `child:${childId}`,
|
|
1208
|
+
runId,
|
|
1209
|
+
seq
|
|
1210
|
+
});
|
|
1211
|
+
if (!await store.getRun(childId)) host.startChild(name, inputs[i], childId);
|
|
1212
|
+
if (!cp) {
|
|
1213
|
+
await writeCheckpoint(instantCheckpoint({
|
|
1214
|
+
runId,
|
|
1215
|
+
seq,
|
|
1216
|
+
name: `signal:child:${childId}`,
|
|
1217
|
+
kind: "signal",
|
|
1218
|
+
status: "running",
|
|
1219
|
+
parallelGroup: group
|
|
1220
|
+
}));
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
if (pending) throw new WorkflowSuspended();
|
|
1224
|
+
const outputs = [];
|
|
1225
|
+
const failures = [];
|
|
1226
|
+
for (let i = 0; i < inputs.length; i += 1) {
|
|
1227
|
+
const c = existing[i]?.output;
|
|
1228
|
+
if (c && typeof c === "object" && "ok" in c && c.ok === false) {
|
|
1229
|
+
failures.push({
|
|
1230
|
+
index: i,
|
|
1231
|
+
id: id(i),
|
|
1232
|
+
error: c.error ?? "unknown"
|
|
1233
|
+
});
|
|
1234
|
+
outputs.push(void 0);
|
|
1235
|
+
} else {
|
|
1236
|
+
outputs.push(c?.value);
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
if (failures.length > 0) throw new GatherError(failures, inputs.length);
|
|
1240
|
+
return outputs;
|
|
1241
|
+
}, "all");
|
|
1148
1242
|
const startChild = /* @__PURE__ */ __name(async (workflow2, input, options) => {
|
|
1149
1243
|
const { childId, priority } = normalizeChildOptions(options);
|
|
1150
1244
|
const current = pos.next();
|
|
@@ -1279,6 +1373,7 @@ function createWorkflowCtx(host, runId, compensations, workflow = "") {
|
|
|
1279
1373
|
waitForEvent,
|
|
1280
1374
|
task,
|
|
1281
1375
|
child,
|
|
1376
|
+
all,
|
|
1282
1377
|
startChild,
|
|
1283
1378
|
breakpoint,
|
|
1284
1379
|
webhook,
|
|
@@ -2268,7 +2363,8 @@ var WorkflowEngine = class {
|
|
|
2268
2363
|
attempts: 1,
|
|
2269
2364
|
enqueuedAt: startedAt,
|
|
2270
2365
|
startedAt,
|
|
2271
|
-
finishedAt: startedAt
|
|
2366
|
+
finishedAt: startedAt,
|
|
2367
|
+
parallelGroup: event.parallelGroup
|
|
2272
2368
|
}));
|
|
2273
2369
|
this.emit({
|
|
2274
2370
|
type: "step.started",
|
|
@@ -2292,7 +2388,8 @@ var WorkflowEngine = class {
|
|
|
2292
2388
|
attempts: 1,
|
|
2293
2389
|
enqueuedAt: startedAt,
|
|
2294
2390
|
startedAt,
|
|
2295
|
-
finishedAt: event.finishedAt != null ? new Date(event.finishedAt) : /* @__PURE__ */ new Date()
|
|
2391
|
+
finishedAt: event.finishedAt != null ? new Date(event.finishedAt) : /* @__PURE__ */ new Date(),
|
|
2392
|
+
parallelGroup: event.parallelGroup
|
|
2296
2393
|
}));
|
|
2297
2394
|
this.emit({
|
|
2298
2395
|
type: failed ? "step.failed" : "step.completed",
|
|
@@ -2529,6 +2626,13 @@ var WorkflowEngine = class {
|
|
|
2529
2626
|
try {
|
|
2530
2627
|
decision = await remote.executor.advance(run, history);
|
|
2531
2628
|
} catch (err) {
|
|
2629
|
+
if (err instanceof RemoteWorkflowTimeout) {
|
|
2630
|
+
await this.store.releaseRunLock(run.id);
|
|
2631
|
+
return {
|
|
2632
|
+
runId: run.id,
|
|
2633
|
+
status: "running"
|
|
2634
|
+
};
|
|
2635
|
+
}
|
|
2532
2636
|
const error = {
|
|
2533
2637
|
message: err instanceof Error ? err.message : String(err),
|
|
2534
2638
|
stack: err instanceof Error ? err.stack : void 0
|
|
@@ -2648,7 +2752,11 @@ var WorkflowEngine = class {
|
|
|
2648
2752
|
attempts: 1,
|
|
2649
2753
|
enqueuedAt: startedAt,
|
|
2650
2754
|
startedAt,
|
|
2651
|
-
finishedAt
|
|
2755
|
+
finishedAt,
|
|
2756
|
+
// Carry the worker's `parallelGroup` (a Python `ctx.gather` tags every step in the fan with
|
|
2757
|
+
// the same group) onto the checkpoint, so the dashboard can render the steps as one parallel
|
|
2758
|
+
// group instead of a sequential list. Additive: undefined for ordinary sequential steps.
|
|
2759
|
+
parallelGroup: cmd.parallelGroup
|
|
2652
2760
|
}));
|
|
2653
2761
|
this.emit({
|
|
2654
2762
|
type: cmd.error ? "step.failed" : "step.completed",
|
|
@@ -3283,11 +3391,12 @@ var RemoteWorkflowExecutor = class {
|
|
|
3283
3391
|
};
|
|
3284
3392
|
const decision = new Promise((resolve, reject) => {
|
|
3285
3393
|
this.pending.set(taskId, resolve);
|
|
3286
|
-
|
|
3394
|
+
const { timeoutMs } = this.opts;
|
|
3395
|
+
if (timeoutMs) {
|
|
3287
3396
|
const timer = setTimeout(() => {
|
|
3288
3397
|
this.pending.delete(taskId);
|
|
3289
|
-
reject(new
|
|
3290
|
-
},
|
|
3398
|
+
reject(new RemoteWorkflowTimeout(taskId, timeoutMs));
|
|
3399
|
+
}, timeoutMs);
|
|
3291
3400
|
timer.unref?.();
|
|
3292
3401
|
}
|
|
3293
3402
|
});
|
|
@@ -4014,6 +4123,7 @@ export {
|
|
|
4014
4123
|
Entities,
|
|
4015
4124
|
EventAccumulators,
|
|
4016
4125
|
FatalError,
|
|
4126
|
+
GatherError,
|
|
4017
4127
|
InMemoryAdmissionBackend,
|
|
4018
4128
|
InMemoryStateStore,
|
|
4019
4129
|
InMemoryTransport,
|
|
@@ -4022,6 +4132,7 @@ export {
|
|
|
4022
4132
|
RemoteStepError,
|
|
4023
4133
|
RemoteStepTimeout,
|
|
4024
4134
|
RemoteWorkflowExecutor,
|
|
4135
|
+
RemoteWorkflowTimeout,
|
|
4025
4136
|
STATE_STORE,
|
|
4026
4137
|
STATE_STORE_CANONICAL,
|
|
4027
4138
|
SignalTimeoutError,
|
|
@@ -4036,6 +4147,7 @@ export {
|
|
|
4036
4147
|
attributeOperand,
|
|
4037
4148
|
breakpointToken,
|
|
4038
4149
|
collectMetrics,
|
|
4150
|
+
createStepLogger,
|
|
4039
4151
|
eventMatchOf,
|
|
4040
4152
|
eventMatches,
|
|
4041
4153
|
eventPrefix,
|