@lostgradient/weft 0.2.1 → 0.4.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/README.md +123 -43
- package/dist/cli/conformance.js +7 -1
- package/dist/cli/generated/operation-client.generated.d.ts +55 -13
- package/dist/cli/generated/operation-client.generated.js +3 -0
- package/dist/cli/help-text.d.ts +1 -1
- package/dist/cli/help-text.js +1 -0
- package/dist/cli/operation-catalog-snapshot.d.ts +8 -0
- package/dist/cli/operation-catalog-snapshot.js +11 -0
- package/dist/cli/parse-schedule-arguments.js +3 -1
- package/dist/cli/schedule.js +2 -1
- package/dist/cli/types.d.ts +1 -0
- package/dist/cli-main.js +80 -79
- package/dist/client/handle-delegation.d.ts +7 -2
- package/dist/client/handle-delegation.js +9 -1
- package/dist/client/http-client-requests.d.ts +4 -1
- package/dist/client/http-client-requests.js +10 -0
- package/dist/client/http-client.d.ts +10 -4
- package/dist/client/http-client.js +18 -1
- package/dist/client/http-request.d.ts +11 -1
- package/dist/client/http-request.js +17 -7
- package/dist/client/index.d.ts +1 -1
- package/dist/client/interface.d.ts +100 -4
- package/dist/client/local.d.ts +7 -1
- package/dist/client/local.js +17 -2
- package/dist/client/start-body.d.ts +9 -2
- package/dist/client/start-body.js +13 -4
- package/dist/core/byte-arrays.d.ts +5 -0
- package/dist/core/byte-arrays.js +5 -0
- package/dist/core/checkpoint/lifecycle.d.ts +3 -0
- package/dist/core/checkpoint/lifecycle.js +9 -4
- package/dist/core/checkpoint/serialization.js +12 -5
- package/dist/core/codec/extension-codec.d.ts +16 -0
- package/dist/core/codec/extension-codec.js +104 -8
- package/dist/core/codec/index.d.ts +1 -0
- package/dist/core/codec/index.js +1 -0
- package/dist/core/codec/serializer-registry.d.ts +122 -0
- package/dist/core/codec/serializer-registry.js +51 -0
- package/dist/core/context/activity-retry-state.d.ts +38 -0
- package/dist/core/context/activity-retry-state.js +89 -0
- package/dist/core/context/activity-schedule-to-close.d.ts +159 -0
- package/dist/core/context/activity-schedule-to-close.js +69 -0
- package/dist/core/context/child-workflow-pipe.d.ts +5 -5
- package/dist/core/context/child-workflow-pipe.js +15 -2
- package/dist/core/context/context-presence.d.ts +19 -0
- package/dist/core/context/context-presence.js +13 -0
- package/dist/core/context/durable-operations.d.ts +25 -0
- package/dist/core/context/durable-operations.js +64 -0
- package/dist/core/context/index.d.ts +18 -5
- package/dist/core/context/index.js +17 -12
- package/dist/core/context/internals.d.ts +29 -0
- package/dist/core/context/internals.js +6 -1
- package/dist/core/context/operation-request.d.ts +35 -0
- package/dist/core/context/parallel-cache-entry.d.ts +14 -5
- package/dist/core/context/run-operation.d.ts +21 -3
- package/dist/core/context/run-operation.js +56 -93
- package/dist/core/context/session-state.js +7 -8
- package/dist/core/context/speculative-child.js +2 -0
- package/dist/core/context/types.d.ts +15 -0
- package/dist/core/context/version-patching.d.ts +8 -0
- package/dist/core/context/version-patching.js +40 -0
- package/dist/core/context/workflow-logger.d.ts +98 -0
- package/dist/core/context/workflow-logger.js +68 -0
- package/dist/core/engine/activity-heartbeat-tracking.d.ts +64 -0
- package/dist/core/engine/activity-heartbeat-tracking.js +42 -0
- package/dist/core/engine/activity-per-attempt-timeout.d.ts +41 -0
- package/dist/core/engine/activity-per-attempt-timeout.js +36 -0
- package/dist/core/engine/activity-reconciliation.d.ts +1 -0
- package/dist/core/engine/activity-reconciliation.js +12 -1
- package/dist/core/engine/activity-resolution.d.ts +23 -0
- package/dist/core/engine/activity-resolution.js +37 -0
- package/dist/core/engine/aggregate.js +66 -30
- package/dist/core/engine/async-activity-completion.d.ts +23 -6
- package/dist/core/engine/async-activity-completion.js +53 -12
- package/dist/core/engine/attributes-tags.js +9 -4
- package/dist/core/engine/bulk-operations-purge.d.ts +26 -0
- package/dist/core/engine/bulk-operations-purge.js +38 -3
- package/dist/core/engine/bulk-operations-shared.d.ts +2 -0
- package/dist/core/engine/bulk-operations-shared.js +8 -2
- package/dist/core/engine/bulk-operations.d.ts +4 -1
- package/dist/core/engine/bulk-operations.js +235 -24
- package/dist/core/engine/callback-creators-bundles.d.ts +9 -0
- package/dist/core/engine/callback-creators-bundles.js +30 -2
- package/dist/core/engine/callback-creators-core.js +6 -4
- package/dist/core/engine/callback-creators-router.js +10 -0
- package/dist/core/engine/callback-creators-schedule.d.ts +2 -2
- package/dist/core/engine/callback-creators-schedule.js +12 -8
- package/dist/core/engine/candidate-read-batching.d.ts +6 -0
- package/dist/core/engine/candidate-read-batching.js +1 -0
- package/dist/core/engine/checkpoint-io.js +61 -25
- package/dist/core/engine/checkpoint-reads.js +3 -2
- package/dist/core/engine/checkpoint-replay.d.ts +20 -0
- package/dist/core/engine/checkpoint-replay.js +242 -0
- package/dist/core/engine/checkpoint-side-effects.d.ts +23 -0
- package/dist/core/engine/checkpoint-side-effects.js +35 -0
- package/dist/core/engine/child-workflow-cancellation.d.ts +10 -0
- package/dist/core/engine/child-workflow-cancellation.js +40 -0
- package/dist/core/engine/child-workflow.js +27 -4
- package/dist/core/engine/condition-waiters.d.ts +14 -0
- package/dist/core/engine/condition-waiters.js +5 -0
- package/dist/core/engine/construction.d.ts +3 -1
- package/dist/core/engine/construction.js +30 -8
- package/dist/core/engine/coordination-branch-executors.d.ts +70 -0
- package/dist/core/engine/coordination-branch-executors.js +107 -0
- package/dist/core/engine/deferred-consume-envelope.d.ts +59 -0
- package/dist/core/engine/deferred-consume-envelope.js +14 -0
- package/dist/core/engine/disposal.js +25 -0
- package/dist/core/engine/engine-create-types.d.ts +14 -18
- package/dist/core/engine/engine-internal-types.d.ts +38 -3
- package/dist/core/engine/engine-leak-warnings.d.ts +6 -0
- package/dist/core/engine/engine-leak-warnings.js +4 -0
- package/dist/core/engine/engine-runtime-helpers.d.ts +17 -0
- package/dist/core/engine/engine-runtime-helpers.js +26 -5
- package/dist/core/engine/errors.d.ts +121 -0
- package/dist/core/engine/errors.js +45 -1
- package/dist/core/engine/event-log-compaction.d.ts +8 -0
- package/dist/core/engine/event-log-compaction.js +20 -2
- package/dist/core/engine/fenced-write.d.ts +65 -0
- package/dist/core/engine/fenced-write.js +71 -0
- package/dist/core/engine/finalizer-state.d.ts +28 -0
- package/dist/core/engine/finalizer-state.js +16 -0
- package/dist/core/engine/handle-result.js +1 -1
- package/dist/core/engine/handles.d.ts +97 -40
- package/dist/core/engine/handles.js +25 -27
- package/dist/core/engine/index.d.ts +125 -15
- package/dist/core/engine/index.js +207 -11
- package/dist/core/engine/inline-launch-queue.d.ts +14 -0
- package/dist/core/engine/inline-launch-queue.js +32 -7
- package/dist/core/engine/inline-parking.js +3 -2
- package/dist/core/engine/internals.d.ts +125 -13
- package/dist/core/engine/lease-codec.d.ts +35 -0
- package/dist/core/engine/lease-codec.js +32 -0
- package/dist/core/engine/lease-deposition.d.ts +66 -0
- package/dist/core/engine/lease-deposition.js +10 -0
- package/dist/core/engine/lease-errors.d.ts +99 -0
- package/dist/core/engine/lease-errors.js +30 -0
- package/dist/core/engine/lease-manager.d.ts +114 -0
- package/dist/core/engine/lease-manager.js +135 -0
- package/dist/core/engine/lifecycle/fork-helpers.js +1 -7
- package/dist/core/engine/lifecycle/persist.js +15 -52
- package/dist/core/engine/lifecycle/recovered-services.d.ts +8 -6
- package/dist/core/engine/lifecycle/recovered-services.js +18 -3
- package/dist/core/engine/lifecycle/resume.js +39 -11
- package/dist/core/engine/lifecycle/shared.d.ts +8 -1
- package/dist/core/engine/lifecycle/start-batch.d.ts +1 -1
- package/dist/core/engine/lifecycle/start-batch.js +2 -1
- package/dist/core/engine/lifecycle/start-commit.d.ts +56 -0
- package/dist/core/engine/lifecycle/start-commit.js +69 -0
- package/dist/core/engine/lifecycle/start-exec.d.ts +30 -2
- package/dist/core/engine/lifecycle/start-exec.js +38 -0
- package/dist/core/engine/lifecycle/start-or-signal-create.d.ts +58 -0
- package/dist/core/engine/lifecycle/start-or-signal-create.js +95 -0
- package/dist/core/engine/lifecycle/start-or-signal-resolution.d.ts +79 -0
- package/dist/core/engine/lifecycle/start-or-signal-resolution.js +60 -0
- package/dist/core/engine/lifecycle/start-or-signal.d.ts +46 -0
- package/dist/core/engine/lifecycle/start-or-signal.js +71 -0
- package/dist/core/engine/lifecycle/start-terminal-conflict-purge.d.ts +39 -0
- package/dist/core/engine/lifecycle/start-terminal-conflict-purge.js +28 -0
- package/dist/core/engine/lifecycle/start.d.ts +6 -6
- package/dist/core/engine/lifecycle/start.js +47 -45
- package/dist/core/engine/lifecycle/transition.js +17 -5
- package/dist/core/engine/lifecycle.d.ts +3 -2
- package/dist/core/engine/lifecycle.js +9 -2
- package/dist/core/engine/list-candidate-resolution.js +2 -2
- package/dist/core/engine/listing.js +10 -6
- package/dist/core/engine/operations-activity.d.ts +4 -11
- package/dist/core/engine/operations-activity.js +22 -49
- package/dist/core/engine/operations-coordination.d.ts +10 -0
- package/dist/core/engine/operations-coordination.js +43 -8
- package/dist/core/engine/operations-router.d.ts +6 -0
- package/dist/core/engine/operations-router.js +2 -0
- package/dist/core/engine/operations-speculate.js +6 -2
- package/dist/core/engine/operations-stream.js +12 -2
- package/dist/core/engine/operations-time.d.ts +4 -2
- package/dist/core/engine/operations-time.js +14 -2
- package/dist/core/engine/operations-wait-condition.d.ts +23 -0
- package/dist/core/engine/operations-wait-condition.js +62 -0
- package/dist/core/engine/ownership-options.d.ts +23 -0
- package/dist/core/engine/ownership-options.js +26 -0
- package/dist/core/engine/payload-size-policy.d.ts +3 -0
- package/dist/core/engine/payload-size-policy.js +4 -0
- package/dist/core/engine/pending-updates.d.ts +17 -0
- package/dist/core/engine/pending-updates.js +33 -11
- package/dist/core/engine/persisted-data-version.d.ts +5 -9
- package/dist/core/engine/persisted-data-version.js +4 -5
- package/dist/core/engine/queries.js +1 -1
- package/dist/core/engine/registration.d.ts +1 -0
- package/dist/core/engine/registration.js +18 -3
- package/dist/core/engine/schedule-handle.d.ts +45 -0
- package/dist/core/engine/schedule-handle.js +26 -0
- package/dist/core/engine/schedule-jitter.d.ts +5 -0
- package/dist/core/engine/schedule-jitter.js +10 -0
- package/dist/core/engine/schedule-run.d.ts +17 -0
- package/dist/core/engine/schedule-run.js +38 -0
- package/dist/core/engine/schedule-timer.js +81 -17
- package/dist/core/engine/schedules.d.ts +8 -5
- package/dist/core/engine/schedules.js +44 -19
- package/dist/core/engine/search-attribute-records.d.ts +4 -0
- package/dist/core/engine/search-attribute-records.js +17 -0
- package/dist/core/engine/second-instance-detector.d.ts +96 -0
- package/dist/core/engine/second-instance-detector.js +108 -0
- package/dist/core/engine/signals.d.ts +38 -0
- package/dist/core/engine/signals.js +55 -19
- package/dist/core/engine/state-utilities.d.ts +49 -2
- package/dist/core/engine/state-utilities.js +114 -3
- package/dist/core/engine/storage-io.d.ts +16 -2
- package/dist/core/engine/storage-io.js +26 -5
- package/dist/core/engine/stream-chunk-loading.d.ts +2 -0
- package/dist/core/engine/stream-chunk-loading.js +24 -1
- package/dist/core/engine/sub-operation.js +22 -3
- package/dist/core/engine/termination/cleanup.d.ts +28 -1
- package/dist/core/engine/termination/cleanup.js +44 -2
- package/dist/core/engine/termination/complete.js +48 -9
- package/dist/core/engine/termination/finalizer-activity.d.ts +53 -0
- package/dist/core/engine/termination/finalizer-activity.js +30 -0
- package/dist/core/engine/termination/finalizer-claim.d.ts +110 -0
- package/dist/core/engine/termination/finalizer-claim.js +80 -0
- package/dist/core/engine/termination/finalizer.d.ts +48 -0
- package/dist/core/engine/termination/finalizer.js +159 -0
- package/dist/core/engine/termination/suspend.d.ts +70 -0
- package/dist/core/engine/termination/suspend.js +41 -0
- package/dist/core/engine/termination.d.ts +5 -2
- package/dist/core/engine/termination.js +6 -0
- package/dist/core/engine/updates.js +5 -25
- package/dist/core/engine/validation/schedule.d.ts +2 -1
- package/dist/core/engine/validation/schedule.js +51 -2
- package/dist/core/engine/validation.js +54 -3
- package/dist/core/engine/waiting-update-response.d.ts +8 -0
- package/dist/core/engine/waiting-update-response.js +22 -0
- package/dist/core/engine/workflow-concurrency.d.ts +10 -0
- package/dist/core/engine/workflow-concurrency.js +136 -0
- package/dist/core/engine/workflow-feed.d.ts +9 -8
- package/dist/core/engine/workflow-feed.js +4 -1
- package/dist/core/engine/workflow-indexes.d.ts +9 -0
- package/dist/core/engine/workflow-indexes.js +10 -0
- package/dist/core/engine/workflow-state-stream.js +33 -13
- package/dist/core/engine/workflow-visibility-queries.d.ts +2 -2
- package/dist/core/engine-helpers.js +1 -0
- package/dist/core/events/activity-events.d.ts +43 -12
- package/dist/core/events/activity-events.js +28 -0
- package/dist/core/events/attribute-events.d.ts +2 -3
- package/dist/core/events/event-map.d.ts +19 -12
- package/dist/core/events/index.d.ts +1 -0
- package/dist/core/events/index.js +1 -0
- package/dist/core/events/schedule-events.d.ts +71 -0
- package/dist/core/events/schedule-events.js +29 -0
- package/dist/core/events/signal-events.d.ts +4 -6
- package/dist/core/events/system-events.d.ts +29 -19
- package/dist/core/events/system-events.js +26 -0
- package/dist/core/events/update-events.d.ts +6 -8
- package/dist/core/events/workflow-events.d.ts +108 -20
- package/dist/core/events/workflow-events.js +35 -0
- package/dist/core/failure-categories.js +5 -17
- package/dist/core/fault-code.d.ts +9 -3
- package/dist/core/fault-code.js +1 -0
- package/dist/core/inline-execution-strategy.context-options.d.ts +69 -0
- package/dist/core/inline-execution-strategy.context-options.js +56 -0
- package/dist/core/inline-execution-strategy.d.ts +31 -36
- package/dist/core/inline-execution-strategy.js +16 -27
- package/dist/core/list-filter-validation.d.ts +1 -1
- package/dist/core/list-filter-validation.js +2 -1
- package/dist/core/payload-size.d.ts +1 -1
- package/dist/core/persisted-data-incompatible-error.d.ts +9 -7
- package/dist/core/review/events.d.ts +6 -8
- package/dist/core/scheduler/scheduler-class.d.ts +10 -1
- package/dist/core/scheduler/scheduler-class.js +38 -11
- package/dist/core/scheduler/timer-batch.js +9 -1
- package/dist/core/scheduler/timer-sources.d.ts +1 -0
- package/dist/core/scheduler/timer-sources.js +11 -5
- package/dist/core/session-state.d.ts +0 -1
- package/dist/core/session-state.js +2 -2
- package/dist/core/start-workflow-validation.d.ts +56 -0
- package/dist/core/start-workflow-validation.js +30 -1
- package/dist/core/step-context.d.ts +10 -6
- package/dist/core/step-context.js +7 -15
- package/dist/core/types/activity-verification.d.ts +67 -0
- package/dist/core/types/activity-verification.js +0 -0
- package/dist/core/types/activity.d.ts +86 -64
- package/dist/core/types/bulk.d.ts +50 -9
- package/dist/core/types/checkpoint.d.ts +44 -8
- package/dist/core/types/identity.d.ts +8 -1
- package/dist/core/types/launch-metadata.d.ts +33 -0
- package/dist/core/types/launch-metadata.js +0 -0
- package/dist/core/types/list-options.d.ts +146 -0
- package/dist/core/types/list-options.js +0 -0
- package/dist/core/types/message-handles.d.ts +25 -0
- package/dist/core/types/options.d.ts +165 -215
- package/dist/core/types/reviews.d.ts +2 -1
- package/dist/core/types/schedules.d.ts +39 -3
- package/dist/core/types/services-resolution.d.ts +47 -0
- package/dist/core/types/services-resolution.js +0 -0
- package/dist/core/types/state.d.ts +11 -11
- package/dist/core/types/workflow-builder-runtime.d.ts +12 -3
- package/dist/core/types/workflow-builder-runtime.js +11 -2
- package/dist/core/types/workflow-builder.d.ts +47 -15
- package/dist/core/types/workflow-concurrency.d.ts +39 -0
- package/dist/core/types/workflow-concurrency.js +0 -0
- package/dist/core/types/workflow-context.d.ts +157 -14
- package/dist/core/types/workflow-definition.d.ts +53 -10
- package/dist/core/types/workflow-function.d.ts +101 -9
- package/dist/core/types/workflow-log.d.ts +98 -0
- package/dist/core/types/workflow-log.js +0 -0
- package/dist/core/types/workflow-registries.d.ts +14 -3
- package/dist/core/types/workflow-registry.d.ts +3 -0
- package/dist/core/types/workflow-snapshot.d.ts +29 -0
- package/dist/core/types/workflow-snapshot.js +0 -0
- package/dist/core/types.d.ts +7 -0
- package/dist/core/types.js +7 -0
- package/dist/core/versioning.d.ts +9 -39
- package/dist/core/versioning.js +2 -12
- package/dist/core/weft-error.d.ts +44 -1
- package/dist/core/weft-error.js +19 -1
- package/dist/core/worker-execution-strategy-options.d.ts +26 -0
- package/dist/core/worker-execution-strategy.js +40 -36
- package/dist/core/worker-inbound-message.d.ts +38 -0
- package/dist/core/worker-inbound-message.js +37 -0
- package/dist/core/worker-log-abuse-counter.d.ts +175 -0
- package/dist/core/worker-log-abuse-counter.js +107 -0
- package/dist/core/worker-message-helpers.d.ts +47 -0
- package/dist/core/worker-message-helpers.js +26 -0
- package/dist/core/worker-protocol-guard.js +1 -1
- package/dist/core/worker-protocol-log.d.ts +56 -0
- package/dist/core/worker-protocol-log.js +18 -0
- package/dist/core/worker-protocol.d.ts +23 -0
- package/dist/core/worker-protocol.js +12 -2
- package/dist/core/workflow-version-tuple.d.ts +3 -9
- package/dist/core/workflow-version-tuple.js +2 -3
- package/dist/diagnostics/doctor.js +6 -3
- package/dist/diagnostics/format.js +3 -8
- package/dist/diagnostics/types.d.ts +5 -5
- package/dist/diagnostics/validate.d.ts +0 -1
- package/dist/diagnostics/version-check.d.ts +1 -1
- package/dist/diagnostics/version-check.js +10 -13
- package/dist/index.d.ts +13 -11
- package/dist/index.js +39 -4
- package/dist/json-schema.js +3 -3
- package/dist/mcp/cli.js +35 -35
- package/dist/mcp/dispatcher.js +1 -1
- package/dist/mcp/http.js +16 -6
- package/dist/mcp/list-filter.js +2 -1
- package/dist/mcp/protocol.d.ts +2 -0
- package/dist/mcp/protocol.js +1 -1
- package/dist/mcp/session.d.ts +16 -0
- package/dist/mcp/session.js +60 -6
- package/dist/mcp/tools.js +73 -6
- package/dist/observability/index.js +2 -2
- package/dist/server/asyncapi-channels.js +5 -2
- package/dist/server/attribute-filters.d.ts +8 -3
- package/dist/server/attribute-filters.js +6 -1
- package/dist/server/authentication/api-key.d.ts +2 -1
- package/dist/server/authentication/api-key.js +5 -2
- package/dist/server/authentication/constant-time-api-key.d.ts +15 -0
- package/dist/server/authentication/constant-time-api-key.js +24 -0
- package/dist/server/authentication/index.d.ts +1 -1
- package/dist/server/authentication/index.js +7 -4
- package/dist/server/authentication/rotating-api-key-store.d.ts +5 -3
- package/dist/server/authentication/rotating-api-key-store.js +19 -11
- package/dist/server/engine-event-feed-backend.d.ts +4 -5
- package/dist/server/fault-to-http.js +8 -1
- package/dist/server/fault-to-json-rpc.js +1 -0
- package/dist/server/fleet-event-feed.d.ts +31 -0
- package/dist/server/fleet-event-feed.js +157 -0
- package/dist/server/handler/index.js +1 -1
- package/dist/server/handler/response-helpers.js +2 -1
- package/dist/server/handler/route-dispatch.d.ts +6 -3
- package/dist/server/handler/route-dispatch.js +2 -2
- package/dist/server/handler.js +31 -31
- package/dist/server/index.d.ts +32 -2
- package/dist/server/index.js +35 -35
- package/dist/server/interactive-operations.js +1 -0
- package/dist/server/json-rpc-transport-helpers.d.ts +1 -0
- package/dist/server/json-rpc-transport-helpers.js +2 -1
- package/dist/server/json-rpc-websocket-runtime.d.ts +11 -2
- package/dist/server/json-rpc-websocket-runtime.js +1 -0
- package/dist/server/json-rpc-websocket-subscriptions.d.ts +10 -0
- package/dist/server/json-rpc-websocket-subscriptions.js +29 -0
- package/dist/server/json-rpc-websocket-types.d.ts +22 -0
- package/dist/server/json-rpc-websocket-types.js +0 -0
- package/dist/server/json-rpc-websocket-validation.js +20 -4
- package/dist/server/json-rpc-websocket.d.ts +2 -43
- package/dist/server/json-rpc-websocket.js +57 -74
- package/dist/server/openapi.d.ts +2 -1
- package/dist/server/openapi.js +1 -3
- package/dist/server/openrpc-document-schema.d.ts +78 -0
- package/dist/server/openrpc-document-schema.js +27 -1
- package/dist/server/openrpc-errors.d.ts +3 -0
- package/dist/server/openrpc-errors.js +2 -1
- package/dist/server/openrpc.js +32 -0
- package/dist/server/operation-catalog/index.d.ts +1 -1
- package/dist/server/operation-catalog/pipeline-helpers.js +1 -0
- package/dist/server/operation-catalog/pipeline-stages.js +26 -12
- package/dist/server/operation-catalog/pipeline.js +8 -1
- package/dist/server/operation-catalog/registry.js +13 -0
- package/dist/server/operation-catalog/types.d.ts +20 -9
- package/dist/server/operation-fault.d.ts +10 -0
- package/dist/server/operation-fault.js +2 -0
- package/dist/server/operation-registry.d.ts +12 -11
- package/dist/server/operation-registry.js +12 -3
- package/dist/server/operations/aggregate-workflows.d.ts +15 -15
- package/dist/server/operations/async-activity.d.ts +2 -2
- package/dist/server/operations/async-activity.js +12 -7
- package/dist/server/operations/bulk-cancel-workflows.d.ts +1 -1
- package/dist/server/operations/bulk-cancel-workflows.js +2 -2
- package/dist/server/operations/bulk-delete-workflows.d.ts +1 -1
- package/dist/server/operations/bulk-delete-workflows.js +2 -2
- package/dist/server/operations/bulk-filter-helpers.d.ts +8 -6
- package/dist/server/operations/bulk-filter-helpers.js +54 -24
- package/dist/server/operations/bulk-mutate-workflow-tags.d.ts +11 -9
- package/dist/server/operations/bulk-mutate-workflow-tags.js +2 -2
- package/dist/server/operations/bulk-operation-helpers.d.ts +2 -2
- package/dist/server/operations/bulk-retry-failed-workflows.d.ts +7 -0
- package/dist/server/operations/bulk-retry-failed-workflows.js +64 -0
- package/dist/server/operations/bulk-signal-workflows.d.ts +11 -9
- package/dist/server/operations/bulk-signal-workflows.js +2 -2
- package/dist/server/operations/cancel-schedule.d.ts +1 -1
- package/dist/server/operations/create-schedule.d.ts +3 -1
- package/dist/server/operations/create-schedule.js +29 -11
- package/dist/server/operations/fleet-events-subscription.d.ts +54 -0
- package/dist/server/operations/fleet-events-subscription.js +99 -0
- package/dist/server/operations/fork-workflow.d.ts +1 -1
- package/dist/server/operations/fork-workflow.js +3 -2
- package/dist/server/operations/get-checkpoint-at.d.ts +1 -1
- package/dist/server/operations/get-registry.d.ts +1 -1
- package/dist/server/operations/get-retention-overview.d.ts +1 -1
- package/dist/server/operations/get-review.d.ts +1 -1
- package/dist/server/operations/get-schedule.d.ts +1 -1
- package/dist/server/operations/get-stream-chunks.d.ts +1 -1
- package/dist/server/operations/get-system-metrics.d.ts +2 -2
- package/dist/server/operations/get-task-diagnostics.d.ts +45 -6
- package/dist/server/operations/get-task-diagnostics.js +101 -7
- package/dist/server/operations/get-update-result.d.ts +1 -1
- package/dist/server/operations/get-workflow-attributes.d.ts +1 -1
- package/dist/server/operations/get-workflow-events.d.ts +1 -1
- package/dist/server/operations/get-workflow-result.d.ts +1 -1
- package/dist/server/operations/get-workflow-timeline.d.ts +1 -1
- package/dist/server/operations/get-workflow.d.ts +1 -1
- package/dist/server/operations/list-checkpoints.d.ts +1 -1
- package/dist/server/operations/list-reviews.d.ts +1 -1
- package/dist/server/operations/list-schedules.d.ts +1 -1
- package/dist/server/operations/list-task-queues.d.ts +2 -2
- package/dist/server/operations/list-workers.d.ts +2 -2
- package/dist/server/operations/list-workflows.d.ts +1 -1
- package/dist/server/operations/operation-helpers.d.ts +16 -1
- package/dist/server/operations/operation-helpers.js +15 -3
- package/dist/server/operations/pause-schedule.d.ts +1 -1
- package/dist/server/operations/purge-workflows.d.ts +5 -5
- package/dist/server/operations/purge-workflows.js +2 -2
- package/dist/server/operations/query-workflow.d.ts +1 -1
- package/dist/server/operations/query-workflow.js +3 -2
- package/dist/server/operations/recover-all.d.ts +1 -1
- package/dist/server/operations/replay-workflow.d.ts +1 -1
- package/dist/server/operations/resume-schedule.d.ts +1 -1
- package/dist/server/operations/resume-workflow.js +2 -2
- package/dist/server/operations/set-workflow-attributes.d.ts +1 -1
- package/dist/server/operations/set-workflow-attributes.js +6 -3
- package/dist/server/operations/signal-workflow.js +8 -3
- package/dist/server/operations/single-workflow-tag-mutation.js +13 -3
- package/dist/server/operations/start-or-signal-workflow.d.ts +44 -0
- package/dist/server/operations/start-or-signal-workflow.js +130 -0
- package/dist/server/operations/start-workflow-options.d.ts +38 -0
- package/dist/server/operations/start-workflow-options.js +63 -0
- package/dist/server/operations/start-workflow-rest-input.d.ts +14 -0
- package/dist/server/operations/start-workflow-rest-input.js +31 -0
- package/dist/server/operations/start-workflow.d.ts +1 -1
- package/dist/server/operations/start-workflow.js +15 -92
- package/dist/server/operations/storage.d.ts +6 -6
- package/dist/server/operations/storage.js +24 -14
- package/dist/server/operations/stream-workflow-sse.d.ts +1 -1
- package/dist/server/operations/submit-review-decision.d.ts +1 -1
- package/dist/server/operations/submit-review-decision.js +6 -3
- package/dist/server/operations/suspend-workflow.d.ts +13 -0
- package/dist/server/operations/suspend-workflow.js +36 -0
- package/dist/server/operations/update-schedule.d.ts +1 -1
- package/dist/server/operations/update-schedule.js +7 -4
- package/dist/server/operations/update-workflow.d.ts +1 -1
- package/dist/server/operations/update-workflow.js +7 -3
- package/dist/server/operations/worker-drain.d.ts +8 -8
- package/dist/server/operations/worker-drain.js +11 -8
- package/dist/server/operations/workflow-events-subscription.d.ts +7 -8
- package/dist/server/operations/workflow-events-subscription.js +43 -8
- package/dist/server/rest-binding.d.ts +21 -8
- package/dist/server/rest-bindings.js +24 -0
- package/dist/server/rest-body.d.ts +10 -0
- package/dist/server/rest-body.js +80 -0
- package/dist/server/runtime/authentication-bridge.d.ts +1 -0
- package/dist/server/runtime/authentication-bridge.js +33 -6
- package/dist/server/runtime/client-visible-events.d.ts +3 -0
- package/dist/server/runtime/client-visible-events.js +65 -0
- package/dist/server/runtime/context.d.ts +7 -0
- package/dist/server/runtime/event-broadcasting.d.ts +6 -0
- package/dist/server/runtime/event-broadcasting.js +72 -38
- package/dist/server/runtime/retry.d.ts +1 -0
- package/dist/server/runtime/retry.js +14 -0
- package/dist/server/runtime/shutdown.d.ts +7 -6
- package/dist/server/runtime/shutdown.js +6 -1
- package/dist/server/runtime/task-dispatch.js +5 -3
- package/dist/server/runtime/task-polling.d.ts +16 -2
- package/dist/server/runtime/task-polling.js +80 -24
- package/dist/server/runtime/task-reconciliation.js +9 -1
- package/dist/server/runtime/task-result-resolution.d.ts +15 -0
- package/dist/server/runtime/task-result-resolution.js +81 -0
- package/dist/server/runtime/websocket-stream.d.ts +20 -1
- package/dist/server/runtime/websocket-stream.js +173 -7
- package/dist/server/runtime/websocket-upgrade.js +22 -3
- package/dist/server/runtime/websocket-worker.d.ts +1 -1
- package/dist/server/runtime/websocket-worker.js +46 -30
- package/dist/server/serve-internals.d.ts +11 -1
- package/dist/server/serve-internals.js +20 -2
- package/dist/server/task-state.d.ts +38 -0
- package/dist/server/task-state.js +28 -0
- package/dist/server/workflow-event-feed.d.ts +36 -115
- package/dist/server/workflow-event-feed.js +92 -27
- package/dist/service-worker/index.js +31 -31
- package/dist/storage/auto.js +1 -1
- package/dist/storage/bun-sql.js +24 -0
- package/dist/storage/capabilities.d.ts +10 -2
- package/dist/storage/capabilities.js +2 -2
- package/dist/storage/compressed-storage.js +1 -1
- package/dist/storage/default-scope.d.ts +7 -4
- package/dist/storage/http.js +2 -2
- package/dist/storage/index.d.ts +81 -4
- package/dist/storage/indexeddb.js +1 -1
- package/dist/storage/interface.d.ts +189 -0
- package/dist/storage/interface.js +1 -1
- package/dist/storage/key-prefixes.d.ts +1 -1
- package/dist/storage/key-prefixes.js +12 -0
- package/dist/storage/lmdb.d.ts +4 -3
- package/dist/storage/lmdb.js +1 -1
- package/dist/storage/memory.js +1 -1
- package/dist/storage/neon-batch.d.ts +30 -0
- package/dist/storage/neon-batch.js +30 -0
- package/dist/storage/neon-value-mapping.d.ts +74 -0
- package/dist/storage/neon-value-mapping.js +23 -0
- package/dist/storage/neon.d.ts +124 -0
- package/dist/storage/neon.js +15 -0
- package/dist/storage/node-sqlite-loader.d.ts +71 -0
- package/dist/storage/node-sqlite-loader.js +41 -0
- package/dist/storage/node-sqlite.d.ts +1 -19
- package/dist/storage/node-sqlite.js +61 -32
- package/dist/storage/postgres-key-value-queries.d.ts +104 -0
- package/dist/storage/postgres-key-value-queries.js +101 -0
- package/dist/storage/resolve.d.ts +2 -165
- package/dist/storage/resolve.js +1 -1
- package/dist/storage/scoped-storage.js +1 -1
- package/dist/storage/storage-configuration.d.ts +209 -0
- package/dist/storage/storage-configuration.js +0 -0
- package/dist/storage/testing.d.ts +168 -0
- package/dist/storage/testing.js +2 -0
- package/dist/storage/text-value-store.d.ts +9 -9
- package/dist/storage/turso.d.ts +8 -0
- package/dist/storage/turso.js +2 -2
- package/dist/storage/typed-storage.js +1 -1
- package/dist/storage/web-extension.js +1 -1
- package/dist/testing/index.js +35 -35
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker/index.js +9 -5
- package/dist/worker/long-poll.js +4 -0
- package/dist/worker/protocol-messages.d.ts +20 -0
- package/dist/worker/protocol-schemas.d.ts +32 -0
- package/dist/worker/protocol-schemas.js +8 -4
- package/dist/worker/protocol-task-result.d.ts +28 -0
- package/dist/worker/protocol-task-result.js +76 -0
- package/dist/worker/protocol.d.ts +4 -15
- package/dist/worker/protocol.js +1 -1
- package/dist/worker/registry/fair-share.d.ts +29 -0
- package/dist/worker/registry/fair-share.js +30 -0
- package/dist/worker/registry/routing.d.ts +18 -0
- package/dist/worker/registry/routing.js +14 -0
- package/dist/worker/registry/types.d.ts +7 -0
- package/dist/worker/registry.d.ts +16 -1
- package/dist/worker/registry.js +24 -36
- package/dist/workers/worker-replay-state.d.ts +32 -0
- package/dist/workers/worker-replay-state.js +35 -0
- package/dist/workers/worker-state-namespace.d.ts +21 -0
- package/dist/workers/worker-state-namespace.js +13 -0
- package/dist/workers/workflow-runner.d.ts +19 -15
- package/dist/workers/workflow-runner.js +72 -60
- package/dist/workers/workflow-worker-entry.js +5 -2
- package/package.json +21 -4
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { KEYS, storageConditionalBatch } from "../../storage/interface.js";
|
|
2
|
+
import {
|
|
3
|
+
decodeEpoch,
|
|
4
|
+
decodeHolder,
|
|
5
|
+
encodeEpoch,
|
|
6
|
+
encodeHolder
|
|
7
|
+
} from "./lease-codec.js";
|
|
8
|
+
import { EngineLeaseAcquisitionTimeoutError, EngineLeaseCorruptedError } from "./lease-errors.js";
|
|
9
|
+
const DEFAULT_ACQUIRE_POLL_INTERVAL_MS = 1000;
|
|
10
|
+
export function createLeaseManager(options) {
|
|
11
|
+
const { storage, holderId, getNow, ttlMs, renewIntervalMs, waitTimeoutMs } = options, acquirePollIntervalMs = options.acquirePollIntervalMs ?? DEFAULT_ACQUIRE_POLL_INTERVAL_MS, unconfirmableMarginMs = renewIntervalMs;
|
|
12
|
+
let stopped = !1, heldEpoch = null, heldEpochBytes = null, lastHolderBytes = null, renewalInterval = null, leaseLost = !1, inFlightRenewal = null;
|
|
13
|
+
const delay = options.delay ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
14
|
+
function reportLeaseLost(reason) {
|
|
15
|
+
if (leaseLost)
|
|
16
|
+
return;
|
|
17
|
+
leaseLost = !0;
|
|
18
|
+
options.onLeaseLost?.(reason);
|
|
19
|
+
}
|
|
20
|
+
async function readState() {
|
|
21
|
+
const holderRaw = await storage.get(KEYS.leaseHolder()), epochRaw = await storage.get(KEYS.leaseEpoch());
|
|
22
|
+
return {
|
|
23
|
+
epochRaw,
|
|
24
|
+
holderRaw,
|
|
25
|
+
epoch: epochRaw === null ? null : decodeEpoch(epochRaw),
|
|
26
|
+
holder: holderRaw === null ? null : decodeHolder(holderRaw)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
async function takeOwnership(expectedEpochBytes, expectedHolderBytes, nextEpoch) {
|
|
30
|
+
const expiresAt = getNow() + ttlMs, holderBytes = encodeHolder({ holderId, expiresAt, epoch: nextEpoch }), committed = await storageConditionalBatch(storage, [
|
|
31
|
+
{ key: KEYS.leaseEpoch(), expectedValue: expectedEpochBytes },
|
|
32
|
+
{ key: KEYS.leaseHolder(), expectedValue: expectedHolderBytes }
|
|
33
|
+
], [
|
|
34
|
+
{ type: "put", key: KEYS.leaseEpoch(), value: encodeEpoch(nextEpoch) },
|
|
35
|
+
{ type: "put", key: KEYS.leaseHolder(), value: holderBytes }
|
|
36
|
+
]);
|
|
37
|
+
if (committed) {
|
|
38
|
+
heldEpoch = nextEpoch;
|
|
39
|
+
heldEpochBytes = encodeEpoch(nextEpoch);
|
|
40
|
+
lastHolderBytes = holderBytes;
|
|
41
|
+
}
|
|
42
|
+
return committed;
|
|
43
|
+
}
|
|
44
|
+
async function tryAcquireOnce() {
|
|
45
|
+
const { epochRaw, holderRaw, epoch, holder } = await readState();
|
|
46
|
+
if (epochRaw !== null && epoch === null)
|
|
47
|
+
throw new EngineLeaseCorruptedError('the "lease:epoch" high-water mark is present but does not decode to a valid epoch');
|
|
48
|
+
if (epochRaw === null && holderRaw !== null)
|
|
49
|
+
throw new EngineLeaseCorruptedError('a "lease:holder" record exists with no "lease:epoch" key (the lease protocol never deletes the epoch)');
|
|
50
|
+
if (holder !== null && getNow() < holder.expiresAt)
|
|
51
|
+
return !1;
|
|
52
|
+
const nextEpoch = (epoch ?? 0) + 1;
|
|
53
|
+
if (nextEpoch >= Number.MAX_SAFE_INTEGER)
|
|
54
|
+
throw new EngineLeaseCorruptedError(`the next ownership epoch (${nextEpoch}) is at or above the safe-integer ceiling and cannot be minted without bricking future boots`);
|
|
55
|
+
return takeOwnership(epochRaw, holderRaw, nextEpoch);
|
|
56
|
+
}
|
|
57
|
+
async function acquire() {
|
|
58
|
+
const startedAt = getNow(), deadline = startedAt + waitTimeoutMs;
|
|
59
|
+
let lastHolderId = null, firstAttempt = !0;
|
|
60
|
+
for (;; ) {
|
|
61
|
+
if (stopped)
|
|
62
|
+
return;
|
|
63
|
+
if (!firstAttempt && getNow() >= deadline)
|
|
64
|
+
throw new EngineLeaseAcquisitionTimeoutError(getNow() - startedAt, lastHolderId);
|
|
65
|
+
firstAttempt = !1;
|
|
66
|
+
if (await tryAcquireOnce())
|
|
67
|
+
return;
|
|
68
|
+
const holderRaw = await storage.get(KEYS.leaseHolder());
|
|
69
|
+
lastHolderId = holderRaw === null ? null : decodeHolder(holderRaw)?.holderId ?? null;
|
|
70
|
+
if (getNow() >= deadline)
|
|
71
|
+
throw new EngineLeaseAcquisitionTimeoutError(getNow() - startedAt, lastHolderId);
|
|
72
|
+
await delay(acquirePollIntervalMs);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async function renewOnce() {
|
|
76
|
+
if (stopped || leaseLost || heldEpoch === null || lastHolderBytes === null)
|
|
77
|
+
return;
|
|
78
|
+
const expiresAt = getNow() + ttlMs, holderBytes = encodeHolder({ holderId, expiresAt, epoch: heldEpoch });
|
|
79
|
+
let committed;
|
|
80
|
+
try {
|
|
81
|
+
committed = await storageConditionalBatch(storage, [{ key: KEYS.leaseHolder(), expectedValue: lastHolderBytes }], [{ type: "put", key: KEYS.leaseHolder(), value: holderBytes }]);
|
|
82
|
+
} catch {
|
|
83
|
+
const priorExpiry = decodeHolder(lastHolderBytes)?.expiresAt ?? 0;
|
|
84
|
+
if (getNow() >= priorExpiry - unconfirmableMarginMs)
|
|
85
|
+
reportLeaseLost("renewal-unconfirmable");
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (committed) {
|
|
89
|
+
lastHolderBytes = holderBytes;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
reportLeaseLost("deposed");
|
|
93
|
+
}
|
|
94
|
+
function renewUnderGuard() {
|
|
95
|
+
if (inFlightRenewal !== null)
|
|
96
|
+
return;
|
|
97
|
+
inFlightRenewal = renewOnce().catch(() => {}).finally(() => {
|
|
98
|
+
inFlightRenewal = null;
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
function startRenewal() {
|
|
102
|
+
if (stopped || renewalInterval !== null)
|
|
103
|
+
return;
|
|
104
|
+
renewalInterval = setInterval(() => {
|
|
105
|
+
renewUnderGuard();
|
|
106
|
+
}, renewIntervalMs);
|
|
107
|
+
renewalInterval.unref?.();
|
|
108
|
+
}
|
|
109
|
+
function currentEpochBytes() {
|
|
110
|
+
return heldEpochBytes === null ? null : heldEpochBytes.slice();
|
|
111
|
+
}
|
|
112
|
+
function clearRenewal() {
|
|
113
|
+
if (renewalInterval !== null) {
|
|
114
|
+
clearInterval(renewalInterval);
|
|
115
|
+
renewalInterval = null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async function release() {
|
|
119
|
+
stopped = !0;
|
|
120
|
+
clearRenewal();
|
|
121
|
+
if (inFlightRenewal !== null)
|
|
122
|
+
await inFlightRenewal;
|
|
123
|
+
if (lastHolderBytes === null)
|
|
124
|
+
return;
|
|
125
|
+
try {
|
|
126
|
+
if (await storageConditionalBatch(storage, [{ key: KEYS.leaseHolder(), expectedValue: lastHolderBytes }], [{ type: "delete", key: KEYS.leaseHolder() }]))
|
|
127
|
+
lastHolderBytes = null;
|
|
128
|
+
} catch {}
|
|
129
|
+
}
|
|
130
|
+
function stop() {
|
|
131
|
+
stopped = !0;
|
|
132
|
+
clearRenewal();
|
|
133
|
+
}
|
|
134
|
+
return { acquire, startRenewal, renewOnce, currentEpochBytes, release, stop };
|
|
135
|
+
}
|
|
@@ -22,17 +22,11 @@ export function createForkedWorkflowState(_internals, workflowId, sourceState, v
|
|
|
22
22
|
type: sourceState.type,
|
|
23
23
|
status: "running",
|
|
24
24
|
input: sourceState.input,
|
|
25
|
-
|
|
25
|
+
versionTuple,
|
|
26
26
|
executionStateOwnerId: workflowId,
|
|
27
27
|
createdAt: forkedAt,
|
|
28
28
|
startedAt: forkedAt,
|
|
29
29
|
updatedAt: forkedAt,
|
|
30
|
-
...versionTuple.agentVersion !== void 0 && {
|
|
31
|
-
agentVersion: versionTuple.agentVersion
|
|
32
|
-
},
|
|
33
|
-
...versionTuple.toolVersions !== void 0 && {
|
|
34
|
-
toolVersions: versionTuple.toolVersions
|
|
35
|
-
},
|
|
36
30
|
forkedFrom: lineage
|
|
37
31
|
};
|
|
38
32
|
}
|
|
@@ -1,80 +1,43 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { encode } from "../../codec.js";
|
|
3
|
-
import {
|
|
4
|
-
VersionMismatchError,
|
|
5
|
-
buildVersionUpdateOperations,
|
|
6
|
-
checkVersionCompatibility,
|
|
7
|
-
migrateCheckpoint
|
|
8
|
-
} from "../../versioning.js";
|
|
1
|
+
import { VersionMismatchError, checkVersionCompatibility } from "../../versioning.js";
|
|
9
2
|
import {
|
|
10
3
|
diffWorkflowVersionTuples
|
|
11
4
|
} from "../../workflow-version-tuple.js";
|
|
12
|
-
import {
|
|
5
|
+
import { hydrateCheckpointReplayState } from "../checkpoint-replay.js";
|
|
13
6
|
export function createWorkflowVersionTuple(_internals, registration, _callbacks) {
|
|
14
7
|
return {
|
|
15
8
|
workflowVersion: registration.version
|
|
16
9
|
};
|
|
17
10
|
}
|
|
18
11
|
export function workflowVersionTupleFromState(_internals, state, _callbacks) {
|
|
19
|
-
return
|
|
20
|
-
workflowVersion: state.version,
|
|
21
|
-
...state.agentVersion !== void 0 && { agentVersion: state.agentVersion },
|
|
22
|
-
...state.toolVersions !== void 0 && { toolVersions: state.toolVersions }
|
|
23
|
-
};
|
|
12
|
+
return state.versionTuple;
|
|
24
13
|
}
|
|
25
14
|
export function workflowStateWithVersionTuple(internals, state, versionTuple, _callbacks) {
|
|
26
|
-
const {
|
|
27
|
-
agentVersion: _existingAgentVersion,
|
|
28
|
-
toolVersions: _existingToolVersions,
|
|
29
|
-
...rest
|
|
30
|
-
} = state;
|
|
31
15
|
return {
|
|
32
|
-
...
|
|
33
|
-
|
|
34
|
-
updatedAt: internals.options.getNow()
|
|
35
|
-
...versionTuple.agentVersion !== void 0 && {
|
|
36
|
-
agentVersion: versionTuple.agentVersion
|
|
37
|
-
},
|
|
38
|
-
...versionTuple.toolVersions !== void 0 && {
|
|
39
|
-
toolVersions: versionTuple.toolVersions
|
|
40
|
-
}
|
|
16
|
+
...state,
|
|
17
|
+
versionTuple,
|
|
18
|
+
updatedAt: internals.options.getNow()
|
|
41
19
|
};
|
|
42
20
|
}
|
|
43
21
|
export function derivePreparedExecutionState(internals, workflowId, state, checkpoint, registration, callbacks) {
|
|
44
|
-
const compatibility = checkVersionCompatibility(checkpoint.version, registration.version
|
|
45
|
-
if (compatibility === "incompatible" || hasVersionTupleDrift
|
|
22
|
+
const compatibility = checkVersionCompatibility(checkpoint.version, registration.version), registeredVersionTuple = createWorkflowVersionTuple(internals, registration, callbacks), versionDiff = diffWorkflowVersionTuples(workflowVersionTupleFromState(internals, state, callbacks), registeredVersionTuple), hasVersionTupleDrift = versionDiff.workflowVersion !== void 0 || versionDiff.agentVersion !== void 0 || versionDiff.toolVersions !== void 0;
|
|
23
|
+
if (compatibility === "incompatible" || hasVersionTupleDrift)
|
|
46
24
|
throwVersionMismatch(internals, workflowId, state, registration, versionDiff, callbacks);
|
|
47
|
-
let preparedState = state, preparedCheckpoint = checkpoint, shouldPersistPreparedState = !1;
|
|
48
|
-
if ((compatibility === "needs-migration" || hasVersionTupleDrift) && registration.migrate) {
|
|
49
|
-
const migrated = migrateCheckpoint(checkpoint, checkpoint.version, registration.version, registration.migrate);
|
|
50
|
-
migrated.version = registeredVersionTuple.workflowVersion;
|
|
51
|
-
preparedCheckpoint = migrated;
|
|
52
|
-
preparedState = workflowStateWithVersionTuple(internals, state, registeredVersionTuple, callbacks);
|
|
53
|
-
shouldPersistPreparedState = !0;
|
|
54
|
-
}
|
|
55
25
|
return {
|
|
56
|
-
state
|
|
57
|
-
checkpoint
|
|
26
|
+
state,
|
|
27
|
+
checkpoint,
|
|
58
28
|
versionTuple: registeredVersionTuple,
|
|
59
|
-
shouldPersistPreparedState
|
|
29
|
+
shouldPersistPreparedState: !1
|
|
60
30
|
};
|
|
61
31
|
}
|
|
62
32
|
export async function prepareResumeState(internals, workflowId, state, checkpoint, checkpointBytes, registration, callbacks) {
|
|
63
|
-
const preparedExecutionState = derivePreparedExecutionState(internals, workflowId, state, checkpoint, registration, callbacks);
|
|
64
|
-
if (preparedExecutionState.shouldPersistPreparedState) {
|
|
65
|
-
const versionVisibilityOperations = buildWorkflowVisibilityIndexTransition(workflowId, state, preparedExecutionState.state).batchOps;
|
|
66
|
-
await internals.storage.batch([
|
|
67
|
-
...buildVersionUpdateOperations(workflowId, serializeCheckpoint(preparedExecutionState.checkpoint), preparedExecutionState.versionTuple.workflowVersion, encode(preparedExecutionState.state)),
|
|
68
|
-
...versionVisibilityOperations
|
|
69
|
-
]);
|
|
70
|
-
}
|
|
33
|
+
const preparedExecutionState = derivePreparedExecutionState(internals, workflowId, state, checkpoint, registration, callbacks), hydratedCheckpoint = await hydrateCheckpointReplayState(internals.storage, workflowId, preparedExecutionState.checkpoint);
|
|
71
34
|
return {
|
|
72
35
|
state: preparedExecutionState.state,
|
|
73
|
-
checkpoint:
|
|
74
|
-
serializedCheckpoint:
|
|
36
|
+
checkpoint: hydratedCheckpoint,
|
|
37
|
+
serializedCheckpoint: checkpointBytes,
|
|
75
38
|
versionTuple: preparedExecutionState.versionTuple
|
|
76
39
|
};
|
|
77
40
|
}
|
|
78
41
|
export function throwVersionMismatch(_internals, workflowId, state, registration, versionDiff, _callbacks) {
|
|
79
|
-
throw new VersionMismatchError(workflowId, state.type, state.
|
|
42
|
+
throw new VersionMismatchError(workflowId, state.type, state.versionTuple.workflowVersion, registration.version, void 0, versionDiff);
|
|
80
43
|
}
|
|
@@ -16,8 +16,8 @@ import type { EngineInternals } from '../internals.ts';
|
|
|
16
16
|
* has no marker and proceeds without touching the resolver — so a fail-closed
|
|
17
17
|
* resolver does not fail healthy no-services runs.
|
|
18
18
|
*
|
|
19
|
-
* Returns `false` to proceed (services available
|
|
20
|
-
*
|
|
19
|
+
* Returns `false` to proceed (services available or none expected). Returns
|
|
20
|
+
* `true` to STOP — the run was terminally
|
|
21
21
|
* failed (services unavailable), or the terminal commit faulted and the run was
|
|
22
22
|
* left for a later boot to retry. Either way the generator must not advance:
|
|
23
23
|
* driving it without services would crash the body and that throw would escape
|
|
@@ -36,10 +36,12 @@ import type { EngineInternals } from '../internals.ts';
|
|
|
36
36
|
* @param onCommitError - Records a fail-warn when `failRun` itself throws, so the
|
|
37
37
|
* swallowed terminal-commit fault is still observable.
|
|
38
38
|
*/
|
|
39
|
-
export declare function reprovideRecoveredServices(internals: EngineInternals, state: WorkflowState, failRun: (workflowId: string, error: Error) => Promise<void>, onCommitError: (source: string, error: unknown, workflowId: string) => void): Promise<boolean>;
|
|
39
|
+
export declare function reprovideRecoveredServices(internals: EngineInternals, state: WorkflowState, failRun: (workflowId: string, error: Error) => Promise<void>, onCommitError: (source: string, error: unknown, workflowId: string) => void, dispatchDiagnostic?: (event: Event) => void): Promise<boolean>;
|
|
40
40
|
/**
|
|
41
|
-
* The canonical terminal error for
|
|
42
|
-
*
|
|
43
|
-
* message (the failure category is `system`,
|
|
41
|
+
* The canonical terminal error for any run whose services could not be provided —
|
|
42
|
+
* both recovery re-provision paths and a scheduled-occurrence launch. Shared so
|
|
43
|
+
* every caller fails with an identical message (the failure category is `system`,
|
|
44
|
+
* the default for `failWorkflow`). The message is recovery-agnostic because a
|
|
45
|
+
* freshly launched scheduled occurrence has never been recovered.
|
|
44
46
|
*/
|
|
45
47
|
export declare function unavailableServicesError(workflowId: string, reason: string): Error;
|
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
import { KEYS } from "../../../storage/interface.js";
|
|
2
|
-
|
|
2
|
+
import { DevelopmentWarningEvent } from "../../events.js";
|
|
3
|
+
const RESOLVE_WORKFLOW_SERVICES_OPTION_PATH = "EngineOptions.resolveWorkflowServices";
|
|
4
|
+
export async function reprovideRecoveredServices(internals, state, failRun, onCommitError, dispatchDiagnostic = () => {}) {
|
|
3
5
|
const resolver = internals.options.resolveWorkflowServices;
|
|
4
|
-
if (internals.inlineStrategy === null
|
|
6
|
+
if (internals.inlineStrategy === null)
|
|
5
7
|
return !1;
|
|
6
8
|
if (internals.workflowServices.has(state.id))
|
|
7
9
|
return !1;
|
|
8
10
|
if (await internals.storage.get(KEYS.workflowHasServices(state.id)) === null)
|
|
9
11
|
return !1;
|
|
12
|
+
if (!resolver) {
|
|
13
|
+
const reason = missingServicesResolverReason(state.id);
|
|
14
|
+
dispatchDiagnostic(new DevelopmentWarningEvent(state.id, reason, [RESOLVE_WORKFLOW_SERVICES_OPTION_PATH]));
|
|
15
|
+
try {
|
|
16
|
+
await failRun(state.id, unavailableServicesError(state.id, reason));
|
|
17
|
+
} catch (error) {
|
|
18
|
+
onCommitError("reprovideRecoveredServices", error, state.id);
|
|
19
|
+
}
|
|
20
|
+
return !0;
|
|
21
|
+
}
|
|
10
22
|
let reason;
|
|
11
23
|
try {
|
|
12
24
|
const resolution = await resolver({
|
|
@@ -30,5 +42,8 @@ export async function reprovideRecoveredServices(internals, state, failRun, onCo
|
|
|
30
42
|
return !0;
|
|
31
43
|
}
|
|
32
44
|
export function unavailableServicesError(workflowId, reason) {
|
|
33
|
-
return Error(`
|
|
45
|
+
return Error(`Workflow "${workflowId}" services unavailable: ${reason}`);
|
|
46
|
+
}
|
|
47
|
+
function missingServicesResolverReason(workflowId) {
|
|
48
|
+
return `Workflow "${workflowId}" was started with services, but this engine has no resolveWorkflowServices option. Configure EngineOptions.resolveWorkflowServices before recovery so ctx.services can be re-provided.`;
|
|
34
49
|
}
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { KEYS } from "../../../storage/interface.js";
|
|
2
2
|
import { deserializeCheckpoint, serializeCheckpoint } from "../../checkpoint.js";
|
|
3
|
+
import { encode } from "../../codec.js";
|
|
3
4
|
import { Context, setContextWorkflowInterceptor } from "../../context.js";
|
|
4
5
|
import { EventLog } from "../../event-log.js";
|
|
5
6
|
import { WorkflowResumedEvent } from "../../events.js";
|
|
7
|
+
import { buildTimerBatchOperations } from "../../scheduler.js";
|
|
6
8
|
import { createCancelHandlerRegistration, resetCancelHandlers } from "../cancel-handlers.js";
|
|
7
9
|
import { rememberCommittedCheckpointBytes } from "../checkpoint-commit-snapshots.js";
|
|
10
|
+
import { rehydrateChildCancellationHandlers } from "../child-workflow-cancellation.js";
|
|
11
|
+
import { commitFencedEngineWrite } from "../fenced-write.js";
|
|
8
12
|
import { getWorkflowExecutionStartedAt } from "../handles.js";
|
|
9
13
|
import { loadWorkflowState } from "../storage-io.js";
|
|
10
14
|
import { getComposedWorkflowInterceptor } from "../strategy-helpers.js";
|
|
11
15
|
import { decodeWorkflowState } from "../validation.js";
|
|
16
|
+
import { buildWorkflowVisibilityIndexTransition } from "../workflow-indexes.js";
|
|
12
17
|
import { prepareResumeState } from "./persist.js";
|
|
13
18
|
import { reprovideRecoveredServices } from "./recovered-services.js";
|
|
14
19
|
import {
|
|
@@ -18,7 +23,7 @@ import {
|
|
|
18
23
|
setWorkflowStartHeaders
|
|
19
24
|
} from "./shared.js";
|
|
20
25
|
async function prepareRecoveredServicesOrFail(internals, state, callbacks) {
|
|
21
|
-
return reprovideRecoveredServices(internals, state, callbacks.failWorkflowForUnavailableServices, callbacks.handleCleanupError);
|
|
26
|
+
return reprovideRecoveredServices(internals, state, callbacks.failWorkflowForUnavailableServices, callbacks.handleCleanupError, callbacks.dispatchEvent);
|
|
22
27
|
}
|
|
23
28
|
function assertResumeNotTerminating(internals, workflowId) {
|
|
24
29
|
if (internals.terminalizingWorkflows.has(workflowId))
|
|
@@ -40,9 +45,10 @@ function commitSerializedResumeState(internals, args) {
|
|
|
40
45
|
setWorkflowStartHeaders(internals, workflowId, args.workflowStartHeaders, callbacks);
|
|
41
46
|
internals.parkedInlineWorkflows.delete(workflowId);
|
|
42
47
|
}
|
|
43
|
-
function relaunchInlineWorkflowAfterResume(internals, latestState, args) {
|
|
48
|
+
async function relaunchInlineWorkflowAfterResume(internals, latestState, args) {
|
|
44
49
|
const { workflowId, resumeCheckpoint, registration, callbacks } = args, accumulatedResults = new Map(resumeCheckpoint.accumulatedResults), workflowAbort = new AbortController;
|
|
45
50
|
resetCancelHandlers(internals, workflowId);
|
|
51
|
+
await rehydrateChildCancellationHandlers(internals, workflowId, callbacks);
|
|
46
52
|
const context = new Context({
|
|
47
53
|
workflowId,
|
|
48
54
|
workflowType: latestState.type,
|
|
@@ -62,7 +68,8 @@ function relaunchInlineWorkflowAfterResume(internals, latestState, args) {
|
|
|
62
68
|
...latestState.executionDeadline !== void 0 && {
|
|
63
69
|
deadline: latestState.executionDeadline
|
|
64
70
|
},
|
|
65
|
-
services: internals.workflowServices.get(workflowId)
|
|
71
|
+
services: internals.workflowServices.get(workflowId),
|
|
72
|
+
...internals.options.onLog != null && { logSink: internals.options.onLog }
|
|
66
73
|
});
|
|
67
74
|
setContextWorkflowInterceptor(context, getComposedWorkflowInterceptor(internals));
|
|
68
75
|
if (internals.options.development)
|
|
@@ -71,8 +78,11 @@ function relaunchInlineWorkflowAfterResume(internals, latestState, args) {
|
|
|
71
78
|
inlineStrategy.adoptWorkflow(workflowId, generator, context, workflowAbort);
|
|
72
79
|
inlineStrategy.continueWorkflow(workflowId, void 0);
|
|
73
80
|
}
|
|
74
|
-
function relaunchWorkerWorkflowAfterResume(internals, latestState, args) {
|
|
75
|
-
const { workflowId, resumeCheckpoint, workflowStartHeaders } = args
|
|
81
|
+
async function relaunchWorkerWorkflowAfterResume(internals, latestState, args) {
|
|
82
|
+
const { workflowId, resumeCheckpoint, workflowStartHeaders, callbacks } = args;
|
|
83
|
+
resetCancelHandlers(internals, workflowId);
|
|
84
|
+
await rehydrateChildCancellationHandlers(internals, workflowId, callbacks);
|
|
85
|
+
const serialized = serializeCheckpoint(resumeCheckpoint);
|
|
76
86
|
internals.strategy.startWorkflow({
|
|
77
87
|
workflowId,
|
|
78
88
|
workflowType: latestState.type,
|
|
@@ -95,22 +105,40 @@ async function performSerializedResume(internals, args) {
|
|
|
95
105
|
assertResumeNotTerminating(internals, workflowId);
|
|
96
106
|
if (!latestState)
|
|
97
107
|
throw Error(`Workflow "${workflowId}" not found in storage`);
|
|
98
|
-
if (latestState.status !== "running")
|
|
99
|
-
throw Error(`Cannot resume workflow "${workflowId}": status is "${latestState.status}", expected "running"`);
|
|
108
|
+
if (latestState.status !== "running" && latestState.status !== "suspended")
|
|
109
|
+
throw Error(`Cannot resume workflow "${workflowId}": status is "${latestState.status}", expected "running" or "suspended"`);
|
|
110
|
+
await reactivateSuspendedWorkflowState(internals, latestState);
|
|
100
111
|
commitSerializedResumeState(internals, args);
|
|
101
112
|
if (internals.inlineStrategy) {
|
|
102
|
-
relaunchInlineWorkflowAfterResume(internals, latestState, args);
|
|
113
|
+
await relaunchInlineWorkflowAfterResume(internals, latestState, args);
|
|
103
114
|
return;
|
|
104
115
|
}
|
|
105
|
-
relaunchWorkerWorkflowAfterResume(internals, latestState, args);
|
|
116
|
+
await relaunchWorkerWorkflowAfterResume(internals, latestState, args);
|
|
117
|
+
}
|
|
118
|
+
async function reactivateSuspendedWorkflowState(internals, state) {
|
|
119
|
+
if (state.status !== "suspended")
|
|
120
|
+
return;
|
|
121
|
+
const previousState = { ...state };
|
|
122
|
+
state.status = "running";
|
|
123
|
+
state.updatedAt = internals.options.getNow();
|
|
124
|
+
await commitFencedEngineWrite(internals, [
|
|
125
|
+
{ type: "put", key: KEYS.workflow(state.id), value: encode(state) },
|
|
126
|
+
...buildWorkflowVisibilityIndexTransition(state.id, previousState, state).batchOps,
|
|
127
|
+
...state.executionDeadline !== void 0 ? buildTimerBatchOperations({
|
|
128
|
+
id: `deadline:${state.id}`,
|
|
129
|
+
workflowId: state.id,
|
|
130
|
+
fireAt: state.executionDeadline,
|
|
131
|
+
kind: "execution-deadline"
|
|
132
|
+
}) : []
|
|
133
|
+
], [], () => Error(`Resume of workflow "${state.id}" lost its CAS race.`));
|
|
106
134
|
}
|
|
107
135
|
export async function resumeWorkflowFromStorage(internals, workflowId, dispatchResumedEvent, callbacks) {
|
|
108
136
|
const stateBytes = await internals.storage.get(KEYS.workflow(workflowId));
|
|
109
137
|
if (!stateBytes)
|
|
110
138
|
throw Error(`Workflow "${workflowId}" not found in storage`);
|
|
111
139
|
const state = decodeWorkflowState(stateBytes);
|
|
112
|
-
if (state.status !== "running")
|
|
113
|
-
throw Error(`Cannot resume workflow "${workflowId}": status is "${state.status}", expected "running"`);
|
|
140
|
+
if (state.status !== "running" && state.status !== "suspended")
|
|
141
|
+
throw Error(`Cannot resume workflow "${workflowId}": status is "${state.status}", expected "running" or "suspended"`);
|
|
114
142
|
const checkpointBytes = await internals.storage.get(KEYS.checkpoint(workflowId));
|
|
115
143
|
if (!checkpointBytes)
|
|
116
144
|
throw Error(`Checkpoint not found for workflow "${workflowId}"`);
|
|
@@ -22,7 +22,7 @@ export declare const EMPTY_STORAGE_VALUE: Uint8Array<ArrayBuffer>;
|
|
|
22
22
|
export type RecoverAllOptions = {
|
|
23
23
|
/**
|
|
24
24
|
* Skip stored running workflows whose type is not registered. Use only for
|
|
25
|
-
* rolling deploys or explicit storage
|
|
25
|
+
* rolling deploys or explicit operator storage repair.
|
|
26
26
|
*/
|
|
27
27
|
acknowledgeUnknownWorkflowTypes?: boolean;
|
|
28
28
|
};
|
|
@@ -56,6 +56,13 @@ export type LifecycleCallbacks = {
|
|
|
56
56
|
* `error` is the canonical {@link unavailableServicesError}.
|
|
57
57
|
*/
|
|
58
58
|
failWorkflowForUnavailableServices: (workflowId: string, error: Error) => Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Force a recovered workflow to a terminal `failed` state because its
|
|
61
|
+
* persisted checkpoint cannot be decoded on this runtime. The failure is
|
|
62
|
+
* isolated to the affected run so `recoverAll()` can continue recovering
|
|
63
|
+
* other workflows from the same storage backend.
|
|
64
|
+
*/
|
|
65
|
+
failWorkflowForCheckpointDecodeError: (workflowId: string, error: Error) => Promise<void>;
|
|
59
66
|
};
|
|
60
67
|
/**
|
|
61
68
|
* Pre-replay history circuit breaker. Called at every restore-from-checkpoint
|
|
@@ -2,6 +2,6 @@ import type { BatchOperation } from '../../../storage/interface.ts';
|
|
|
2
2
|
import type { Checkpoint, SearchAttributeValue, StartOptions, TimerEntry, WorkflowState } from '../../types.ts';
|
|
3
3
|
import type { EngineInternals } from '../internals.ts';
|
|
4
4
|
import { type LifecycleCallbacks, type RegistrationEntry } from './shared.ts';
|
|
5
|
-
export declare function buildStartBatchOperations(_internals: EngineInternals, workflowId: string, state: WorkflowState, checkpoint: Checkpoint, registration: RegistrationEntry, options: StartOptions | undefined, executionDeadline: number | undefined, delayedStartTimer: TimerEntry | undefined, workflowStartHeaders: Map<string, string> | undefined, additionalOperations: BatchOperation[] | undefined, callbacks: LifecycleCallbacks): BatchOperation[];
|
|
5
|
+
export declare function buildStartBatchOperations(_internals: EngineInternals, workflowId: string, state: WorkflowState, checkpoint: Checkpoint, registration: RegistrationEntry, options: StartOptions | undefined, executionDeadline: number | undefined, delayedStartTimer: TimerEntry | undefined, workflowStartHeaders: Map<string, string> | undefined, additionalOperations: BatchOperation[] | undefined, callbacks: LifecycleCallbacks, purgeDeleteOperations: BatchOperation[] | undefined): BatchOperation[];
|
|
6
6
|
export declare function buildInitialSearchAttributeOperations(_internals: EngineInternals, workflowId: string, registration: RegistrationEntry, searchAttributes: StartOptions['searchAttributes'], callbacks: LifecycleCallbacks): BatchOperation[];
|
|
7
7
|
export declare function validateSearchAttributes(_internals: EngineInternals, registration: RegistrationEntry, searchAttributes: Record<string, SearchAttributeValue>, _callbacks: LifecycleCallbacks): void;
|
|
@@ -8,8 +8,9 @@ import { validateAttributeValueSizes } from "../attributes-tags.js";
|
|
|
8
8
|
import { encodeWorkflowStartHeaders } from "../state-utilities.js";
|
|
9
9
|
import { buildWorkflowVisibilityIndexOperations } from "../workflow-indexes.js";
|
|
10
10
|
import { EMPTY_STORAGE_VALUE } from "./shared.js";
|
|
11
|
-
export function buildStartBatchOperations(_internals, workflowId, state, checkpoint, registration, options, executionDeadline, delayedStartTimer, workflowStartHeaders, additionalOperations, callbacks) {
|
|
11
|
+
export function buildStartBatchOperations(_internals, workflowId, state, checkpoint, registration, options, executionDeadline, delayedStartTimer, workflowStartHeaders, additionalOperations, callbacks, purgeDeleteOperations) {
|
|
12
12
|
const visibilityIndexOperations = buildWorkflowVisibilityIndexOperations(workflowId, null, state).batchOps, operations = [
|
|
13
|
+
...purgeDeleteOperations ?? [],
|
|
13
14
|
{ type: "put", key: KEYS.workflow(workflowId), value: encode(state) },
|
|
14
15
|
{
|
|
15
16
|
type: "put",
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { BatchOperation, ConditionalBatchCondition } from '../../../storage/interface.ts';
|
|
2
|
+
import type { Checkpoint, StartOptions, TimerEntry, WorkflowState } from '../../types.ts';
|
|
3
|
+
import type { EngineInternals } from '../internals.ts';
|
|
4
|
+
import type { WorkflowConcurrencyStartOperations } from '../workflow-concurrency.ts';
|
|
5
|
+
import { type LifecycleCallbacks, type RegistrationEntry } from './shared.ts';
|
|
6
|
+
/**
|
|
7
|
+
* Builds the id-dependent operations and compare-and-swap preconditions for an
|
|
8
|
+
* idempotent start or `startOrSignal`. Invoked by `startWorkflow` with the real
|
|
9
|
+
* `workflowId` once it has been generated, so the idempotency mapping put (and
|
|
10
|
+
* any create-batch signal) can carry that id. The whole start batch then commits
|
|
11
|
+
* through a single `storageConditionalBatch` gated on the returned conditions; a
|
|
12
|
+
* lost CAS rolls back the start and throws {@link StartIdempotencyRaceLostError}
|
|
13
|
+
* so the caller resolves to the winner.
|
|
14
|
+
*/
|
|
15
|
+
export type BuildIdempotentStartOperations = (workflowId: string) => {
|
|
16
|
+
operations: BatchOperation[];
|
|
17
|
+
conditions: ConditionalBatchCondition[];
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Internal sentinel: the idempotent create batch lost its compare-and-swap to a
|
|
21
|
+
* concurrent caller holding the same idempotency key. Never surfaced to users —
|
|
22
|
+
* `start` / `startOrSignal` catch it and resolve to the winning run's handle.
|
|
23
|
+
*/
|
|
24
|
+
export declare class StartIdempotencyRaceLostError extends Error {
|
|
25
|
+
constructor();
|
|
26
|
+
}
|
|
27
|
+
/** Everything {@link buildAndCommitStartBatch} needs to assemble the start batch. */
|
|
28
|
+
export type StartBatchContext = {
|
|
29
|
+
internals: EngineInternals;
|
|
30
|
+
workflowId: string;
|
|
31
|
+
state: WorkflowState;
|
|
32
|
+
checkpoint: Checkpoint;
|
|
33
|
+
registration: RegistrationEntry;
|
|
34
|
+
options: StartOptions | undefined;
|
|
35
|
+
delayedStartTimer: TimerEntry | undefined;
|
|
36
|
+
persistedWorkflowStartHeaders: Map<string, string> | undefined;
|
|
37
|
+
additionalStartOperations: BatchOperation[] | undefined;
|
|
38
|
+
buildWorkflowConcurrencyStartOperations: (() => Promise<WorkflowConcurrencyStartOperations | undefined>) | undefined;
|
|
39
|
+
callbacks: LifecycleCallbacks;
|
|
40
|
+
/**
|
|
41
|
+
* Storage deletes for a prior terminal run being displaced by an
|
|
42
|
+
* `onTerminalConflict: 'start-new'` restart. Prepended ahead of the create puts
|
|
43
|
+
* so purge-and-recreate commit as one atomic batch (see
|
|
44
|
+
* {@link buildStartBatchOperations}). Undefined for an ordinary start.
|
|
45
|
+
*/
|
|
46
|
+
purgeDeleteOperations: BatchOperation[] | undefined;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Assemble the start batch — folding in the id-dependent idempotency mapping and
|
|
50
|
+
* create-batch signal once the real workflow id exists — and commit it, gated on
|
|
51
|
+
* any idempotency preconditions. Throws {@link StartIdempotencyRaceLostError}
|
|
52
|
+
* when a concurrent same-key caller won the compare-and-swap, so the calling
|
|
53
|
+
* `startWorkflow` rolls back its transient state and the wrapper resolves to the
|
|
54
|
+
* winning run.
|
|
55
|
+
*/
|
|
56
|
+
export declare function buildAndCommitStartBatch(context: StartBatchContext, buildIdempotentStartOperations: BuildIdempotentStartOperations | undefined): Promise<void>;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { requireStorageCapability, storageValuesEqual } from "../../../storage/interface.js";
|
|
2
|
+
import { AtomicStateConflictError } from "../../atomic-state.js";
|
|
3
|
+
import {
|
|
4
|
+
commitFencedEngineWrite,
|
|
5
|
+
commitFencedEngineWriteAllowingPreconditionFailure
|
|
6
|
+
} from "../fenced-write.js";
|
|
7
|
+
import { buildStartBatchOperations } from "./start-batch.js";
|
|
8
|
+
|
|
9
|
+
export class StartIdempotencyRaceLostError extends Error {
|
|
10
|
+
constructor() {
|
|
11
|
+
super("start idempotency compare-and-swap lost to a concurrent caller");
|
|
12
|
+
this.name = "StartIdempotencyRaceLostError";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
const WORKFLOW_CONCURRENCY_ADMISSION_MAX_ATTEMPTS = 5;
|
|
16
|
+
async function persistStartBatch(internals, startOperations, conditions) {
|
|
17
|
+
if (conditions.length === 0) {
|
|
18
|
+
await commitFencedEngineWrite(internals, startOperations, [], () => Error("Workflow start lost its CAS race."));
|
|
19
|
+
return !0;
|
|
20
|
+
}
|
|
21
|
+
requireStorageCapability(internals.storage, "conditionalBatch", "start preconditions");
|
|
22
|
+
return commitFencedEngineWriteAllowingPreconditionFailure(internals, startOperations, conditions.map((entry) => entry.condition));
|
|
23
|
+
}
|
|
24
|
+
async function hasStartPreconditionConflict(internals, conditions) {
|
|
25
|
+
for (const entry of conditions) {
|
|
26
|
+
if (entry.source !== "start-precondition")
|
|
27
|
+
continue;
|
|
28
|
+
const currentValue = await internals.storage.get(entry.condition.key);
|
|
29
|
+
if (!storageValuesEqual(currentValue, entry.condition.expectedValue))
|
|
30
|
+
return !0;
|
|
31
|
+
}
|
|
32
|
+
return !1;
|
|
33
|
+
}
|
|
34
|
+
function tagStartPreconditions(conditions) {
|
|
35
|
+
return (conditions ?? []).map((condition) => ({
|
|
36
|
+
source: "start-precondition",
|
|
37
|
+
condition
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
function tagWorkflowConcurrencyConditions(conditions) {
|
|
41
|
+
return conditions.map((condition) => ({
|
|
42
|
+
source: "workflow-concurrency",
|
|
43
|
+
condition
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
function mergeAdditionalStartOperations(additional, idempotent) {
|
|
47
|
+
if (idempotent === void 0 || idempotent.length === 0)
|
|
48
|
+
return additional;
|
|
49
|
+
return [...additional ?? [], ...idempotent];
|
|
50
|
+
}
|
|
51
|
+
export async function buildAndCommitStartBatch(context, buildIdempotentStartOperations) {
|
|
52
|
+
const { internals, workflowId, state, checkpoint, registration, options } = context, maxAttempts = context.buildWorkflowConcurrencyStartOperations === void 0 ? 1 : WORKFLOW_CONCURRENCY_ADMISSION_MAX_ATTEMPTS;
|
|
53
|
+
let lastWorkflowConcurrencyStateKey;
|
|
54
|
+
for (let attempt = 0;attempt < maxAttempts; attempt += 1) {
|
|
55
|
+
const idempotent = buildIdempotentStartOperations?.(workflowId), workflowConcurrency = await context.buildWorkflowConcurrencyStartOperations?.();
|
|
56
|
+
lastWorkflowConcurrencyStateKey = workflowConcurrency?.stateKey ?? lastWorkflowConcurrencyStateKey;
|
|
57
|
+
const startOperations = buildStartBatchOperations(internals, workflowId, state, checkpoint, registration, options, state.executionDeadline, context.delayedStartTimer, context.persistedWorkflowStartHeaders, mergeAdditionalStartOperations(context.additionalStartOperations, mergeAdditionalStartOperations(idempotent?.operations, workflowConcurrency?.operations)), context.callbacks, context.purgeDeleteOperations), conditions = [
|
|
58
|
+
...tagStartPreconditions(idempotent?.conditions),
|
|
59
|
+
...tagWorkflowConcurrencyConditions(workflowConcurrency?.conditions ?? [])
|
|
60
|
+
];
|
|
61
|
+
if (await persistStartBatch(internals, startOperations, conditions))
|
|
62
|
+
return;
|
|
63
|
+
if (await hasStartPreconditionConflict(internals, conditions))
|
|
64
|
+
throw new StartIdempotencyRaceLostError;
|
|
65
|
+
if (workflowConcurrency === void 0)
|
|
66
|
+
throw new StartIdempotencyRaceLostError;
|
|
67
|
+
}
|
|
68
|
+
throw new AtomicStateConflictError(lastWorkflowConcurrencyStateKey ?? "workflow concurrency admission", WORKFLOW_CONCURRENCY_ADMISSION_MAX_ATTEMPTS);
|
|
69
|
+
}
|
|
@@ -1,5 +1,33 @@
|
|
|
1
|
-
import type { Checkpoint } from '../../types.ts';
|
|
1
|
+
import type { Checkpoint, StartOptions, WorkflowState } from '../../types.ts';
|
|
2
2
|
import type { EngineInternals } from '../internals.ts';
|
|
3
|
-
import { type LifecycleCallbacks } from './shared.ts';
|
|
3
|
+
import { type LifecycleCallbacks, type RegistrationEntry } from './shared.ts';
|
|
4
4
|
export declare function runWorkflowStartInterceptor(_internals: EngineInternals, workflowId: string, workflowType: string, input: unknown, parentHeaders: Map<string, string> | undefined, callbacks: LifecycleCallbacks): Map<string, string> | undefined;
|
|
5
5
|
export declare function startWorkflowExecution(internals: EngineInternals, workflowId: string, workflowType: string, input: unknown, checkpoint: Checkpoint, nestingDepth: number, executionDeadline: number | undefined, executionStateOwnerId: string, _callbacks?: LifecycleCallbacks): void;
|
|
6
|
+
export declare function beginWorkflowExecution(internals: EngineInternals, workflowId: string, workflowType: string, input: unknown, checkpoint: Checkpoint, executionDeadline: number | undefined, executionStateOwnerId: string, _registration: RegistrationEntry, callbacks: LifecycleCallbacks, onStarted?: () => void): void;
|
|
7
|
+
/**
|
|
8
|
+
* `defer: false` is an inline-only liveness gate: it awaits the moment the
|
|
9
|
+
* generator is first driven. A worker-mode start queues to the Worker transport
|
|
10
|
+
* (no inline liveness to await), and a delayed start has not begun executing at
|
|
11
|
+
* all — so both reject rather than silently behaving like `defer: true`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function assertDeferSupported(internals: EngineInternals, options: StartOptions | undefined, isDelayedStart: boolean): void;
|
|
14
|
+
type BeginExecutionParams = {
|
|
15
|
+
type: string;
|
|
16
|
+
input: unknown;
|
|
17
|
+
checkpoint: Checkpoint;
|
|
18
|
+
state: WorkflowState;
|
|
19
|
+
registration: RegistrationEntry;
|
|
20
|
+
options: StartOptions | undefined;
|
|
21
|
+
isDelayed: boolean;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Drive the initial execution for a freshly-started workflow and, when
|
|
25
|
+
* `defer: false`, await the run actually beginning before resolving. A delayed
|
|
26
|
+
* start does not begin executing now, so it neither begins execution here nor
|
|
27
|
+
* awaits liveness. The liveness promise is settled by the inline-launch queue
|
|
28
|
+
* once the generator is driven (or by dispose if the queued start is discarded),
|
|
29
|
+
* so a `defer: false` caller can rely on the run being live without a macrotask
|
|
30
|
+
* round-trip the moment `engine.start()` resolves.
|
|
31
|
+
*/
|
|
32
|
+
export declare function beginExecutionAwaitingLiveness(internals: EngineInternals, params: BeginExecutionParams, workflowId: string, callbacks: LifecycleCallbacks): Promise<void>;
|
|
33
|
+
export {};
|