eve 0.48.0 → 0.49.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/CHANGELOG.md +15 -0
- package/dist/src/channel/channel-address.js +1 -1
- package/dist/src/channel/types.d.ts +10 -0
- 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/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/slackChannel.d.ts +7 -1
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/setup/flows/registry.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/guides/instrumentation.md +1 -1
- package/docs/install-integrations.mdx +2 -0
- package/docs/instructions.mdx +1 -1
- package/docs/memory/custom-provider.md +214 -0
- package/docs/memory/file.md +129 -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/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
|
@@ -4,7 +4,7 @@ import { type RunErrorCode } from '#compiled/@workflow/errors/index.js';
|
|
|
4
4
|
*
|
|
5
5
|
* - `user`: the error came from customer code (a step or workflow function
|
|
6
6
|
* threw, or a value they passed across a boundary wasn't serializable).
|
|
7
|
-
* - `sdk`: the SDK produced the error itself
|
|
7
|
+
* - `sdk`: the SDK produced the error itself: an internal invariant broke,
|
|
8
8
|
* or a runtime guard rejected the call. These should be rare; when they
|
|
9
9
|
* happen we want to frame the terminal output as "this is us, not you."
|
|
10
10
|
*/
|
|
@@ -26,7 +26,7 @@ export interface ErrorDescription {
|
|
|
26
26
|
*
|
|
27
27
|
* - `errorCode` is typed as `string` rather than `RunErrorCode` because
|
|
28
28
|
* the value comes from stored JSON/CBOR and may predate the current
|
|
29
|
-
* enum
|
|
29
|
+
* enum, so callers should not narrow on it blindly. Values that don't
|
|
30
30
|
* match a known `RUN_ERROR_CODES` entry fall through to USER_ERROR.
|
|
31
31
|
* - `errorName` is the thrown `Error#name`. It is not universally
|
|
32
32
|
* persisted today; callers that have access to it (either via an
|
|
@@ -40,13 +40,13 @@ export interface PersistedErrorSignal {
|
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
42
|
* Data-driven variant of {@link describeError} that works from persisted
|
|
43
|
-
* event fields instead of a live `Error` instance. Intended for
|
|
44
|
-
* renderers that read failure events and no longer
|
|
45
|
-
* thrown object.
|
|
43
|
+
* event fields instead of a live `Error` instance. Intended for command-line
|
|
44
|
+
* interface (CLI) and web renderers that read failure events and no longer
|
|
45
|
+
* have the original thrown object.
|
|
46
46
|
*/
|
|
47
47
|
export declare function describeRunError(signal: PersistedErrorSignal): ErrorDescription;
|
|
48
48
|
/**
|
|
49
|
-
* Describe an error for user-facing presentation. Purely informational
|
|
49
|
+
* Describe an error for user-facing presentation. Purely informational: it
|
|
50
50
|
* does not change any persisted event data or error classification used by
|
|
51
51
|
* the runtime.
|
|
52
52
|
*
|
|
@@ -58,7 +58,7 @@ export declare function describeRunError(signal: PersistedErrorSignal): ErrorDes
|
|
|
58
58
|
* - Context-violation errors (`NotInWorkflowContextError`, etc.) likewise
|
|
59
59
|
* describe a user mistake.
|
|
60
60
|
* - `WorkflowRuntimeError` (and subclasses like `StepNotRegisteredError`)
|
|
61
|
-
* indicates an internal SDK invariant broke
|
|
61
|
+
* indicates an internal SDK invariant broke, so surface that as `sdk`.
|
|
62
62
|
*
|
|
63
63
|
* @param err The error value thrown by the workflow / step.
|
|
64
64
|
* @param errorCode Optional precomputed error code. Callers that already
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* calls on every encrypt/decrypt invocation.
|
|
13
13
|
*
|
|
14
14
|
* Wire format: `[nonce (12 bytes)][ciphertext + auth tag]`
|
|
15
|
-
* The `encr` format prefix is NOT part of this module
|
|
15
|
+
* The `encr` format prefix is NOT part of this module: it's added/stripped
|
|
16
16
|
* by the serialization layer in `maybeEncrypt`/`maybeDecrypt`.
|
|
17
17
|
*/
|
|
18
18
|
export type CryptoKey = import('node:crypto').webcrypto.CryptoKey;
|
|
@@ -30,7 +30,7 @@ export declare const TAG_BYTES: number;
|
|
|
30
30
|
*
|
|
31
31
|
* Pass `usages: ['encrypt']` (or `['decrypt']`) for cross-run scenarios
|
|
32
32
|
* where the caller should not be able to perform the inverse operation
|
|
33
|
-
* with the key
|
|
33
|
+
* with the key. For example, a child workflow writing into a parent
|
|
34
34
|
* run's forwarded WritableStream only needs to encrypt, never decrypt.
|
|
35
35
|
*
|
|
36
36
|
* @param raw - Raw 32-byte AES-256 key (from World.getEncryptionKeyForRun)
|
|
@@ -53,17 +53,17 @@ export declare function encrypt(key: CryptoKey, data: Uint8Array, aad?: Uint8Arr
|
|
|
53
53
|
/**
|
|
54
54
|
* Decrypt data using AES-256-GCM.
|
|
55
55
|
*
|
|
56
|
-
* Any failure inside the Web Crypto layer
|
|
56
|
+
* Any failure inside the Web Crypto layer (most commonly an
|
|
57
57
|
* `OperationError: The operation failed for an operation-specific reason`
|
|
58
58
|
* raised by `AESCipherJob.onDone` when the GCM authentication tag does
|
|
59
|
-
* not verify
|
|
59
|
+
* not verify) is rewrapped as {@link RuntimeDecryptionError}. The
|
|
60
60
|
* wrapped error carries the original DOMException as `cause`, plus a
|
|
61
61
|
* small diagnostic context (`operation`, input `byteLength`) to help
|
|
62
62
|
* disambiguate ciphertext corruption from key mismatch from truncated
|
|
63
63
|
* transport reads.
|
|
64
64
|
*
|
|
65
65
|
* Note: `data` is the raw AES payload (`[nonce][ciphertext + tag]`), not a
|
|
66
|
-
* format-prefixed envelope
|
|
66
|
+
* format-prefixed envelope: callers strip the `encr` marker via
|
|
67
67
|
* `decodeFormatPrefix()` before reaching this function. The outer
|
|
68
68
|
* envelope's format prefix is therefore attached by the serialization
|
|
69
69
|
* layer (`serialization/encryption.ts`), which is the layer that has it.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Event } from '#compiled/@workflow/world/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Delay before firing the deferred unconsumed-event check after the promise
|
|
4
4
|
* queue has drained. Must be long enough for cross-VM microtask chains to
|
|
@@ -49,7 +49,7 @@ export interface EventsConsumerOptions {
|
|
|
49
49
|
* Callback invoked when an event is skipped because it repeats an event
|
|
50
50
|
* class the walk already consumed for the same entity. `firstEventType` is
|
|
51
51
|
* the type that recorded the class, which is the one the workflow observed.
|
|
52
|
-
* Diagnostics only: skipping is a normal outcome, not an error
|
|
52
|
+
* Diagnostics only: skipping is a normal outcome, not an error, though a
|
|
53
53
|
* `firstEventType` differing from `event.eventType` says the two writers
|
|
54
54
|
* decided the entity's outcome differently, which is worth more than an
|
|
55
55
|
* info log.
|
|
@@ -69,7 +69,7 @@ export interface EventsConsumerOptions {
|
|
|
69
69
|
* claimed yet is an event it has not reached yet.
|
|
70
70
|
*
|
|
71
71
|
* Required rather than defaulting to always-idle: always-idle is exactly the
|
|
72
|
-
* pre-gate
|
|
72
|
+
* pre-gate behavior, so a defaulted option would let a construction site opt
|
|
73
73
|
* a whole replay path back out without saying so. Tests that drive a consumer
|
|
74
74
|
* with no orchestrator context pass `() => true` to keep the pre-existing
|
|
75
75
|
* timing, and say so at the call site.
|
|
@@ -117,8 +117,8 @@ export declare class EventsConsumer {
|
|
|
117
117
|
/**
|
|
118
118
|
* The oldest event the walk stepped over that no consumer has claimed yet,
|
|
119
119
|
* if any. Parking is a bet that a consumer will be registered later, so at
|
|
120
|
-
* any point where no consumer ever will be again
|
|
121
|
-
* the definitive one
|
|
120
|
+
* any point where no consumer ever will be again (the replay finishing is
|
|
121
|
+
* the definitive one), this answers which event the bet lost on.
|
|
122
122
|
*/
|
|
123
123
|
get strandedEvent(): Event | undefined;
|
|
124
124
|
/**
|
|
@@ -165,6 +165,27 @@ export declare class EventsConsumer {
|
|
|
165
165
|
* afterwards is what keeps the two pointers from interfering.
|
|
166
166
|
*/
|
|
167
167
|
private drainParked;
|
|
168
|
+
/**
|
|
169
|
+
* Release anything parked whose class a consumption has since recorded for
|
|
170
|
+
* the same entity, on the same terms as {@link skipDuplicateEvent}.
|
|
171
|
+
*
|
|
172
|
+
* The ordered walk decides a straggler at the event, but only for one of the
|
|
173
|
+
* two orders the copies can arrive in. When neither copy has a consumer yet,
|
|
174
|
+
* both park — the walk steps over the first and re-enters immediately, so
|
|
175
|
+
* the second is offered in the same tick, with no class recorded because
|
|
176
|
+
* nothing has been *consumed*. The drain then claims the first and the
|
|
177
|
+
* second is left held by a consumer list that will never grow the callback
|
|
178
|
+
* it needs, which the workflow function returning reports through
|
|
179
|
+
* {@link strandedEvent} as a replay divergence.
|
|
180
|
+
*
|
|
181
|
+
* Run before each offer pass rather than once, because the consumption that
|
|
182
|
+
* records the class happens inside the drain itself.
|
|
183
|
+
*
|
|
184
|
+
* Not specific to `attr_set`: `wait_completed` reaches the same state, and
|
|
185
|
+
* {@link ONE_SHOT_EVENT_TYPES} only covers it in the order where the
|
|
186
|
+
* consumption came first.
|
|
187
|
+
*/
|
|
188
|
+
private dropParkedDuplicates;
|
|
168
189
|
/**
|
|
169
190
|
* Step the ordered walk over an event nobody claimed, holding on to it for a
|
|
170
191
|
* later consumer. Returns false when the event's type makes its position a
|
|
@@ -173,12 +194,13 @@ export declare class EventsConsumer {
|
|
|
173
194
|
*/
|
|
174
195
|
private park;
|
|
175
196
|
/**
|
|
176
|
-
* The key `event`'s class is tracked under, or `undefined` for the
|
|
177
|
-
*
|
|
178
|
-
* `
|
|
197
|
+
* The key `event`'s class is tracked under, or `undefined` for the events
|
|
198
|
+
* that belong to no class and are therefore never skipped: the types with no
|
|
199
|
+
* entry at all (`hook_received`, `hook_conflict`, `run_created`), and a
|
|
200
|
+
* classed type carrying no entity to track it under.
|
|
179
201
|
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
202
|
+
* {@link classifyEntityEvent} owns that rule, because the observability UI
|
|
203
|
+
* decides the same question about the same log and the two must not drift.
|
|
182
204
|
*/
|
|
183
205
|
private eventClassKey;
|
|
184
206
|
/**
|
|
@@ -220,7 +242,7 @@ export declare class EventsConsumer {
|
|
|
220
242
|
* ids are minted from a monotonic ULID per body position, so nothing later in
|
|
221
243
|
* the body registers a second consumer under this id. Waiting would cost
|
|
222
244
|
* `getDeferredCheckDelayMs()` per straggler per replay for information that
|
|
223
|
-
* cannot arrive
|
|
245
|
+
* cannot arrive: 0.75% of production runs carry at least one straggler, and
|
|
224
246
|
* the p99 among those carries 155.
|
|
225
247
|
*
|
|
226
248
|
* The invariant to preserve if hook identity ever becomes caller-supplied
|
|
@@ -231,6 +253,18 @@ export declare class EventsConsumer {
|
|
|
231
253
|
* class map lives next to the event types rather than being inferred.
|
|
232
254
|
*/
|
|
233
255
|
private firstEventTypeOfClass;
|
|
256
|
+
/**
|
|
257
|
+
* Steps the walk over a sealed-log `noop` (specVersion >= 7): the World's
|
|
258
|
+
* backend wrote it to occupy a slot whose writer allocated the position and
|
|
259
|
+
* died, so the log's density arithmetic holds. It is invisible to the
|
|
260
|
+
* workflow: no consumer is offered it, no event class is recorded, and the
|
|
261
|
+
* deterministic clock does not advance, exactly as with
|
|
262
|
+
* {@link skipDuplicateEvent}, so a log that happens to contain one produces the same
|
|
263
|
+
* timestamps as a log that does not. (Its `createdAt` is the seal time,
|
|
264
|
+
* which can even postdate later slots' events; letting it touch the clock
|
|
265
|
+
* would leak the sealer's wall clock into replay.)
|
|
266
|
+
*/
|
|
267
|
+
private skipSealedNoop;
|
|
234
268
|
/** Steps the walk over a repeat of an already-consumed class. */
|
|
235
269
|
private skipDuplicateEvent;
|
|
236
270
|
private handleEndOfLog;
|
|
@@ -248,8 +282,9 @@ export declare class EventsConsumer {
|
|
|
248
282
|
* pass that offered it, before this check is ever scheduled, and a class
|
|
249
283
|
* recorded while the check was in flight can only have been recorded by a
|
|
250
284
|
* consumption inside {@link consume}, whose next pass re-offers this event
|
|
251
|
-
* and steps over it there
|
|
252
|
-
* in-flight check.
|
|
285
|
+
* and steps over it there, leaving the identity guard above to drop the
|
|
286
|
+
* in-flight check. One that parks before any consumption records its class
|
|
287
|
+
* is released later by {@link dropParkedDuplicates} instead.
|
|
253
288
|
*/
|
|
254
289
|
private resolveUnconsumedEvent;
|
|
255
290
|
/**
|
|
@@ -273,7 +308,7 @@ export declare class EventsConsumer {
|
|
|
273
308
|
* loses it, and no measurement of a delivery outrunning 100ms exists either
|
|
274
309
|
* way. So read this as retiring the bet rather than as repairing an observed
|
|
275
310
|
* failure of that number: the delay is a user-settable env override, which
|
|
276
|
-
* leaves the old
|
|
311
|
+
* leaves the old behavior one configuration away from losing on any backend.
|
|
277
312
|
*
|
|
278
313
|
* Termination is `hasParkedCommittedDelivery`'s: it counts only deliveries
|
|
279
314
|
* that resolve on their own, so nothing here can gate its own retirement. A
|
|
@@ -15,7 +15,7 @@ type DrainBarrier = () => Promise<void>;
|
|
|
15
15
|
* This is deliberately distinct from the per-request batch caps below: this
|
|
16
16
|
* bounds how much is *buffered*, those bound how much goes out in one
|
|
17
17
|
* `writeMulti`. Raising this must never let a single request exceed a wire
|
|
18
|
-
* limit
|
|
18
|
+
* limit, since batch sizing enforces that independently.
|
|
19
19
|
*/
|
|
20
20
|
export declare const MAX_INFLIGHT_CHUNKS = 1000;
|
|
21
21
|
export declare const getMaxInflightChunks: () => number;
|
|
@@ -29,7 +29,7 @@ export declare const MAX_CHUNKS_PER_BATCH = 1000;
|
|
|
29
29
|
export declare const getMaxChunksPerBatch: () => number;
|
|
30
30
|
/**
|
|
31
31
|
* Wire limit: maximum cumulative bytes in a single coalesced `writeMulti`.
|
|
32
|
-
* Chunk *count* alone is not enough
|
|
32
|
+
* Chunk *count* alone is not enough: 1,000 small chunks are ~100KB but 1,000
|
|
33
33
|
* file-sized chunks can be hundreds of MB, which platform request-body limits
|
|
34
34
|
* reject long before the count cap matters. A batch is split once adding the
|
|
35
35
|
* next chunk would exceed this (a single chunk larger than the cap still goes
|
|
@@ -38,7 +38,7 @@ export declare const getMaxChunksPerBatch: () => number;
|
|
|
38
38
|
export declare const MAX_BYTES_PER_BATCH: number;
|
|
39
39
|
export declare const getMaxBytesPerBatch: () => number;
|
|
40
40
|
/**
|
|
41
|
-
* Buffer bound (bytes) for the server writable's group-commit buffer
|
|
41
|
+
* Buffer bound (bytes) for the server writable's group-commit buffer, the
|
|
42
42
|
* byte-denominated counterpart of {@link MAX_INFLIGHT_CHUNKS}. `write()`
|
|
43
43
|
* blocks once this much data is buffered-but-not-durable, so a fast producer
|
|
44
44
|
* of large chunks can't grow client memory without bound. Default 8 MiB
|
|
@@ -59,7 +59,7 @@ export declare const getMaxBufferedBytes: () => number;
|
|
|
59
59
|
* after each step body returns, so a coarser interval (the previous 100ms)
|
|
60
60
|
* adds visible per-step latency to streaming workflows. With a uniformly
|
|
61
61
|
* distributed offset between step return and the next tick, the expected
|
|
62
|
-
* wait is half the interval
|
|
62
|
+
* wait is half the interval, so 10ms means ~5ms average wait per step
|
|
63
63
|
* instead of ~50ms. The per-tick work is `writable.locked` plus a
|
|
64
64
|
* `getWriter()`/`releaseLock()` probe, both microsecond-scale; 10× more
|
|
65
65
|
* ticks during a stream's lifetime is not measurable in practice.
|
|
@@ -13,7 +13,7 @@ export interface StepInvocationQueueItem {
|
|
|
13
13
|
* during replay: the queue message ID stamped by the invocation running
|
|
14
14
|
* the step inline, or undefined when the latest start was unstamped (a
|
|
15
15
|
* retry attempt driven by a queued step message, or an older runtime).
|
|
16
|
-
* Latest start wins
|
|
16
|
+
* Latest start wins: an unstamped bare start clears a previous stamp; an
|
|
17
17
|
* owner-recovery re-stamped start restores it.
|
|
18
18
|
*/
|
|
19
19
|
ownerMessageId?: string;
|
|
@@ -65,6 +65,8 @@ export type QueueItem = StepInvocationQueueItem | HookInvocationQueueItem | Wait
|
|
|
65
65
|
* onto the queue.
|
|
66
66
|
*/
|
|
67
67
|
export declare class WorkflowSuspension extends Error {
|
|
68
|
+
items: QueueItem[];
|
|
69
|
+
/** @deprecated Use `items` instead. */
|
|
68
70
|
steps: QueueItem[];
|
|
69
71
|
globalThis: typeof globalThis;
|
|
70
72
|
stepCount: number;
|
|
@@ -73,7 +75,7 @@ export declare class WorkflowSuspension extends Error {
|
|
|
73
75
|
attributeCount: number;
|
|
74
76
|
hookDisposedCount: number;
|
|
75
77
|
abortCount: number;
|
|
76
|
-
constructor(
|
|
78
|
+
constructor(itemsInput: Map<string, QueueItem>, global: typeof globalThis);
|
|
77
79
|
static is(value: unknown): value is WorkflowSuspension;
|
|
78
80
|
}
|
|
79
81
|
export declare function ENOTSUP(): never;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Core utilities intended for import by user
|
|
3
3
|
* steps/workflows. This allows the bundler to tree-shake and limit what goes
|
|
4
4
|
* into the final user bundles. Logic for running/handling steps/workflows
|
|
5
5
|
* should live in runtime. Eventually these might be separate packages
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`)}`)}return await x(t,r.value)}}}async function E(e,t={}){let n=
|
|
1
|
+
import{J as e,M as t,P as n,Qn as r,Y as i,_r as a,br as o,fr as s,mr as c,pr as l,sr as u,ur as d,vr as f,w as p,yr as m}from"../../_chunks/workflow/wait-until-BtySPYD0.js";import{i as h,u as g}from"../../_chunks/workflow/dist-DjojkP5e.js";import{a as _,i as v,r as y,t as b}from"../../_chunks/workflow/attribute-changes-BwAadFfB.js";import"../../_chunks/workflow/dist-CgbVZs5l.js";import{n as x}from"../../_chunks/workflow/resume-hook-BToMtPbH.js";import{t as S}from"../../_chunks/workflow/sleep-3_A5uOp-.js";function C(e){v(`createHook()`,`https://workflow-sdk.dev/docs/api-reference/workflow/create-hook`,C)}function w(e){v(`createWebhook()`,`https://workflow-sdk.dev/docs/api-reference/workflow/create-webhook`,w)}function T({schema:e}={}){function t(e){v(`defineHook().create()`,`https://workflow-sdk.dev/docs/api-reference/workflow/define-hook`,t)}return{create:t,async resume(t,n){if(!e?.[`~standard`])return await x(t,n);let r=e[`~standard`].validate(n);if(r instanceof Promise&&(r=await r),r.issues){let e=r.issues.map(e=>{let t=e.path?.map(e=>String(typeof e==`object`&&e?e.key:e)).join(`.`);return t?` at "${t}": ${e.message}`:` ${e.message}`});throw Error(`Hook payload did not match the defined schema:\n${e.join(`
|
|
2
|
+
`)}`)}return await x(t,r.value)}}}async function E(e,t={}){let n=i.getStore(),r=n?.workflowMetadata?.workflowRunId;if(!r)throw new h(`setAttributes() must be called from a 'use workflow' or 'use step' function. Calling it from plain host code is not supported.`);let a=b(e,t);if(a.length!==0){if(n.runReadyBarrier)try{await n.runReadyBarrier}catch{}await(await d()).events.create(r,{eventType:`attr_set`,specVersion:7,eventData:{changes:a,writer:{type:`step`,stepId:n.stepMetadata.stepId,attempt:n.stepMetadata.attempt},...t.allowReservedAttributes===!0?{allowReservedAttributes:!0}:{}}})}}function D(){let e=i.getStore();return e||y(`getStepMetadata()`,`https://workflow-sdk.dev/docs/api-reference/workflow/get-step-metadata`,D),e.stepMetadata}function O(){let e=i.getStore();return e||_(`getWorkflowMetadata()`,`https://workflow-sdk.dev/docs/api-reference/workflow/get-workflow-metadata`,O),e.workflowMetadata}function k(d={}){let h=i.getStore();h||_(`getWritable()`,`https://workflow-sdk.dev/docs/api-reference/workflow/get-writable`,k);let{namespace:g}=d,v=h.workflowMetadata.workflowRunId,y=e(v,g);h.writables??=new Map;let b=h.writables,x=b.get(y);if(x)return x.writable;let S=n(t(globalThis,h.ops,v,h.encryptionKey,!0,h.runReadyBarrier),h.encryptionKey),C=new p(v,y,h.runReadyBarrier),w=s();return h.ops.push(w.promise),l(S.readable,C,w).catch(()=>{}),c(S.writable,w),Object.defineProperty(S.writable,a,{value:y,writable:!1}),Object.defineProperty(S.writable,o,{value:v,writable:!1}),h.workflowDeploymentId&&Object.defineProperty(S.writable,f,{value:h.workflowDeploymentId,writable:!1}),r(h.encryptionKey)&&Object.defineProperty(S.writable,m,{value:u(h.encryptionKey.keyPair.publicKey),writable:!1}),b.set(y,{writable:S.writable,state:w}),S.writable}export{h as FatalError,g as RetryableError,C as createHook,w as createWebhook,T as defineHook,D as getStepMetadata,O as getWorkflowMetadata,k as getWritable,E as setAttributes,S as sleep};
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* step step_… · add (./workflows/x)
|
|
10
10
|
* hint: Move the call to a step function.
|
|
11
11
|
* FatalError: …
|
|
12
|
-
* at … (trimmed stack
|
|
12
|
+
* at … (trimmed stack, internals collapsed)
|
|
13
13
|
*
|
|
14
14
|
* Without this composition, callers passing `${framing}\n${stack}` as the
|
|
15
15
|
* message and structured fields as the metadata object got `util.inspect`'s
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*
|
|
19
19
|
* The same metadata is also emitted as structured OTel span events from
|
|
20
20
|
* the logger itself, so backends that want JSON-shaped data still get it.
|
|
21
|
-
* web/web-shared do not consume stderr at all
|
|
21
|
+
* web/web-shared do not consume stderr at all: they read CBOR/JSON event
|
|
22
22
|
* payloads from the World event log.
|
|
23
23
|
*/
|
|
24
24
|
export declare function composeLogLine(prefix: string, message: string, metadata: Record<string, unknown> | undefined): string;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { WorldCapabilities } from '#compiled/@workflow/world/index.js';
|
|
5
5
|
import type { EventsConsumer } from './events-consumer.js';
|
|
6
|
-
import type
|
|
6
|
+
import { type QueueItem } from './global.js';
|
|
7
7
|
import type { ReplayPayloadCache } from './replay-payload-cache.js';
|
|
8
8
|
import type { Serializable } from './schemas.js';
|
|
9
9
|
import type { PayloadKey } from './serialization/encryption.js';
|
|
@@ -32,12 +32,12 @@ export interface WorkflowOrchestratorContext {
|
|
|
32
32
|
globalThis: typeof globalThis;
|
|
33
33
|
/**
|
|
34
34
|
* Increments when a suspension is accepted and on every retained-session
|
|
35
|
-
* resume.
|
|
36
|
-
*
|
|
37
|
-
* timers queued at boundary N that would fire after the session resumed
|
|
38
|
-
* into boundary N+1. Sleep
|
|
39
|
-
*
|
|
40
|
-
*
|
|
35
|
+
* resume. Step, hook, and attribute suspension signals capture it when
|
|
36
|
+
* scheduled and no-op if it moved, which drops same-boundary sibling signals
|
|
37
|
+
* and timers queued at boundary N that would fire after the session resumed
|
|
38
|
+
* into boundary N+1. Sleep signals are intentionally unguarded: their
|
|
39
|
+
* presence makes the boundary unretainable, so a late signal correctly
|
|
40
|
+
* demotes the session (workflow.ts `onWorkflowError`).
|
|
41
41
|
*/
|
|
42
42
|
suspensionGeneration: number;
|
|
43
43
|
eventsConsumer: EventsConsumer;
|
|
@@ -53,6 +53,14 @@ export interface WorkflowOrchestratorContext {
|
|
|
53
53
|
* whole run and both replays of a run must draw in the same order.
|
|
54
54
|
*/
|
|
55
55
|
generateUlid: () => string;
|
|
56
|
+
/**
|
|
57
|
+
* Monotone count of correlation-id draws this replay has made. Progress
|
|
58
|
+
* metric for {@link quiesceEarlierCascades}: a macrotask turn in which it
|
|
59
|
+
* does not move (and no hydration is in flight) means every woken branch has
|
|
60
|
+
* run as far as it can without another delivery. Optional so lightweight
|
|
61
|
+
* test contexts degrade to the single-yield behavior.
|
|
62
|
+
*/
|
|
63
|
+
readonly mintCount?: number;
|
|
56
64
|
generateNanoid: () => string;
|
|
57
65
|
/**
|
|
58
66
|
* Sequential promise queue that ensures all event-driven promise resolutions
|
|
@@ -66,12 +74,12 @@ export interface WorkflowOrchestratorContext {
|
|
|
66
74
|
* Counter of in-flight async data delivery operations (step result
|
|
67
75
|
* hydration, hook payload hydration, abort signal hydration). Suspensions
|
|
68
76
|
* must wait for this to reach 0 before firing, to avoid preempting data
|
|
69
|
-
* delivery
|
|
77
|
+
* delivery, e.g. dehydrating a step's arguments while an abort that should
|
|
70
78
|
* be reflected in those arguments is still hydrating its reason.
|
|
71
79
|
*/
|
|
72
80
|
pendingDeliveries: number;
|
|
73
81
|
/**
|
|
74
|
-
* Ordered registry of in-flight "branch-deciding" deliveries
|
|
82
|
+
* Ordered registry of in-flight "branch-deciding" deliveries: the
|
|
75
83
|
* resolutions a workflow typically `Promise.race`s on, or awaits from
|
|
76
84
|
* independent concurrent branches: hook payloads (`hook_received`), wait
|
|
77
85
|
* completions (`wait_completed`), and step results (`step_completed` /
|
|
@@ -84,7 +92,7 @@ export interface WorkflowOrchestratorContext {
|
|
|
84
92
|
* costing extra hops; a `wait_completed` resolves with fewer, and a reused
|
|
85
93
|
* sleep can resolve in an entirely earlier loop iteration; a step result is
|
|
86
94
|
* gated on hydration whose cost varies between replays of the SAME
|
|
87
|
-
* invocation
|
|
95
|
+
* invocation: the first replay pays the full decrypt/decompress/revive,
|
|
88
96
|
* while later replays sharing the invocation's `ReplayPayloadCache`
|
|
89
97
|
* memo-hit small primitive results and resolve in one or two hops. Either
|
|
90
98
|
* way, the resolution that the committed event log ordered first can lose a
|
|
@@ -118,8 +126,8 @@ export interface WorkflowOrchestratorContext {
|
|
|
118
126
|
export type DeliveryKind = 'hook' | 'wait' | 'step';
|
|
119
127
|
interface DeliveryBarrierEntry {
|
|
120
128
|
kind: DeliveryKind;
|
|
121
|
-
/** Resolves once this delivery
|
|
122
|
-
|
|
129
|
+
/** Resolves once this delivery is handed to the workflow or retired. */
|
|
130
|
+
released: Promise<void>;
|
|
123
131
|
/**
|
|
124
132
|
* Whether this delivery is committed to reaching the workflow without any
|
|
125
133
|
* further action by workflow code. True for wait completions and step
|
|
@@ -127,77 +135,29 @@ interface DeliveryBarrierEntry {
|
|
|
127
135
|
* that already had a waiting consumer when it was consumed.
|
|
128
136
|
*
|
|
129
137
|
* False for a BUFFERED hook payload no consumer has claimed yet: it is
|
|
130
|
-
* delivered by `claim()`, i.e. whenever the workflow next reads the hook
|
|
138
|
+
* delivered by `claim()`, i.e. whenever the workflow next reads the hook,
|
|
131
139
|
* which may be causally *after* a later-in-log delivery. `arm()` flips it
|
|
132
140
|
* once a consumer takes the payload.
|
|
133
141
|
*/
|
|
134
142
|
armed: boolean;
|
|
143
|
+
/** Whether this entry has been removed and its `released` promise settled. */
|
|
144
|
+
retired: boolean;
|
|
135
145
|
/**
|
|
136
|
-
* Retire this entry: resolve `
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
146
|
+
* Retire this entry: resolve `released` and remove it from the registry,
|
|
147
|
+
* without marking the handle delivered to the workflow. A safety-retired
|
|
148
|
+
* buffered payload may therefore install a fresh entry if it is claimed by
|
|
149
|
+
* a retained VM later. Called only by the context's safety-net dispenser
|
|
150
|
+
* ({@link ensureBarrierSafetyNet}), and only on the lowest-index entry at
|
|
151
|
+
* delivery idle. Idempotent.
|
|
140
152
|
*/
|
|
141
153
|
retire: () => void;
|
|
142
154
|
}
|
|
143
|
-
/**
|
|
144
|
-
* Awaits, in strict event-log order, every still-registered delivery that is
|
|
145
|
-
* earlier in the log than `eventIndex` and that a delivery of `kind` defers
|
|
146
|
-
* behind (see {@link DEFER_BEHIND}), so that this resolution is handed to the
|
|
147
|
-
* workflow only after all relevant earlier-in-log deliveries have been. This
|
|
148
|
-
* is what keeps a `Promise.race` — or the ULID a follow-up `useStep` draws on
|
|
149
|
-
* a concurrent branch — deterministic and aligned with the committed event
|
|
150
|
-
* log, independent of microtask-hop counts, hydration time, or race-argument
|
|
151
|
-
* order. When this delivery does have to wait, it also yields a macrotask
|
|
152
|
-
* afterwards so the earlier delivery's consumer can run to its own next
|
|
153
|
-
* suspension point first; see the comment at that `await` for why ordering the
|
|
154
|
-
* `resolve()` calls alone is not enough.
|
|
155
|
-
*
|
|
156
|
-
* What counts as "defers behind" is {@link gatesOn}, shared with
|
|
157
|
-
* {@link computeResolvesOnItsOwn} so the two cannot drift.
|
|
158
|
-
*
|
|
159
|
-
* One asymmetry: a STEP result skips any earlier delivery that is UNARMED,
|
|
160
|
-
* i.e. a buffered hook payload no consumer has claimed. Such a payload is
|
|
161
|
-
* delivered only when the workflow next reads the hook, and reaching that read
|
|
162
|
-
* very commonly requires the step result itself (`await stepX()` before the
|
|
163
|
-
* read). Gating the step on it would stall the workflow until the barrier's
|
|
164
|
-
* idle safety net fires, which then releases every delivery queued behind that
|
|
165
|
-
* payload at once — losing exactly the race this ordering exists to protect.
|
|
166
|
-
* Waits and hooks keep gating on unclaimed payloads: for them, waiting for the
|
|
167
|
-
* claim IS the ordering guarantee (a `wait_completed` must not preempt a
|
|
168
|
-
* payload the log ordered first).
|
|
169
|
-
*
|
|
170
|
-
* The skip is direct, never transitive. A step still gates on an earlier ARMED
|
|
171
|
-
* wait or hook, including one that is itself parked behind an unclaimed
|
|
172
|
-
* payload. Skipping those too would invert log order for the commonest shape
|
|
173
|
-
* there is: a workflow that creates a hook it does not read on this branch,
|
|
174
|
-
* races `step` against `sleep`, and has the log say the sleep won. The step
|
|
175
|
-
* would then overtake the wait, both branches would swap the correlation ids
|
|
176
|
-
* they draw next, and replay would diverge — see
|
|
177
|
-
* `step-delivery-ordering.test.ts`. Waiting instead is safe because the
|
|
178
|
-
* payload's own idle safety net retires it and the whole chain then delivers
|
|
179
|
-
* in log order; {@link hasParkedCommittedDelivery} deliberately reports such a
|
|
180
|
-
* step as not self-resolving so that idle stays reachable.
|
|
181
|
-
*
|
|
182
|
-
* "The whole chain then delivers in log order" rests on the PAYLOAD's barrier
|
|
183
|
-
* being retired before that of anything parked behind it. That order is
|
|
184
|
-
* structural: safety-net retirements go through one per-context dispenser that
|
|
185
|
-
* only ever retires the lowest-index entry at delivery idle, and every
|
|
186
|
-
* retirement that wakes a chain flips {@link hasParkedCommittedDelivery} back
|
|
187
|
-
* to true, re-blocking the dispenser until the chain has drained — see
|
|
188
|
-
* {@link ensureBarrierSafetyNet}. (This used to rest on the FIFO of one idle
|
|
189
|
-
* poll per barrier, which held for a single parked segment but decayed to
|
|
190
|
-
* timing noise with several — the release order, and therefore the ULIDs
|
|
191
|
-
* drawn by the woken branches, then depended on how much log the replay had
|
|
192
|
-
* loaded. storm-log-replay.test.ts replays a production log corrupted exactly
|
|
193
|
-
* that way.)
|
|
194
|
-
*/
|
|
195
155
|
export declare function awaitEarlierDeliveries(ctx: WorkflowOrchestratorContext, eventIndex: number | undefined, kind: DeliveryKind): Promise<void>;
|
|
196
156
|
/** Handle for a registered branch-deciding delivery barrier. */
|
|
197
157
|
export interface DeliveryBarrier {
|
|
198
158
|
/**
|
|
199
159
|
* Mark this delivery as delivered to the workflow. Resolves its
|
|
200
|
-
* `
|
|
160
|
+
* `released` promise so any later-in-log delivery gated on it (via
|
|
201
161
|
* {@link awaitEarlierDeliveries}) may proceed, and removes it from the
|
|
202
162
|
* registry. Idempotent.
|
|
203
163
|
*/
|
|
@@ -222,12 +182,12 @@ export interface DeliveryBarrier {
|
|
|
222
182
|
* suspending and never observes it), the barrier auto-resolves at idle.
|
|
223
183
|
*
|
|
224
184
|
* INVARIANT required of every call site: a barrier that is ever `armed` must
|
|
225
|
-
* be paired with a delivery chain that runs unconditionally
|
|
185
|
+
* be paired with a delivery chain that runs unconditionally, attached when
|
|
226
186
|
* the event is consumed (waits, step results, waiting-consumer hook payloads,
|
|
227
187
|
* aborts), or by the `claim()` whose invocation is what arms it (buffered
|
|
228
188
|
* hook payloads). The idle check ({@link scheduleWhenIdle}) refuses to
|
|
229
189
|
* observe idle while an armed, self-resolving barrier is undelivered, and the
|
|
230
|
-
* safety net below is itself idle-gated
|
|
190
|
+
* safety net below is itself idle-gated, so an armed barrier with no
|
|
231
191
|
* unconditional chain would livelock every idle check in the run, including
|
|
232
192
|
* its own retirement.
|
|
233
193
|
*/
|
|
@@ -237,19 +197,19 @@ export declare function registerDeliveryBarrier(ctx: WorkflowOrchestratorContext
|
|
|
237
197
|
/**
|
|
238
198
|
* Whether some registered branch-deciding delivery is going to reach the
|
|
239
199
|
* workflow without any further help (it is armed and not transitively parked
|
|
240
|
-
* behind an unclaimed buffered payload
|
|
200
|
+
* behind an unclaimed buffered payload, see {@link resolvesOnItsOwn}) but
|
|
241
201
|
* has not been handed over yet.
|
|
242
202
|
*
|
|
243
203
|
* This is the delivery state `pendingDeliveries` cannot see. That counter
|
|
244
204
|
* covers the hydration window inside a serial `promiseQueue` slot and is
|
|
245
205
|
* released there, while the delivery's `resolve()` runs later, from a
|
|
246
|
-
* detached continuation behind {@link awaitEarlierDeliveries}
|
|
206
|
+
* detached continuation behind {@link awaitEarlierDeliveries}, including its
|
|
247
207
|
* macrotask yield whenever the delivery had to defer. Replaying a batch of N
|
|
248
208
|
* parallel step results consumed in one drain window leaves N-1 of them
|
|
249
209
|
* parked on that yield with `pendingDeliveries` already at 0. An idle check
|
|
250
210
|
* armed during the same window (a pending `sleep()` arms one on every replay)
|
|
251
211
|
* could then observe "idle" mid-deferral and raise a `WorkflowSuspension`
|
|
252
|
-
* BEFORE the workflow's own continuations ran
|
|
212
|
+
* BEFORE the workflow's own continuations ran: a suspension carrying none of
|
|
253
213
|
* the follow-up work the batch was about to create, which the runtime
|
|
254
214
|
* dutifully schedules as nothing, leaving the run dormant until an unrelated
|
|
255
215
|
* timer fires (vercel/workflow#3183).
|
|
@@ -258,7 +218,7 @@ export declare function registerDeliveryBarrier(ctx: WorkflowOrchestratorContext
|
|
|
258
218
|
* accuracy but for termination: an unclaimed buffered hook payload is retired
|
|
259
219
|
* BY the idle safety net in {@link registerDeliveryBarrier}, so counting it
|
|
260
220
|
* here would gate its own retirement. That reasoning extends to whatever is
|
|
261
|
-
* parked behind such a payload
|
|
221
|
+
* parked behind such a payload (a wait, and a step gating on that wait) for
|
|
262
222
|
* the same reason: the whole chain moves only once the net fires, and it
|
|
263
223
|
* cannot fire while the chain is counted. Self-resolving deliveries always
|
|
264
224
|
* deliver from their own chains (see the INVARIANT on
|
|
@@ -272,7 +232,7 @@ export declare function hasParkedCommittedDelivery(ctx: WorkflowOrchestratorCont
|
|
|
272
232
|
* "In flight" is two distinct windows, each with its own guard:
|
|
273
233
|
* `pendingDeliveries > 0` covers hydration inside the serial queue slots, and
|
|
274
234
|
* {@link hasParkedCommittedDelivery} covers the detached gap between a slot
|
|
275
|
-
* releasing that counter and the delivery's `resolve()` actually running
|
|
235
|
+
* releasing that counter and the delivery's `resolve()` actually running,
|
|
276
236
|
* deliberately outside `pendingDeliveries` (see step.ts), and invisible to it.
|
|
277
237
|
*
|
|
278
238
|
* Anything that decides a replay is over, or that a replay went wrong, has to
|
|
@@ -285,7 +245,7 @@ export declare function hasParkedCommittedDelivery(ctx: WorkflowOrchestratorCont
|
|
|
285
245
|
* entry is parked behind an unclaimed buffered payload. Those entries only
|
|
286
246
|
* move when the safety-net dispenser retires them (lowest-first, see
|
|
287
247
|
* {@link ensureBarrierSafetyNet}), and the deliveries they release are real
|
|
288
|
-
* workflow reactions
|
|
248
|
+
* workflow reactions: a suspension raised before they run would be computed
|
|
289
249
|
* from a VM that has not seen them, scheduling none of their follow-up work
|
|
290
250
|
* and leaving the run dormant (the vercel/workflow#3183 shape). The dispenser
|
|
291
251
|
* itself is gated on {@link canRetireAbandonedBarriers}, the weaker predicate
|
|
@@ -316,5 +276,7 @@ export declare function isDeliveryIdle(ctx: WorkflowOrchestratorContext): boolea
|
|
|
316
276
|
* breaks hook/sleep `Promise.race` ordering (CorruptedEventLogError).
|
|
317
277
|
*/
|
|
318
278
|
export declare function scheduleWhenIdle(ctx: WorkflowOrchestratorContext, fn: () => void): void;
|
|
279
|
+
/** Schedule a generation-guarded suspension after deliveries settle. */
|
|
280
|
+
export declare function scheduleWorkflowSuspension(ctx: WorkflowOrchestratorContext): void;
|
|
319
281
|
export {};
|
|
320
282
|
//# sourceMappingURL=private.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,
|
|
1
|
+
import{a as e,c as t,i as n,n as r,o as i,r as a,s as o,t as s}from"../../_chunks/workflow/private-CZFMABEf.js";export{s as awaitEarlierDeliveries,r as getStepFunction,a as hasParkedCommittedDelivery,n as isDeliveryIdle,e as registerDeliveryBarrier,i as registerStepFunction,o as scheduleWhenIdle,t as scheduleWorkflowSuspension};
|
|
@@ -10,33 +10,26 @@ type ReplayPayloadField = 'result' | 'error' | 'payload';
|
|
|
10
10
|
* those replays. Deserialization still runs against each VM's globals so every
|
|
11
11
|
* replay receives fresh object graphs and correctly revived Workflow objects.
|
|
12
12
|
*
|
|
13
|
-
* Successful prepared plaintext
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* Successful prepared plaintext and memoized primitive step results remain
|
|
14
|
+
* resident for the invocation lifetime. Their memory never crosses workflow
|
|
15
|
+
* runs or queue deliveries.
|
|
16
16
|
*/
|
|
17
17
|
export declare class ReplayPayloadCache {
|
|
18
|
-
private readonly encryptionKey;
|
|
19
18
|
private readonly preparer;
|
|
20
19
|
private readonly preparedPayloads;
|
|
21
20
|
private readonly primitiveStepResults;
|
|
21
|
+
private readonly encryptionKey;
|
|
22
22
|
private nextUnscannedEventIndex;
|
|
23
|
-
constructor(encryptionKey: PayloadKey | undefined
|
|
23
|
+
constructor(encryptionKey: PayloadKey | undefined | Promise<PayloadKey | undefined>, preparer?: ReplayPayloadPreparer);
|
|
24
|
+
/** Start preparing an event payload as soon as its frame is decoded. */
|
|
25
|
+
prepareEvent(event: Event): void;
|
|
24
26
|
/**
|
|
25
27
|
* Start every missing binary preparation before workflow execution. Failures
|
|
26
28
|
* are intentionally retained: the ordered event consumer must observe the
|
|
27
29
|
* original rejection before that entry becomes retryable.
|
|
28
30
|
*/
|
|
29
31
|
prewarm(workflowRun: WorkflowRun, events: Event[]): Promise<void>;
|
|
30
|
-
/**
|
|
31
|
-
* Forget how much of the event log has been scanned, so the next
|
|
32
|
-
* {@link prewarm} walks it from the start again.
|
|
33
|
-
*
|
|
34
|
-
* Required before a replay whose event log was reloaded rather than extended:
|
|
35
|
-
* a corrected log inserts the events the previous load was missing, which
|
|
36
|
-
* shifts every later position, so a positional resume would skip exactly the
|
|
37
|
-
* events the reload was for. Already-prepared payloads are kept — they are
|
|
38
|
-
* keyed by event id, so re-scanning re-observes them for free.
|
|
39
|
-
*/
|
|
32
|
+
/** Rescan the next event log after an authoritative replacement. */
|
|
40
33
|
resetScan(): void;
|
|
41
34
|
/** Return the workflow input after shared host-side preparation. */
|
|
42
35
|
prepareWorkflowInput(workflowRun: WorkflowRun): Promise<PreparedReplayPayload>;
|
|
@@ -48,8 +41,8 @@ export declare class ReplayPayloadCache {
|
|
|
48
41
|
prepareEventPayload(eventId: string, field: ReplayPayloadField, value: unknown): Promise<PreparedReplayPayload>;
|
|
49
42
|
/**
|
|
50
43
|
* Reuse final step values only when sharing them across VMs is unobservable.
|
|
51
|
-
* Objects
|
|
52
|
-
*
|
|
44
|
+
* Objects always run `hydrate` again to produce a fresh VM-specific value;
|
|
45
|
+
* every primitive is safe to reuse directly.
|
|
53
46
|
*/
|
|
54
47
|
getStepResult(eventId: string, hydrate: () => Promise<unknown>): Promise<unknown>;
|
|
55
48
|
/**
|
|
@@ -61,6 +54,9 @@ export declare class ReplayPayloadCache {
|
|
|
61
54
|
private ensurePreparation;
|
|
62
55
|
/** Normalize synchronous and asynchronous preparers to one promise contract. */
|
|
63
56
|
private runPreparation;
|
|
57
|
+
/** Start one event's binary payload unless another path already did. */
|
|
58
|
+
private prepareEventIfMissing;
|
|
59
|
+
private startPreparation;
|
|
64
60
|
private workflowInputKey;
|
|
65
61
|
private eventPayloadKey;
|
|
66
62
|
}
|