eve 0.48.0 → 0.49.1
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/CHANGELOG.md +26 -0
- package/dist/src/channel/channel-address.js +1 -1
- package/dist/src/channel/types.d.ts +10 -0
- package/dist/src/cli/commands/integration-setup.d.ts +1 -0
- package/dist/src/cli/commands/integration-setup.js +1 -1
- package/dist/src/cli/commands/register-integration-commands.d.ts +1 -1
- package/dist/src/cli/commands/register-integration-commands.js +1 -1
- package/dist/src/cli/commands/registry-declared-setups.d.ts +1 -0
- package/dist/src/cli/commands/registry-declared-setups.js +1 -1
- package/dist/src/cli/commands/registry-metadata.d.ts +30 -0
- package/dist/src/cli/commands/registry-metadata.js +1 -1
- package/dist/src/cli/commands/registry-package.d.ts +6 -0
- package/dist/src/cli/commands/registry-package.js +1 -1
- package/dist/src/cli/commands/registry-pnpm-build-policy-flow.d.ts +30 -0
- package/dist/src/cli/commands/registry-pnpm-build-policy-flow.js +1 -0
- package/dist/src/cli/commands/registry-pnpm-build-policy.d.ts +12 -0
- package/dist/src/cli/commands/registry-pnpm-build-policy.js +6 -0
- package/dist/src/cli/commands/registry-recovery.d.ts +4 -0
- package/dist/src/cli/commands/registry-recovery.js +1 -1
- package/dist/src/cli/commands/registry.d.ts +1 -1
- package/dist/src/cli/commands/registry.js +1 -1
- package/dist/src/cli/dev/tui/setup-commands.js +2 -2
- package/dist/src/compiled/.vendor-stamp.json +7 -7
- package/dist/src/compiled/@workflow/core/attribute-changes.d.ts +2 -4
- package/dist/src/compiled/@workflow/core/capabilities.d.ts +10 -9
- package/dist/src/compiled/@workflow/core/capture-stack.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/class-serialization.d.ts +8 -8
- package/dist/src/compiled/@workflow/core/context-violation-error.d.ts +5 -5
- package/dist/src/compiled/@workflow/core/create-hook.d.ts +2 -2
- package/dist/src/compiled/@workflow/core/describe-error.d.ts +7 -7
- package/dist/src/compiled/@workflow/core/encryption.d.ts +5 -5
- package/dist/src/compiled/@workflow/core/events-consumer.d.ts +49 -14
- package/dist/src/compiled/@workflow/core/flushable-stream.d.ts +4 -4
- package/dist/src/compiled/@workflow/core/global.d.ts +4 -2
- package/dist/src/compiled/@workflow/core/index.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/index.js +2 -2
- package/dist/src/compiled/@workflow/core/log-format.d.ts +2 -2
- package/dist/src/compiled/@workflow/core/private.d.ts +40 -78
- package/dist/src/compiled/@workflow/core/private.js +1 -1
- package/dist/src/compiled/@workflow/core/replay-payload-cache.d.ts +13 -17
- package/dist/src/compiled/@workflow/core/runtime/compute-instance.d.ts +4 -3
- package/dist/src/compiled/@workflow/core/runtime/constants.d.ts +27 -27
- package/dist/src/compiled/@workflow/core/runtime/count-step-started-events.d.ts +7 -7
- package/dist/src/compiled/@workflow/core/runtime/deployment-guard.d.ts +7 -7
- package/dist/src/compiled/@workflow/core/runtime/get-port-lazy.d.ts +2 -2
- package/dist/src/compiled/@workflow/core/runtime/get-world-lazy.d.ts +2 -2
- package/dist/src/compiled/@workflow/core/runtime/helpers.d.ts +30 -49
- package/dist/src/compiled/@workflow/core/runtime/quickjs-entrypoint.d.ts +21 -10
- package/dist/src/compiled/@workflow/core/runtime/quickjs-runtime.d.ts +31 -15
- package/dist/src/compiled/@workflow/core/runtime/quickjs-serde.d.ts +10 -10
- package/dist/src/compiled/@workflow/core/runtime/replay-budget.d.ts +4 -4
- package/dist/src/compiled/@workflow/core/runtime/replay-recovery-reporter.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/runtime/resume-hook.d.ts +20 -12
- package/dist/src/compiled/@workflow/core/runtime/resume-latency.d.ts +37 -30
- package/dist/src/compiled/@workflow/core/runtime/run-id-time.d.ts +2 -2
- package/dist/src/compiled/@workflow/core/runtime/run.d.ts +22 -5
- package/dist/src/compiled/@workflow/core/runtime/runs.d.ts +4 -4
- package/dist/src/compiled/@workflow/core/runtime/start.d.ts +3 -3
- package/dist/src/compiled/@workflow/core/runtime/step-executor.d.ts +14 -14
- package/dist/src/compiled/@workflow/core/runtime/step-latency.d.ts +42 -25
- package/dist/src/compiled/@workflow/core/runtime/step-ownership.d.ts +6 -6
- package/dist/src/compiled/@workflow/core/runtime/step-single-flight.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/runtime/suspension-handler.d.ts +38 -24
- package/dist/src/compiled/@workflow/core/runtime/unserializable-step.d.ts +34 -0
- package/dist/src/compiled/@workflow/core/runtime/vm-mode.d.ts +2 -2
- package/dist/src/compiled/@workflow/core/runtime/wait-continuation.d.ts +31 -9
- package/dist/src/compiled/@workflow/core/runtime/wait-until.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/runtime/world-compatibility.d.ts +20 -9
- package/dist/src/compiled/@workflow/core/runtime/world-init.d.ts +5 -5
- package/dist/src/compiled/@workflow/core/runtime.js +3 -3
- package/dist/src/compiled/@workflow/core/sealed-box.d.ts +7 -7
- package/dist/src/compiled/@workflow/core/serialization/codec-devalue-vm.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/serialization/codec-devalue.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/serialization/codec.d.ts +4 -4
- package/dist/src/compiled/@workflow/core/serialization/compression.d.ts +12 -11
- package/dist/src/compiled/@workflow/core/serialization/encryption.d.ts +7 -7
- package/dist/src/compiled/@workflow/core/serialization/format.d.ts +6 -6
- package/dist/src/compiled/@workflow/core/serialization/hardened.d.ts +23 -22
- package/dist/src/compiled/@workflow/core/serialization/index.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/serialization/reducers/class-vm.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/serialization/reducers/step-function-vm.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/serialization/types.d.ts +5 -5
- package/dist/src/compiled/@workflow/core/serialization/workflow-vm.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/serialization-format.d.ts +11 -11
- package/dist/src/compiled/@workflow/core/serialization.d.ts +18 -19
- package/dist/src/compiled/@workflow/core/source-map.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/step/context-storage.d.ts +5 -5
- package/dist/src/compiled/@workflow/core/step/writable-stream.d.ts +3 -3
- package/dist/src/compiled/@workflow/core/symbols.d.ts +2 -2
- package/dist/src/compiled/@workflow/core/telemetry/semantic-conventions.d.ts +71 -20
- package/dist/src/compiled/@workflow/core/telemetry.d.ts +15 -3
- package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/vm/script-cache.d.ts +9 -11
- package/dist/src/compiled/@workflow/core/workflow/abort-controller.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/workflow/set-attributes.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/workflow/world-init-stub.d.ts +1 -1
- package/dist/src/compiled/@workflow/core/workflow.js +1 -1
- package/dist/src/compiled/@workflow/errors/index.d.ts +18 -18
- package/dist/src/compiled/@workflow/errors/index.js +1 -1
- package/dist/src/compiled/@workflow/world/analytics.d.ts +3 -2
- package/dist/src/compiled/@workflow/world/attributes-validation.d.ts +28 -0
- package/dist/src/compiled/@workflow/world/attributes.d.ts +8 -107
- package/dist/src/compiled/@workflow/world/env-config.d.ts +5 -5
- package/dist/src/compiled/@workflow/world/event-metadata.d.ts +132 -0
- package/dist/src/compiled/@workflow/world/events.d.ts +42 -96
- package/dist/src/compiled/@workflow/world/hooks.d.ts +12 -11
- package/dist/src/compiled/@workflow/world/index.d.ts +3 -3
- package/dist/src/compiled/@workflow/world/interfaces.d.ts +94 -39
- package/dist/src/compiled/@workflow/world/queue.d.ts +29 -22
- package/dist/src/compiled/@workflow/world/runs.d.ts +20 -0
- package/dist/src/compiled/@workflow/world/slot-identity.d.ts +3 -3
- package/dist/src/compiled/@workflow/world/spec-version.d.ts +82 -15
- package/dist/src/compiled/@workflow/world/ulid.d.ts +2 -2
- package/dist/src/compiled/@workflow/world-local/index.js +5 -5
- package/dist/src/compiled/@workflow/world-vercel/index.js +12 -12
- package/dist/src/compiled/_chunks/workflow/{attribute-changes-DXbpwBdw.js → attribute-changes-BwAadFfB.js} +3 -3
- package/dist/src/compiled/_chunks/workflow/debug-log-CVPstO1D.js +1 -0
- package/dist/src/compiled/_chunks/workflow/dist-CgbVZs5l.js +40 -0
- package/dist/src/compiled/_chunks/workflow/dist-DjojkP5e.js +3 -0
- package/dist/src/compiled/_chunks/workflow/frames-CZ9eHShe.js +3 -0
- package/dist/src/compiled/_chunks/workflow/global-singleton-BNinwFrL.js +1 -0
- package/dist/src/compiled/_chunks/workflow/private-CZFMABEf.js +1 -0
- package/dist/src/compiled/_chunks/workflow/resume-hook-BToMtPbH.js +1 -0
- package/dist/src/compiled/_chunks/workflow/run-DzyAoGh4.js +1 -0
- package/dist/src/compiled/_chunks/workflow/sleep-3_A5uOp-.js +1 -0
- package/dist/src/compiled/_chunks/workflow/undici-DfxNX5og.js +95 -0
- package/dist/src/compiled/_chunks/workflow/wait-until-BtySPYD0.js +15 -0
- package/dist/src/compiled/_chunks/workflow/ws-transport-PnVVxT0R.js +1 -0
- package/dist/src/eve-channel/index.js +1 -1
- package/dist/src/execution/agent-handle-dispatch.js +1 -1
- package/dist/src/execution/continuation-conflict-step.d.ts +10 -0
- package/dist/src/execution/continuation-conflict-step.js +1 -0
- package/dist/src/execution/delegated-parent-notification.js +1 -1
- package/dist/src/execution/dispatch-runtime-actions-shared.d.ts +7 -29
- package/dist/src/execution/dispatch-runtime-actions-shared.js +1 -1
- package/dist/src/execution/dispatch-runtime-actions-start.d.ts +33 -0
- package/dist/src/execution/dispatch-runtime-actions-start.js +1 -0
- package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
- package/dist/src/execution/dispatch-turn-step.js +1 -1
- package/dist/src/execution/dynamic-connections.js +1 -1
- package/dist/src/execution/inline-turn.js +1 -1
- package/dist/src/execution/next-driver-action.d.ts +5 -4
- package/dist/src/execution/proxied-deliver-step.js +1 -1
- package/dist/src/execution/runtime-errors.d.ts +0 -12
- package/dist/src/execution/runtime-errors.js +1 -1
- package/dist/src/execution/sandbox/bindings/docker-options.d.ts +1 -1
- package/dist/src/execution/sandbox/bindings/docker-options.js +1 -1
- package/dist/src/execution/sandbox/bindings/eve-image.d.ts +4 -0
- package/dist/src/execution/sandbox/bindings/eve-image.js +1 -0
- package/dist/src/execution/sandbox/bindings/microsandbox-options.d.ts +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-options.js +1 -1
- package/dist/src/execution/sandbox/bindings/vercel-create-sdk.js +1 -1
- package/dist/src/execution/session-timeout-steps.js +1 -1
- package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
- package/dist/src/execution/stable-workflow-names.d.ts +2 -2
- package/dist/src/execution/subagent-start-local.js +1 -1
- package/dist/src/execution/tasks/parent/dispatch-task-step.js +1 -1
- package/dist/src/execution/tasks/parent/run-parent.js +1 -1
- package/dist/src/execution/tasks/parent/tool-execution.js +1 -1
- package/dist/src/execution/tool-run/start.js +1 -1
- package/dist/src/execution/tools/subagent/local.js +1 -1
- package/dist/src/execution/turn-workflow.js +1 -1
- package/dist/src/execution/workflow-entry.d.ts +5 -1
- package/dist/src/execution/workflow-entry.js +1 -1
- package/dist/src/execution/workflow-runtime.d.ts +12 -12
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/workflow/development-world-client.js +1 -1
- package/dist/src/packages/eve-catalog/src/index.js +1 -1
- package/dist/src/public/channels/slack/activity.d.ts +18 -0
- package/dist/src/public/channels/slack/activity.js +1 -0
- package/dist/src/public/channels/slack/api.js +1 -1
- package/dist/src/public/channels/slack/index.d.ts +1 -0
- package/dist/src/public/channels/slack/index.js +1 -1
- package/dist/src/public/channels/slack/interaction-cards.js +1 -1
- package/dist/src/public/channels/slack/interactions.js +1 -1
- package/dist/src/public/channels/slack/slackChannel.d.ts +12 -1
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/public/memory/file/backends/default.js +1 -1
- package/dist/src/public/sandbox/docker-sandbox.d.ts +5 -4
- package/dist/src/public/sandbox/microsandbox-sandbox.d.ts +1 -1
- package/dist/src/public/sandbox/vercel-sandbox.d.ts +3 -1
- package/dist/src/setup/flows/registry.js +1 -1
- package/dist/src/setup/integrations/file-memory/setup.d.ts +15 -0
- package/dist/src/setup/integrations/file-memory/setup.js +2 -0
- package/dist/src/setup/integrations/file-memory/vercel.d.ts +103 -0
- package/dist/src/setup/integrations/file-memory/vercel.js +1 -0
- package/dist/src/setup/integrations/registry.js +1 -1
- package/dist/src/setup/integrations/shared/vercel-project.js +1 -1
- package/dist/src/setup/scaffold/connections/catalog.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/docs/channels/custom.mdx +4 -0
- package/docs/channels/eve.mdx +12 -8
- package/docs/channels/mcp.mdx +4 -1
- package/docs/channels/slack.mdx +1 -1
- package/docs/guides/instrumentation.md +1 -1
- package/docs/install-integrations.mdx +5 -0
- package/docs/instructions.mdx +1 -1
- package/docs/memory/custom-provider.md +214 -0
- package/docs/memory/file.md +168 -0
- package/docs/memory/meta.json +5 -0
- package/docs/memory/overview.mdx +282 -0
- package/docs/patterns/multi-tenant-memory.md +12 -20
- package/docs/reference/cli.md +28 -23
- package/docs/sandbox.mdx +5 -3
- package/package.json +8 -8
- package/dist/src/compiled/_chunks/workflow/dist-CqvWKNQv.js +0 -3
- package/dist/src/compiled/_chunks/workflow/dist-Dk0aQqFO.js +0 -40
- package/dist/src/compiled/_chunks/workflow/dist-DpYyXbJv.js +0 -1
- package/dist/src/compiled/_chunks/workflow/env-config-L94XftKz.js +0 -1
- package/dist/src/compiled/_chunks/workflow/frames-Dl2Hcma4.js +0 -3
- package/dist/src/compiled/_chunks/workflow/private-CuQ4HTFC.js +0 -1
- package/dist/src/compiled/_chunks/workflow/resume-hook-E-Nkx8q_.js +0 -1
- package/dist/src/compiled/_chunks/workflow/run-cIeex2KF.js +0 -1
- package/dist/src/compiled/_chunks/workflow/sleep-CxFsdxB_.js +0 -1
- package/dist/src/compiled/_chunks/workflow/spec-version-DBUVfF_R.js +0 -1
- package/dist/src/compiled/_chunks/workflow/undici-DznrXKcM.js +0 -95
- package/dist/src/compiled/_chunks/workflow/wait-until-BZHmJCAW.js +0 -15
- package/dist/src/compiled/_chunks/workflow/ws-transport-Ct6yyRWZ.js +0 -1
- package/docs/memory.md +0 -408
|
@@ -41,7 +41,7 @@ export interface StepExecutorParams {
|
|
|
41
41
|
* Pre-claimed inline start: the suspension handler committed (or lost) this
|
|
42
42
|
* step's `step_created` + `step_started` pair inside its batched fan-out
|
|
43
43
|
* write, so the start this executor would otherwise send has already been
|
|
44
|
-
* decided. `owned: false` returns `{ type: 'skipped' }` before any write
|
|
44
|
+
* decided. `owned: false` returns `{ type: 'skipped' }` before any write,
|
|
45
45
|
* the same outcome as losing the lazy claim's atomic create. `owned: true`
|
|
46
46
|
* skips both start paths (no start write at all) and runs the body against
|
|
47
47
|
* the claimed step. Mutually exclusive with `lazyStepInput`: the input
|
|
@@ -51,11 +51,11 @@ export interface StepExecutorParams {
|
|
|
51
51
|
/**
|
|
52
52
|
* Inline step ownership: the queue message ID of the invocation this
|
|
53
53
|
* executeStep call runs in (from the queue handler's meta). When set, the
|
|
54
|
-
* `step_started` this call sends is stamped with it
|
|
54
|
+
* `step_started` this call sends is stamped with it: on the lazy paths
|
|
55
55
|
* (where `lazyStepInput` is present) and on the owned-recovery
|
|
56
56
|
* payload-less start (where it is not; the re-stamp keeps a recovered
|
|
57
57
|
* step readable as owned by this message, since ownership derives from
|
|
58
|
-
* the LATEST start
|
|
58
|
+
* the LATEST start, so a recovery start is never bare). Wake
|
|
59
59
|
* replays that observe an actively-owned step suppress the immediate
|
|
60
60
|
* requeue and enqueue a delayed backstop instead. Omitted on the
|
|
61
61
|
* background-step path, whose bare start intentionally clears ownership
|
|
@@ -82,7 +82,7 @@ export interface StepExecutorParams {
|
|
|
82
82
|
* It matters most on the lazy inline path, where the `step_started` claim is
|
|
83
83
|
* the step's FIRST durable write (its `step_created` is deferred): without a
|
|
84
84
|
* seed the claim would name no position at all, and a replay working from a
|
|
85
|
-
* stale view could claim
|
|
85
|
+
* stale view could claim (and then commit) a step scheduled without
|
|
86
86
|
* observing an event it never loaded.
|
|
87
87
|
*
|
|
88
88
|
* A World that fences rejects a stale claim with `PreconditionFailedError`
|
|
@@ -100,7 +100,7 @@ export interface StepExecutorParams {
|
|
|
100
100
|
* stale-sensitive (an open hook means an out-of-band event can make the
|
|
101
101
|
* scheduling view stale): the guard's 412 fence can reject a stale claim's
|
|
102
102
|
* durable writes, but it cannot un-run a body that optimistic start began
|
|
103
|
-
* before the claim settled
|
|
103
|
+
* before the claim settled; awaiting the claim extends the fence to user
|
|
104
104
|
* code. Wins over `forceOptimisticStart` and the env flag.
|
|
105
105
|
*/
|
|
106
106
|
suppressOptimisticStart?: boolean;
|
|
@@ -116,8 +116,8 @@ export interface StepExecutorParams {
|
|
|
116
116
|
* Turbo mode only: a promise that resolves once the backgrounded
|
|
117
117
|
* `run_started` has landed. When set, the lazy/optimistic `step_started` is
|
|
118
118
|
* chained on it so the step is never created before its run exists. The body
|
|
119
|
-
* still runs immediately against locally-synthesized state
|
|
120
|
-
* write waits
|
|
119
|
+
* still runs immediately against locally-synthesized state (only the network
|
|
120
|
+
* write waits), so the `run_started` round-trip overlaps the body. `undefined`
|
|
121
121
|
* outside turbo, where `run_started` was already awaited up front.
|
|
122
122
|
*/
|
|
123
123
|
runReadyBarrier?: Promise<unknown>;
|
|
@@ -126,7 +126,7 @@ export interface StepExecutorParams {
|
|
|
126
126
|
* by the orchestrator. When set, this executor computes the final values
|
|
127
127
|
* against the wall clock taken immediately before user code runs and
|
|
128
128
|
* attaches them to the step's terminal event. Set only for the first step of
|
|
129
|
-
* an inline batch, and only on first-attempt executions that qualify
|
|
129
|
+
* an inline batch, and only on first-attempt executions that qualify; see
|
|
130
130
|
* runtime/step-latency.ts.
|
|
131
131
|
*/
|
|
132
132
|
latencyTracking?: StepLatencyTracking;
|
|
@@ -136,12 +136,12 @@ export interface StepExecutorParams {
|
|
|
136
136
|
* executor closes the measurement against the `step_started` claim and the
|
|
137
137
|
* wall clock taken immediately before user code, and attaches the total plus
|
|
138
138
|
* its phase breakdown to this step's `step.execute` span. Set by the runtime
|
|
139
|
-
* for exactly one step per resumption
|
|
139
|
+
* for exactly one step per resumption; see runtime/resume-latency.ts.
|
|
140
140
|
*/
|
|
141
141
|
resumeTracking?: ResumeTtrTracking;
|
|
142
142
|
/**
|
|
143
143
|
* Authoritative attempt number for this execution, used to bound retries
|
|
144
|
-
* against `maxRetries` BEFORE the body runs.
|
|
144
|
+
* against `maxRetries` BEFORE the body runs. To also catch
|
|
145
145
|
* step timeouts (which we can't have catch handlers for), we determine
|
|
146
146
|
* the attempt count based as follows:
|
|
147
147
|
* - Inline (combined handler): the number of `step_started` events already
|
|
@@ -171,13 +171,13 @@ export type PreclaimedInlineStart = {
|
|
|
171
171
|
*/
|
|
172
172
|
step: StartedStep;
|
|
173
173
|
/**
|
|
174
|
-
* `Date.now()` taken right before the batch POST that carried the pair
|
|
175
|
-
*
|
|
174
|
+
* `Date.now()` taken right before the batch POST that carried the pair:
|
|
175
|
+
* the claim's "start POST sent" instant, anchoring RSFS exactly like
|
|
176
176
|
* the lazy claim's own POST would.
|
|
177
177
|
*/
|
|
178
178
|
batchPostSentAtMs?: number;
|
|
179
179
|
/**
|
|
180
|
-
* `Date.now()` taken right after that batch POST returned
|
|
180
|
+
* `Date.now()` taken right after that batch POST returned: the
|
|
181
181
|
* claim's completion instant (T6 of the hook-resume TTR window).
|
|
182
182
|
*/
|
|
183
183
|
claimCompletedAtMs?: number;
|
|
@@ -233,7 +233,7 @@ export type StepExecutionResult = {
|
|
|
233
233
|
* Executes a single step: creates step_started event, hydrates input,
|
|
234
234
|
* runs the step function, creates step_completed/step_failed/step_retrying events.
|
|
235
235
|
*
|
|
236
|
-
* Does NOT queue workflow continuation messages
|
|
236
|
+
* Does NOT queue workflow continuation messages; the caller decides what to do next.
|
|
237
237
|
* Used by the combined workflow handler for step execution.
|
|
238
238
|
*/
|
|
239
239
|
export declare function executeStep(params: StepExecutorParams): Promise<StepExecutionResult>;
|
|
@@ -7,11 +7,11 @@ import type { Event } from '#compiled/@workflow/world/index.js';
|
|
|
7
7
|
* beginning to execute. STSO (step-to-step overhead) measures the previous
|
|
8
8
|
* step's terminal event → the next step's body beginning to execute. RSFS
|
|
9
9
|
* (run-started-to-first-step) measures the `run_started` response landing →
|
|
10
|
-
* the first step's start POST being issued
|
|
10
|
+
* the first step's start POST being issued, a sub-window of TTFS that
|
|
11
11
|
* isolates replay overhead from the run-creation queue hop; `finalSchedulingReplay`
|
|
12
12
|
* is the synchronous workflow-function-execution duration of only the FINAL
|
|
13
13
|
* replay pass within that window (the pass that reached and scheduled the
|
|
14
|
-
* first step)
|
|
14
|
+
* first step); it is NOT accumulated across earlier pre-first-step passes
|
|
15
15
|
* (see {@link StepLatencyTracking.replayMs}), so it must not be read as "the
|
|
16
16
|
* replay portion of RSFS". All are attached to the step's terminal
|
|
17
17
|
* event so a backend can emit latency metrics from the event write alone,
|
|
@@ -42,7 +42,7 @@ export interface StepLatencyTracking {
|
|
|
42
42
|
* workflow-body `setAttributes` before the first step
|
|
43
43
|
* resolves through an extra replay (see the `hasAttributeEvents` branch in
|
|
44
44
|
* runtime.ts), so everything from this write until the step body runs is
|
|
45
|
-
* the duration of the setAttributes call
|
|
45
|
+
* the duration of the setAttributes call, which is subtracted by ending
|
|
46
46
|
* the measurement at the point where the step would otherwise have been
|
|
47
47
|
* scheduled.
|
|
48
48
|
*/
|
|
@@ -59,7 +59,7 @@ export interface StepLatencyTracking {
|
|
|
59
59
|
eventCount?: number;
|
|
60
60
|
/**
|
|
61
61
|
* Epoch ms the `run_started` response was received/parsed by the SDK.
|
|
62
|
-
* Present only when the step qualifies for RSFS
|
|
62
|
+
* Present only when the step qualifies for RSFS: the same eligibility as
|
|
63
63
|
* TTFS (see {@link computeStepLatencyTracking}), plus a recoverable
|
|
64
64
|
* anchor. In turbo mode, `run_started` is backgrounded rather than
|
|
65
65
|
* awaited, so this is stamped at the point the runtime synthesizes the
|
|
@@ -74,21 +74,30 @@ export interface StepLatencyTracking {
|
|
|
74
74
|
* Wall-clock ms this invocation's synchronous workflow-function replay
|
|
75
75
|
* took: from calling `runWorkflow` to it throwing the suspension that
|
|
76
76
|
* scheduled this batch. Excludes awaited network I/O (the suspension's
|
|
77
|
-
* event commits, the step's own start POST).
|
|
78
|
-
*
|
|
77
|
+
* event commits, the step's own start POST). Reported for every batch that
|
|
78
|
+
* qualifies for TTFS or STSO, not just the first step.
|
|
79
79
|
*
|
|
80
|
-
* This is the FINAL
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
80
|
+
* This is the FINAL pass only: the one that reached and scheduled this
|
|
81
|
+
* batch. Valid RSFS paths can replay more than once before the first step
|
|
82
|
+
* (e.g. a workflow-body `setAttributes()` detour replays twice), and a
|
|
83
|
+
* redelivery omits earlier invocations' replay work entirely; this value is
|
|
84
|
+
* not accumulated across those earlier passes. Do not read it as "the
|
|
85
|
+
* replay portion of RSFS": RSFS ({@link rsfsAnchorMs}) covers the whole
|
|
86
|
+
* run_started-to-first-step window, this covers only the last pass.
|
|
87
|
+
*
|
|
88
|
+
* On a retained resume this measures the resume, not a replay, which is
|
|
89
|
+
* why the distribution is bimodal and why {@link retained} is reported
|
|
90
|
+
* alongside it as the dimension that separates the two modes.
|
|
88
91
|
*/
|
|
89
92
|
replayMs?: number;
|
|
90
93
|
/** Whether turbo mode is active for this invocation. */
|
|
91
94
|
turbo: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Whether a retained VM session served this batch, as opposed to a full
|
|
97
|
+
* replay from the event log. Reported as a `retained` entry in
|
|
98
|
+
* {@link StepLatencyEventData.optimizations}, alongside `turbo`.
|
|
99
|
+
*/
|
|
100
|
+
retained: boolean;
|
|
92
101
|
}
|
|
93
102
|
/** Latency telemetry attached to a step's terminal event's `eventData`. */
|
|
94
103
|
export interface StepLatencyEventData {
|
|
@@ -99,12 +108,18 @@ export interface StepLatencyEventData {
|
|
|
99
108
|
/** Client-measured run_started → first step's start POST, ms. */
|
|
100
109
|
rsfs?: number;
|
|
101
110
|
/**
|
|
102
|
-
* Client-measured wall-clock ms of the FINAL
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
111
|
+
* Client-measured wall-clock ms of the FINAL pass that scheduled this
|
|
112
|
+
* batch (see {@link StepLatencyTracking.replayMs}); not accumulated
|
|
113
|
+
* across earlier passes, so it must not be read as "the replay portion of
|
|
114
|
+
* `rsfs`". Present whenever `ttfs` or `stso` is.
|
|
106
115
|
*/
|
|
107
116
|
finalSchedulingReplay?: number;
|
|
117
|
+
/**
|
|
118
|
+
* Active runtime modes for this measurement: `turbo`, `lazyStepStart`,
|
|
119
|
+
* `optimisticStart`, and `retained` (a retained VM served the batch; its
|
|
120
|
+
* absence means a full replay). The server turns each known entry into a
|
|
121
|
+
* bounded boolean tag on every latency metric.
|
|
122
|
+
*/
|
|
108
123
|
optimizations?: string[];
|
|
109
124
|
}
|
|
110
125
|
/**
|
|
@@ -131,13 +146,13 @@ export declare function computeStepLatencyTracking(params: {
|
|
|
131
146
|
runCreatedAtMs: number | undefined;
|
|
132
147
|
/**
|
|
133
148
|
* Epoch ms the `run_started` response was received/parsed by the SDK (or,
|
|
134
|
-
* under turbo, the instant the run was synthesized locally
|
|
149
|
+
* under turbo, the instant the run was synthesized locally; see
|
|
135
150
|
* {@link StepLatencyTracking.rsfsAnchorMs}). Absent disqualifies RSFS.
|
|
136
151
|
*/
|
|
137
152
|
runStartedReceivedAtMs: number | undefined;
|
|
138
153
|
/**
|
|
139
154
|
* Wall-clock ms this suspension's `runWorkflow` call spent executing
|
|
140
|
-
* synchronously before throwing
|
|
155
|
+
* synchronously before throwing: the FINAL replay pass only, not
|
|
141
156
|
* accumulated across earlier passes. See
|
|
142
157
|
* {@link StepLatencyTracking.replayMs}.
|
|
143
158
|
*/
|
|
@@ -148,7 +163,7 @@ export declare function computeStepLatencyTracking(params: {
|
|
|
148
163
|
* The accumulator's value as of the suspension that wrote the run's first
|
|
149
164
|
* attr_set (its hook phase runs before its attr writes). When the
|
|
150
165
|
* measurement ends at the attr write, only hook time from before that
|
|
151
|
-
* point may be subtracted
|
|
166
|
+
* point may be subtracted; later hook writes fall outside the measured
|
|
152
167
|
* window. Undefined when no attr suspension happened in this invocation
|
|
153
168
|
* (e.g. the attr_set was loaded from a redelivery's snapshot, where no
|
|
154
169
|
* same-invocation hook time precedes it).
|
|
@@ -157,25 +172,27 @@ export declare function computeStepLatencyTracking(params: {
|
|
|
157
172
|
/**
|
|
158
173
|
* Whether the suspension that scheduled this batch also created waits.
|
|
159
174
|
* Those `wait_created` writes are not in `events` yet (they were committed
|
|
160
|
-
* by this
|
|
175
|
+
* by this suspension pass), so they must be reported separately. A
|
|
161
176
|
* wait disqualifies both measurements.
|
|
162
177
|
*/
|
|
163
178
|
suspensionHasWaits: boolean;
|
|
164
179
|
/**
|
|
165
180
|
* Whether the suspension that scheduled this batch also created hooks
|
|
166
|
-
* (also not in `events` yet). Hooks keep TTFS eligible
|
|
167
|
-
* write time is subtracted via `preStepBlockingMs`
|
|
181
|
+
* (also not in `events` yet). Hooks keep TTFS eligible (their measured
|
|
182
|
+
* write time is subtracted via `preStepBlockingMs`) but disqualify STSO,
|
|
168
183
|
* which is only meaningful for a pure back-to-back step gap.
|
|
169
184
|
*/
|
|
170
185
|
suspensionCreatedHooks: boolean;
|
|
171
186
|
/** Whether turbo mode is active for this invocation. */
|
|
172
187
|
turbo: boolean;
|
|
188
|
+
/** See {@link StepLatencyTracking.retained}. */
|
|
189
|
+
retained: boolean;
|
|
173
190
|
}): StepLatencyTracking | undefined;
|
|
174
191
|
/**
|
|
175
192
|
* Compute the latency telemetry to attach to the step's terminal event.
|
|
176
193
|
* Called by `executeStep` with the wall-clock timestamp taken immediately
|
|
177
194
|
* before user step code runs. Returns undefined when there is nothing to
|
|
178
|
-
* report (no tracking, or a retry attempt
|
|
195
|
+
* report (no tracking, or a retry attempt; retries measure neither TTFS nor
|
|
179
196
|
* STSO).
|
|
180
197
|
*/
|
|
181
198
|
export declare function computeStepLatencyEventData(params: {
|
|
@@ -18,13 +18,13 @@ export declare function isStepOwnershipActive(step: StepInvocationQueueItem): bo
|
|
|
18
18
|
/**
|
|
19
19
|
* Seconds left on an owned step's liveness lease, anchored at its latest
|
|
20
20
|
* `step_started`. 0 means the lease has expired (or the start timestamp is
|
|
21
|
-
* missing
|
|
21
|
+
* missing, the degraded mode for worlds whose events lack usable
|
|
22
22
|
* timestamps), in which case dispatch falls back to the immediate enqueue.
|
|
23
23
|
*
|
|
24
24
|
* The result is clamped to the configured lease: `lastStartedAt` is the
|
|
25
25
|
* server-stamped event `createdAt` while `nowMs` is the local clock, so a
|
|
26
26
|
* client running behind the server would otherwise compute a remainder
|
|
27
|
-
* LONGER than the lease itself
|
|
27
|
+
* LONGER than the lease itself, and with the lease tuned to the 900s cap,
|
|
28
28
|
* a `delaySeconds` above the queue's per-message maximum, which SQS-backed
|
|
29
29
|
* worlds reject outright (the wake replay's enqueue would throw and ride
|
|
30
30
|
* the redelivery loop). The clamp makes skew strictly harmless; remaining
|
|
@@ -34,14 +34,14 @@ export declare function stepLeaseRemainingSeconds(step: StepInvocationQueueItem,
|
|
|
34
34
|
/**
|
|
35
35
|
* Idempotency key for the delayed backstop wake of an inline-owned step.
|
|
36
36
|
*
|
|
37
|
-
* The key is scoped to the current OWNERSHIP EPOCH
|
|
38
|
-
* latest `step_started`
|
|
37
|
+
* The key is scoped to the current OWNERSHIP EPOCH (the timestamp of the
|
|
38
|
+
* latest `step_started`), not just the correlation ID. Within one epoch,
|
|
39
39
|
* every wake replay derives the same key, so fan-out stays capped at one
|
|
40
40
|
* pending backstop per step. But when owner recovery re-stamps the step
|
|
41
41
|
* (queue redelivery of the owning message → new `step_started` → new
|
|
42
42
|
* `lastStartedAt`), the key CHANGES. This is load-bearing for liveness:
|
|
43
43
|
* queues dedupe an idempotency key for the lifetime of the original
|
|
44
|
-
* message
|
|
44
|
+
* message (including while a delivery of it is in flight), so a backstop
|
|
45
45
|
* that fires during a refreshed lease and tries to re-arm under a fixed key
|
|
46
46
|
* would dedupe against ITSELF and be dropped, leaving no escape hatch if
|
|
47
47
|
* the recovered owner later dies without further redeliveries. The epoch
|
|
@@ -56,7 +56,7 @@ export declare function stepLeaseRemainingSeconds(step: StepInvocationQueueItem,
|
|
|
56
56
|
* The key must also never be the step message's own `idempotencyKey`
|
|
57
57
|
* (the bare correlation ID): the owner's retry handoff enqueues the step
|
|
58
58
|
* under that key with a short backoff, and a pending backstop sharing it
|
|
59
|
-
* would absorb the retry
|
|
59
|
+
* would absorb the retry, turning a 1s backoff into a full-lease stall.
|
|
60
60
|
*/
|
|
61
61
|
export declare function backstopIdempotencyKey(step: StepInvocationQueueItem): string;
|
|
62
62
|
/**
|
|
@@ -4,7 +4,7 @@ import type { StepExecutionResult } from './step-executor.js';
|
|
|
4
4
|
* already in flight in this process. The winner's result is returned to the
|
|
5
5
|
* winner; a loser awaits the winner's settlement (success OR failure) and
|
|
6
6
|
* then returns `{ type: 'skipped' }` so its caller acks without running the
|
|
7
|
-
* body. A winner failure is not propagated to the loser
|
|
7
|
+
* body. A winner failure is not propagated to the loser: the winner's own
|
|
8
8
|
* queue message redelivers and drives the retry, so exactly one message
|
|
9
9
|
* keeps owning the outcome.
|
|
10
10
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Span } from '#compiled/@opentelemetry/api/index.js';
|
|
2
2
|
import { type SerializedData, type TraceCarrier, type ValidQueueName, type WorkflowRun, type World } from '#compiled/@workflow/world/index.js';
|
|
3
3
|
import type { StepInvocationQueueItem, WorkflowSuspension } from '../global.js';
|
|
4
|
+
import { type GuestCodeExecution } from '../serialization/hardened.js';
|
|
4
5
|
import { type LoadedEventLog } from './helpers.js';
|
|
5
6
|
import { ReplayRecoveryReporter } from './replay-recovery-reporter.js';
|
|
6
7
|
import type { PreclaimedInlineStart } from './step-executor.js';
|
|
@@ -13,7 +14,7 @@ export interface SuspensionHandlerParams {
|
|
|
13
14
|
/**
|
|
14
15
|
* The runtime's loaded event log. Every event creation this suspension makes
|
|
15
16
|
* names the position it was derived from, so a backend that has recorded
|
|
16
|
-
* events the replay did not see can report them back on the write
|
|
17
|
+
* events the replay did not see can report them back on the write, or, if
|
|
17
18
|
* it would rather refuse than report, reject it with a 412. A rejection is
|
|
18
19
|
* not retried here: the event's correlation id was minted by *this* replay's
|
|
19
20
|
* seeded sequence, so re-committing it against a corrected log would persist
|
|
@@ -35,14 +36,14 @@ export interface SuspensionHandlerParams {
|
|
|
35
36
|
replayRecoveryReporter?: ReplayRecoveryReporter;
|
|
36
37
|
/**
|
|
37
38
|
* Resilient step dispatch: when provided (and the per-step eligibility gates
|
|
38
|
-
* pass
|
|
39
|
+
* pass, see the step ops below), each newly created non-inline step's
|
|
39
40
|
* `step_created` write is parallelized with its step-execution queue
|
|
40
41
|
* publish, and the queue message carries the serialized step input
|
|
41
42
|
* (`stepInput`) so the consumer can idempotently re-ensure the event if the
|
|
42
43
|
* direct write failed transiently. Steps queued this way are reported in
|
|
43
44
|
* {@link SuspensionHandlerResult.queuedStepCorrelationIds} so the caller
|
|
44
45
|
* skips them in its own dispatch pass. Omitted by callers that must not
|
|
45
|
-
* queue (terminal drain, tests)
|
|
46
|
+
* queue (terminal drain, tests); creates then behave exactly as before.
|
|
46
47
|
*/
|
|
47
48
|
stepDispatch?: {
|
|
48
49
|
/** The unified workflow queue this run's step messages are published to. */
|
|
@@ -57,9 +58,9 @@ export interface SuspensionHandlerParams {
|
|
|
57
58
|
* Inline step ownership: the queue message ID of the invocation this
|
|
58
59
|
* suspension runs in (the queue handler's meta). When present AND the
|
|
59
60
|
* batched fan-out engages, the lazy-inline steps' deferred writes are
|
|
60
|
-
* folded into the batch as `step_created` + `step_started` pairs
|
|
61
|
+
* folded into the batch as `step_created` + `step_started` pairs (the
|
|
61
62
|
* started row stamped with this ID, exactly like the lazy claim it
|
|
62
|
-
* replaces
|
|
63
|
+
* replaces), pre-claiming the steps the caller is about to run inline. See
|
|
63
64
|
* {@link SuspensionHandlerResult.inlineClaims}. Callers that never
|
|
64
65
|
* inline-execute (terminal drain) omit it, keeping their lazy steps on the
|
|
65
66
|
* plain deferred path.
|
|
@@ -69,8 +70,8 @@ export interface SuspensionHandlerParams {
|
|
|
69
70
|
* Lets the batched fan-out return before every chunk has committed: only
|
|
70
71
|
* the chunk carrying the pre-claimed inline pairs gates the handler's
|
|
71
72
|
* return (its claims are what the caller starts bodies from), while the
|
|
72
|
-
* trailing chunks' commits
|
|
73
|
-
* publishes
|
|
73
|
+
* trailing chunks' commits (and every chunk's in-flush step-message
|
|
74
|
+
* publishes) ride {@link SuspensionHandlerResult.deferredBatchWork}. A
|
|
74
75
|
* caller that opts in MUST await that promise before acking its delivery:
|
|
75
76
|
* the durability contract ("every create durable before ack") moves from
|
|
76
77
|
* the handler's return to that join, and nothing else re-drives a lost
|
|
@@ -90,16 +91,28 @@ export interface SuspensionHandlerResult {
|
|
|
90
91
|
* Correlation IDs for which this suspension call actually wrote the
|
|
91
92
|
* step_created event (as opposed to catching EntityConflictError because
|
|
92
93
|
* a concurrent handler wrote it first). Only the handler that wrote the
|
|
93
|
-
* step_created event should queue / inline-execute the step
|
|
94
|
+
* step_created event should queue / inline-execute the step; this
|
|
94
95
|
* guarantees a single owner per step, even when multiple handlers race
|
|
95
96
|
* into the same batch boundary.
|
|
96
97
|
*/
|
|
97
98
|
createdStepCorrelationIds: Set<string>;
|
|
99
|
+
/**
|
|
100
|
+
* Correlation IDs of steps whose arguments failed to serialize. Each was
|
|
101
|
+
* finalized here as `step_created` (with a placeholder input; the real
|
|
102
|
+
* input is precisely what refused to serialize) followed by `step_failed`
|
|
103
|
+
* carrying the SerializationError, so the next replay rejects the step's
|
|
104
|
+
* promise and a try/catch around the step call observes the error,
|
|
105
|
+
* exactly like a step-body failure. No step-execution message is
|
|
106
|
+
* dispatched for these, so the caller MUST force an in-process replay:
|
|
107
|
+
* when the failed step was the only pending work, nothing else will ever
|
|
108
|
+
* re-invoke the run to observe the terminal event.
|
|
109
|
+
*/
|
|
110
|
+
failedStepCorrelationIds: Set<string>;
|
|
98
111
|
/**
|
|
99
112
|
* Correlation IDs of steps this suspension call already published
|
|
100
113
|
* step-execution queue messages for, via resilient step dispatch (the
|
|
101
114
|
* `step_created` write parallelized with a `stepInput`-carrying queue
|
|
102
|
-
* publish). The caller MUST NOT dispatch these again
|
|
115
|
+
* publish). The caller MUST NOT dispatch these again: the message is
|
|
103
116
|
* already out (a duplicate would be deduped by its idempotency key, but
|
|
104
117
|
* costs a wasted round-trip). Empty when {@link SuspensionHandlerParams.stepDispatch}
|
|
105
118
|
* was not provided or no step was eligible.
|
|
@@ -134,12 +147,12 @@ export interface SuspensionHandlerResult {
|
|
|
134
147
|
* Pre-claimed inline starts, by correlation id: the per-step verdicts of
|
|
135
148
|
* the `step_created` + `step_started` pairs the batched fan-out committed
|
|
136
149
|
* for the lazy-inline steps. A step with an entry here is passed to
|
|
137
|
-
* `executeStep` as `preclaimedStart` INSTEAD of `lazyStepInput
|
|
150
|
+
* `executeStep` as `preclaimedStart` INSTEAD of `lazyStepInput`: its
|
|
138
151
|
* input already rode the pair, and the claim is settled: `owned: true`
|
|
139
152
|
* carries the started attempt-1 entity (input re-attached) so the body
|
|
140
153
|
* runs straight off the batch commit with no start write of its own;
|
|
141
154
|
* `owned: false` lost the pair's atomic create-claim to a concurrent
|
|
142
|
-
* writer, and executeStep returns `skipped` without running the body
|
|
155
|
+
* writer, and executeStep returns `skipped` without running the body,
|
|
143
156
|
* the same outcome as losing the lazy claim. Empty whenever the fold did
|
|
144
157
|
* not engage (batching off, no `ownerMessageId`, or the lone-inline case,
|
|
145
158
|
* which keeps the optimistic lazy path and its claim/body overlap).
|
|
@@ -147,20 +160,20 @@ export interface SuspensionHandlerResult {
|
|
|
147
160
|
* Crash window: the pair commits before the caller runs the body, so a
|
|
148
161
|
* crash between them leaves a started step stamped with this message's
|
|
149
162
|
* ID. Redelivery of the same message re-executes it via the owned-recovery
|
|
150
|
-
* path
|
|
163
|
+
* path, the exact machinery the lazy claim's crash window already uses.
|
|
151
164
|
*/
|
|
152
165
|
inlineClaims: Map<string, PreclaimedInlineStart>;
|
|
153
166
|
/**
|
|
154
167
|
* The highest slot the batched fan-out committed, when it ran. The batch's
|
|
155
168
|
* own events are not in the caller's loaded log (the next reload picks
|
|
156
169
|
* them up), so the caller folds this ceiling into the slot snapshot it
|
|
157
|
-
* hands the inline executions
|
|
170
|
+
* hands the inline executions; otherwise every inline terminal write
|
|
158
171
|
* would name a pre-batch position and be answered with a skipped-slot
|
|
159
172
|
* report echoing the events this suspension just wrote. Under
|
|
160
173
|
* {@link SuspensionHandlerParams.allowDeferredBatchWork} this covers the
|
|
161
174
|
* chunks that had committed by the handler's return (always the pair
|
|
162
175
|
* chunk); a trailing chunk that commits later is echoed back on the
|
|
163
|
-
* terminal writes like any foreign event
|
|
176
|
+
* terminal writes like any foreign event: reports the executor reads for
|
|
164
177
|
* position and discards.
|
|
165
178
|
*
|
|
166
179
|
* So the echo is only fully suppressed for a SINGLE-chunk fold. On a
|
|
@@ -168,7 +181,7 @@ export interface SuspensionHandlerResult {
|
|
|
168
181
|
* chunks are still in flight, and an inline terminal write issued in that
|
|
169
182
|
* window still names a position below them and still draws a report for
|
|
170
183
|
* their events. Bounded (trailing chunks only, large fan-outs only) and
|
|
171
|
-
* self-correcting on the next reload
|
|
184
|
+
* self-correcting on the next reload, and recorded so a report seen there
|
|
172
185
|
* reads as expected rather than as a bug.
|
|
173
186
|
*/
|
|
174
187
|
batchCommittedSlotCeiling?: number;
|
|
@@ -178,7 +191,7 @@ export interface SuspensionHandlerResult {
|
|
|
178
191
|
* trailing work exists: the commits of every chunk except the pair chunk,
|
|
179
192
|
* plus every chunk's step-message publishes (each chained on ITS OWN
|
|
180
193
|
* chunk's commit, so publish-after-create holds per step). The caller
|
|
181
|
-
* MUST await it before acking
|
|
194
|
+
* MUST await it before acking: a rejection here is a failed suspension
|
|
182
195
|
* write and fails the delivery exactly as it would have at the handler's
|
|
183
196
|
* return. Steps whose messages this work publishes are already in
|
|
184
197
|
* {@link queuedStepCorrelationIds} at return time.
|
|
@@ -216,17 +229,18 @@ export interface SuspensionHandlerResult {
|
|
|
216
229
|
* durably creating the user's hooks doesn't count as runtime overhead.
|
|
217
230
|
*/
|
|
218
231
|
hookCreationMs: number;
|
|
219
|
-
/**
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
232
|
+
/** Exact number of workflow-code executions observed during serialization. */
|
|
233
|
+
serializationBlockerCount: number;
|
|
234
|
+
/** Bounded sample used only for retention diagnostics. */
|
|
235
|
+
serializationBlockers: SuspensionSerializationBlocker[];
|
|
236
|
+
}
|
|
237
|
+
export interface SuspensionSerializationBlocker extends GuestCodeExecution {
|
|
238
|
+
source: 'step_input' | 'hook_metadata' | 'hook_abort';
|
|
239
|
+
correlationId: string;
|
|
226
240
|
}
|
|
227
241
|
/**
|
|
228
242
|
* Handles a workflow suspension by processing all pending operations (hooks, steps, waits).
|
|
229
|
-
* Creates events for all operations but does NOT queue step messages
|
|
243
|
+
* Creates events for all operations but does NOT queue step messages; returns the pending
|
|
230
244
|
* steps so the caller can decide which to execute inline vs queue to background.
|
|
231
245
|
*
|
|
232
246
|
* Processing order:
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared shape for finalizing a step whose arguments failed to serialize
|
|
3
|
+
* (used by both the node:vm suspension handler and the QuickJS entrypoint).
|
|
4
|
+
*
|
|
5
|
+
* The world requires a `step_created` before any terminal step event, and
|
|
6
|
+
* the step's real input is precisely what refused to serialize, so the
|
|
7
|
+
* finalization writes a placeholder input. The marker string makes the
|
|
8
|
+
* placeholder distinguishable from a genuine zero-argument step in
|
|
9
|
+
* `workflow inspect steps` and the observability UI: a reader sees
|
|
10
|
+
* "input unavailable" instead of "no arguments".
|
|
11
|
+
*/
|
|
12
|
+
export declare const UNSERIALIZABLE_STEP_INPUT_MARKER = "[input unavailable: step argument serialization failed]";
|
|
13
|
+
/**
|
|
14
|
+
* The placeholder value serialized into the failed step's `step_created`
|
|
15
|
+
* input. Matches the `{ args, closureVars, thisVal }` triple
|
|
16
|
+
* `dehydrateStepArguments` / the QuickJS bootstrap produce for real steps,
|
|
17
|
+
* so every consumer hydrates it uniformly, plus the structural flag the
|
|
18
|
+
* step executor checks before running user code (see
|
|
19
|
+
* {@link isUnserializableStepInputPlaceholder}).
|
|
20
|
+
*/
|
|
21
|
+
export declare function unserializableStepInputPlaceholder(): Record<string, unknown>;
|
|
22
|
+
/**
|
|
23
|
+
* Whether a hydrated step input is the finalization placeholder.
|
|
24
|
+
*
|
|
25
|
+
* Finalization writes `step_created` (placeholder) and `step_failed` as two
|
|
26
|
+
* separate durable writes; a crash or transient failure between them leaves
|
|
27
|
+
* a pending step whose stored input is the placeholder. Redelivery then
|
|
28
|
+
* dispatches that step through normal crash recovery: the executor calls
|
|
29
|
+
* this before running user code and completes the intended failure (a fatal
|
|
30
|
+
* SerializationError → `step_failed`) instead of silently invoking the step
|
|
31
|
+
* body with placeholder arguments.
|
|
32
|
+
*/
|
|
33
|
+
export declare function isUnserializableStepInputPlaceholder(hydratedInput: unknown): boolean;
|
|
34
|
+
//# sourceMappingURL=unserializable-step.d.ts.map
|
|
@@ -24,7 +24,7 @@ export type WorkflowVmMode = (typeof WORKFLOW_VMS)[number];
|
|
|
24
24
|
*
|
|
25
25
|
* Returns the configured engine, or `undefined` if unset/empty.
|
|
26
26
|
* Throws {@link WorkflowRuntimeError} if the value is set but not one of
|
|
27
|
-
* the known engines
|
|
27
|
+
* the known engines, since catching misconfiguration early is better than
|
|
28
28
|
* silently falling back to the default.
|
|
29
29
|
*/
|
|
30
30
|
export declare function getWorkflowVmFromEnv(env?: NodeJS.ProcessEnv): WorkflowVmMode | undefined;
|
|
@@ -40,5 +40,5 @@ export declare function getWorkflowVmFromEnv(env?: NodeJS.ProcessEnv): WorkflowV
|
|
|
40
40
|
* Throws if `WORKFLOW_VM` or `executionContext.workflowVm` is set to an
|
|
41
41
|
* unknown value.
|
|
42
42
|
*/
|
|
43
|
-
export declare function useQuickJSVm(workflowRun: WorkflowRun): boolean;
|
|
43
|
+
export declare function useQuickJSVm(workflowRun: Pick<WorkflowRun, 'executionContext'>): boolean;
|
|
44
44
|
//# sourceMappingURL=vm-mode.d.ts.map
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* The continuation is keyed on the wait's correlationId: while a wait is
|
|
11
11
|
* pending, every replay pass over the run re-observes it (e.g., once per
|
|
12
12
|
* step completion in `Promise.all([steps..., sleep()])`), and without
|
|
13
|
-
* dedupe each pass would enqueue another delayed continuation
|
|
13
|
+
* dedupe each pass would enqueue another delayed continuation: each one
|
|
14
14
|
* a spurious full replay when the wait elapses, and each a fresh message
|
|
15
15
|
* that resets the delivery-attempt runaway guard. A key is attached in
|
|
16
16
|
* all cases: some worlds (e.g. world-postgres) serialize key-less
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* situations exist, each with its own key variation:
|
|
30
30
|
*
|
|
31
31
|
* - Waits longer than the maximum queue delay are chained: the delay is
|
|
32
|
-
* clamped to `WAIT_CONTINUATION_MAX_DELAY_SECONDS` (23h
|
|
32
|
+
* clamped to `WAIT_CONTINUATION_MAX_DELAY_SECONDS` (23h: VQS messages
|
|
33
33
|
* have a 24h retention limit, and one hour of buffer matches
|
|
34
34
|
* world-vercel's own clamp for delayed re-enqueues), so the
|
|
35
35
|
* continuation intentionally fires early, re-observes the wait, and
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
* (`ceil(timeoutSeconds / maxDelay)`): stable for every re-observation
|
|
38
38
|
* within the same hop window (so passes dedupe), decremented at each
|
|
39
39
|
* hop delivery (so the chain always advances). Worlds without a delay
|
|
40
|
-
* limit (world-postgres, world-local)
|
|
40
|
+
* limit (world-postgres, world-local) take the same ≤23h hops.
|
|
41
41
|
*
|
|
42
42
|
* - Near-elapsed waits (≤2s remaining) get a second-bucketed suffix. A
|
|
43
43
|
* continuation delivered marginally early (clock skew between the
|
|
@@ -50,11 +50,25 @@
|
|
|
50
50
|
* Mid-range waits (more than the near-elapsed threshold, at most one
|
|
51
51
|
* hop) use the bare correlationId: every re-observation targets the same
|
|
52
52
|
* deadline, so deduping to the first message is semantically lossless.
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
53
|
+
*
|
|
54
|
+
* That last case used to be the one hole in the scheme, and it was not
|
|
55
|
+
* theoretical. Any delivery early enough to re-observe its own wait as
|
|
56
|
+
* pending burns the bare key on the way in: the re-enqueue is dropped by
|
|
57
|
+
* the dedupe window, nothing else is scheduled to wake the run, and no
|
|
58
|
+
* backstop exists for a wait the way inline step ownership provides one
|
|
59
|
+
* for a step. The run sleeps forever. Waits over the threshold have zero
|
|
60
|
+
* tolerance for it, which is why an infrastructure change in delivery
|
|
61
|
+
* timing was able to strand runs across every published SDK version at
|
|
62
|
+
* once, all of them keyed this way.
|
|
63
|
+
*
|
|
64
|
+
* So the key is no longer derived from the wait alone. A continuation
|
|
65
|
+
* carries the wait it was armed for and its attempt number
|
|
66
|
+
* ({@link WorkflowInvokePayload.waitContinuation}), and an invocation
|
|
67
|
+
* that recognizes itself as the continuation for a wait that is still
|
|
68
|
+
* pending arms the next one at `attempt + 1`. Attempts advance ONLY when
|
|
69
|
+
* an early delivery actually happens, so the normal path is untouched:
|
|
70
|
+
* attempt 0 keys exactly as before, and every re-observation within one
|
|
71
|
+
* attempt still collapses to a single message.
|
|
58
72
|
*/
|
|
59
73
|
/**
|
|
60
74
|
* Maximum `delaySeconds` for a single wait-continuation message. Waits
|
|
@@ -79,6 +93,14 @@ export interface WaitContinuationDispatch {
|
|
|
79
93
|
* message. `timeoutSeconds` is the time until the wait's `resumeAt`
|
|
80
94
|
* (floored at 1s by the suspension handler); `waitCorrelationId`
|
|
81
95
|
* identifies the wait so repeated suspension passes dedupe.
|
|
96
|
+
*
|
|
97
|
+
* `attempt` is the number of continuations already spent on this wait, taken
|
|
98
|
+
* from the incoming message when this invocation IS one of them (see
|
|
99
|
+
* {@link WorkflowInvokePayload.waitContinuation}). It only ever moves when a
|
|
100
|
+
* continuation arrived before its wait elapsed, which is exactly when the
|
|
101
|
+
* previous key is spent and re-using it would drop the message. Attempt 0
|
|
102
|
+
* keys identically to the scheme before attempts existed, so the ordinary
|
|
103
|
+
* path — arm once, deliver once, complete — is byte-for-byte unchanged.
|
|
82
104
|
*/
|
|
83
|
-
export declare function getWaitContinuationDispatch(timeoutSeconds: number, waitCorrelationId: string, now?: number): WaitContinuationDispatch;
|
|
105
|
+
export declare function getWaitContinuationDispatch(timeoutSeconds: number, waitCorrelationId: string, now?: number, attempt?: number): WaitContinuationDispatch;
|
|
84
106
|
//# sourceMappingURL=wait-continuation.d.ts.map
|
|
@@ -3,7 +3,7 @@ export declare function waitUntil(promise: Promise<unknown>): void;
|
|
|
3
3
|
* Schedule a background promise via `waitUntil`, guaranteeing that the
|
|
4
4
|
* promise handed to `waitUntil` can never reject. Nothing consumes a
|
|
5
5
|
* `waitUntil` promise, so a rejection surfaces as an `unhandledRejection`
|
|
6
|
-
* and can crash the process
|
|
6
|
+
* and can crash the process, even when the same underlying error is
|
|
7
7
|
* correctly handled by an awaited copy elsewhere.
|
|
8
8
|
*
|
|
9
9
|
* Expected client-disconnect errors (`AbortError` / `ResponseAborted`)
|