@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,159 @@
|
|
|
1
|
+
import { KEYS } from "../../../storage/interface.js";
|
|
2
|
+
import { decode } from "../../codec.js";
|
|
3
|
+
import { WorkflowTeardownEvent } from "../../events.js";
|
|
4
|
+
import { isTeardownClaim, parseTeardownTimerId } from "../state-utilities.js";
|
|
5
|
+
import { runFinalizerActivity } from "./finalizer-activity.js";
|
|
6
|
+
import {
|
|
7
|
+
claimTeardownMarker,
|
|
8
|
+
clearTeardownMarker,
|
|
9
|
+
deadLetterTeardown,
|
|
10
|
+
encodeOwedClaim,
|
|
11
|
+
MAX_TEARDOWN_ATTEMPTS,
|
|
12
|
+
rearmTeardownTimer,
|
|
13
|
+
runningClaimIsStale,
|
|
14
|
+
settleOnRunningClaim,
|
|
15
|
+
TEARDOWN_SELF_HEAL_DELAY_MS,
|
|
16
|
+
teardownBackoffMs,
|
|
17
|
+
teardownStaleThresholdMs,
|
|
18
|
+
teardownTimerOperations
|
|
19
|
+
} from "./finalizer-claim.js";
|
|
20
|
+
export { teardownStaleThresholdMs } from "./finalizer-claim.js";
|
|
21
|
+
const TERMINAL_STATUSES_OWED_TEARDOWN = new Set([
|
|
22
|
+
"cancelled",
|
|
23
|
+
"timed-out"
|
|
24
|
+
]);
|
|
25
|
+
function errorMessage(error) {
|
|
26
|
+
return error instanceof Error ? error.message : String(error);
|
|
27
|
+
}
|
|
28
|
+
async function rearmOnLostSettle(internals, workflowId, token) {
|
|
29
|
+
await rearmTeardownTimer(internals, workflowId, token, TEARDOWN_SELF_HEAL_DELAY_MS);
|
|
30
|
+
}
|
|
31
|
+
async function clearOrRearm(internals, workflowId, token, markerBytes) {
|
|
32
|
+
return await clearTeardownMarker(internals, workflowId, markerBytes) ? { kind: "cleared" } : { kind: "rearm", token };
|
|
33
|
+
}
|
|
34
|
+
async function readDriveableClaim(internals, workflowId, token, markerBytes) {
|
|
35
|
+
let decoded;
|
|
36
|
+
try {
|
|
37
|
+
decoded = decode(markerBytes);
|
|
38
|
+
} catch {
|
|
39
|
+
return clearOrRearm(internals, workflowId, token, markerBytes);
|
|
40
|
+
}
|
|
41
|
+
if (!isTeardownClaim(decoded))
|
|
42
|
+
return clearOrRearm(internals, workflowId, token, markerBytes);
|
|
43
|
+
return { kind: "claim", claim: decoded };
|
|
44
|
+
}
|
|
45
|
+
async function resolveTeardownDrive(internals, workflowId, token, callbacks) {
|
|
46
|
+
const markerBytes = await internals.storage.get(KEYS.teardownOwed(workflowId));
|
|
47
|
+
if (markerBytes === null)
|
|
48
|
+
return { kind: "cleared" };
|
|
49
|
+
const resolution = await readDriveableClaim(internals, workflowId, token, markerBytes);
|
|
50
|
+
if (resolution.kind !== "claim")
|
|
51
|
+
return resolution;
|
|
52
|
+
const claim = resolution.claim;
|
|
53
|
+
if (claim.token !== token)
|
|
54
|
+
return { kind: "cleared" };
|
|
55
|
+
const state = await callbacks.loadWorkflowState(workflowId);
|
|
56
|
+
if (state === null || !TERMINAL_STATUSES_OWED_TEARDOWN.has(state.status))
|
|
57
|
+
return clearOrRearm(internals, workflowId, token, markerBytes);
|
|
58
|
+
const registeredFinalizer = internals.registrations.get(state.type)?.finalizer;
|
|
59
|
+
if (registeredFinalizer === void 0)
|
|
60
|
+
return { kind: "rearm", token };
|
|
61
|
+
const finalizer = registeredFinalizer;
|
|
62
|
+
if (!runningClaimIsStale(internals, claim, finalizer))
|
|
63
|
+
return { kind: "rearm", token };
|
|
64
|
+
const finalizerStateBytes = await internals.storage.get(KEYS.finalizerState(workflowId));
|
|
65
|
+
if (finalizerStateBytes === null) {
|
|
66
|
+
await deadLetterMissingState(internals, workflowId, state.type, claim.attempts, markerBytes, callbacks);
|
|
67
|
+
return { kind: "cleared" };
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
kind: "run",
|
|
71
|
+
drive: { state, claim, markerBytes, finalizer, finalizerInput: decode(finalizerStateBytes) }
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
async function deadLetterMissingState(internals, workflowId, workflowType, attempts, expectedBytes, callbacks) {
|
|
75
|
+
const lastError = "finalizer state missing \u2014 recorded resource cannot be torn down";
|
|
76
|
+
if (await deadLetterTeardown(internals, workflowId, workflowType, attempts, expectedBytes, {
|
|
77
|
+
lastError,
|
|
78
|
+
finalizerInput: void 0
|
|
79
|
+
}))
|
|
80
|
+
callbacks.dispatchEvent(new WorkflowTeardownEvent(workflowId, workflowType, "dead-lettered", attempts, lastError));
|
|
81
|
+
}
|
|
82
|
+
export async function runWorkflowFinalizer(internals, workflowId, timerId, callbacks) {
|
|
83
|
+
const token = parseTeardownTimerId(timerId);
|
|
84
|
+
if (token === null)
|
|
85
|
+
return;
|
|
86
|
+
try {
|
|
87
|
+
const resolution = await resolveTeardownDrive(internals, workflowId, token, callbacks);
|
|
88
|
+
if (resolution.kind === "cleared")
|
|
89
|
+
return;
|
|
90
|
+
if (resolution.kind === "rearm") {
|
|
91
|
+
await rearmTeardownTimer(internals, workflowId, resolution.token, TEARDOWN_SELF_HEAL_DELAY_MS);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
await driveResolvedTeardown(internals, workflowId, token, resolution.drive, callbacks);
|
|
95
|
+
} catch (error) {
|
|
96
|
+
await rearmTeardownTimer(internals, workflowId, token, TEARDOWN_SELF_HEAL_DELAY_MS);
|
|
97
|
+
callbacks.handleCleanupError("runWorkflowFinalizer", error, workflowId);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async function driveResolvedTeardown(internals, workflowId, token, drive, callbacks) {
|
|
101
|
+
const { state, claim, markerBytes, finalizer, finalizerInput } = drive, attempt = claim.attempts + 1, runningBytes = await claimTeardownMarker(internals, workflowId, markerBytes, claim.attempts, token);
|
|
102
|
+
if (runningBytes === null) {
|
|
103
|
+
await rearmTeardownTimer(internals, workflowId, token, TEARDOWN_SELF_HEAL_DELAY_MS);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const result = await runFinalizerActivity(finalizer, finalizerInput, attempt, internals.abortController.signal);
|
|
107
|
+
if (result.ok) {
|
|
108
|
+
await settleTeardownSuccess(internals, workflowId, state.type, token, attempt, runningBytes, callbacks);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (result.abortedByShutdown) {
|
|
112
|
+
const fireAt = internals.options.getNow() + TEARDOWN_SELF_HEAL_DELAY_MS;
|
|
113
|
+
if (!await settleOnRunningClaim(internals, workflowId, runningBytes, [
|
|
114
|
+
{
|
|
115
|
+
type: "put",
|
|
116
|
+
key: KEYS.teardownOwed(workflowId),
|
|
117
|
+
value: encodeOwedClaim(claim.attempts, token)
|
|
118
|
+
},
|
|
119
|
+
...teardownTimerOperations(token, workflowId, fireAt)
|
|
120
|
+
]))
|
|
121
|
+
await rearmOnLostSettle(internals, workflowId, token);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
await settleTeardownFailure(internals, workflowId, state, attempt, token, runningBytes, result.error, callbacks);
|
|
125
|
+
}
|
|
126
|
+
async function settleTeardownSuccess(internals, workflowId, workflowType, token, attempt, runningBytes, callbacks) {
|
|
127
|
+
if (!await settleOnRunningClaim(internals, workflowId, runningBytes, [
|
|
128
|
+
{ type: "delete", key: KEYS.teardownOwed(workflowId) },
|
|
129
|
+
{ type: "delete", key: KEYS.finalizerState(workflowId) }
|
|
130
|
+
])) {
|
|
131
|
+
await rearmOnLostSettle(internals, workflowId, token);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
callbacks.dispatchEvent(new WorkflowTeardownEvent(workflowId, workflowType, "completed", attempt));
|
|
135
|
+
}
|
|
136
|
+
async function settleTeardownFailure(internals, workflowId, state, attempt, token, runningBytes, error, callbacks) {
|
|
137
|
+
const message = errorMessage(error);
|
|
138
|
+
if (attempt >= MAX_TEARDOWN_ATTEMPTS) {
|
|
139
|
+
const finalizerStateBytes = await internals.storage.get(KEYS.finalizerState(workflowId));
|
|
140
|
+
if (!await deadLetterTeardown(internals, workflowId, state.type, attempt, runningBytes, {
|
|
141
|
+
lastError: message,
|
|
142
|
+
finalizerInput: finalizerStateBytes === null ? void 0 : decode(finalizerStateBytes)
|
|
143
|
+
})) {
|
|
144
|
+
await rearmOnLostSettle(internals, workflowId, token);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
callbacks.dispatchEvent(new WorkflowTeardownEvent(workflowId, state.type, "dead-lettered", attempt, message));
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const fireAt = internals.options.getNow() + teardownBackoffMs(attempt);
|
|
151
|
+
if (!await settleOnRunningClaim(internals, workflowId, runningBytes, [
|
|
152
|
+
{ type: "put", key: KEYS.teardownOwed(workflowId), value: encodeOwedClaim(attempt, token) },
|
|
153
|
+
...teardownTimerOperations(token, workflowId, fireAt)
|
|
154
|
+
])) {
|
|
155
|
+
await rearmOnLostSettle(internals, workflowId, token);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
callbacks.dispatchEvent(new WorkflowTeardownEvent(workflowId, state.type, "failed", attempt, message));
|
|
159
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { EngineInternals } from '../internals.ts';
|
|
2
|
+
import { type TerminationCallbacks } from './cleanup.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Suspend a running workflow without terminating it: a non-terminal cousin of
|
|
5
|
+
* {@link terminateWorkflow}. The workflow's status transitions `running →
|
|
6
|
+
* suspended`, its durable checkpoint is preserved, and it becomes resumable via
|
|
7
|
+
* `engine.resume(id)` / `handle.resume()`. Suspension is client-driven
|
|
8
|
+
* preemption, so — unlike a fault — a suspended workflow is NOT auto-recovered
|
|
9
|
+
* by `engine.recoverAll()`.
|
|
10
|
+
*
|
|
11
|
+
* Contrast with cancel/timeout, which this deliberately does NOT do:
|
|
12
|
+
* - does NOT abort the workflow's `AbortController` — suspend is a pause, not a
|
|
13
|
+
* cancellation, so user code observing `ctx.signal.aborted` or registered
|
|
14
|
+
* abort listeners must not fire. The live inline run is *parked*
|
|
15
|
+
* (`parkWorkflow`: evict execution state without aborting), the same primitive
|
|
16
|
+
* the engine uses for signal-parking — but with the default eviction, not the
|
|
17
|
+
* `retainContext` form signal-parking uses, so suspend leaves no queryable
|
|
18
|
+
* Context behind,
|
|
19
|
+
* - does NOT run cancel handlers,
|
|
20
|
+
* - does NOT settle the result promise (`handle.result()` stays pending until a
|
|
21
|
+
* later `resume()` drives the run to completion, or a `cancel()` terminates it),
|
|
22
|
+
* - does NOT clean up durable output artifacts or in-memory services (the
|
|
23
|
+
* `services` value is preserved so an in-process `resume()` can reuse it),
|
|
24
|
+
* - does NOT schedule terminal cleanup.
|
|
25
|
+
*
|
|
26
|
+
* The CAS status flip and the in-memory teardown both run inside one serialized
|
|
27
|
+
* per-workflow write section with `allowedStatuses: ['running']`. If the
|
|
28
|
+
* workflow already left `running` (it completed, failed, or a concurrent cancel
|
|
29
|
+
* won the race), the flip is skipped and suspend is a no-op — and because the
|
|
30
|
+
* teardown is gated on the flip succeeding, a workflow that lost the race keeps
|
|
31
|
+
* its execution state intact.
|
|
32
|
+
*
|
|
33
|
+
* The teardown evicts every piece of in-memory execution state that could let a
|
|
34
|
+
* post-suspend operation drive the parked run: the inline context/generator (via
|
|
35
|
+
* `parkWorkflow`), the in-memory checkpoint, the parked-inline marker, and the
|
|
36
|
+
* in-flight operation waiters (signal/update/sleep/review — deleted, NOT
|
|
37
|
+
* resolved, so a signal arriving after suspend buffers durably and is replayed
|
|
38
|
+
* on resume instead of waking a dormant operation loop against the gone
|
|
39
|
+
* generator). The durable checkpoint, durable buffered signals, durable sleep
|
|
40
|
+
* timers, and `workflowServices` are all left intact for resume.
|
|
41
|
+
*
|
|
42
|
+
* A signal that races the in-lock teardown is benign: `continueWorkflow` no-ops
|
|
43
|
+
* for an evicted generator, and `persistCheckpoint` no-ops when the context and
|
|
44
|
+
* in-memory checkpoint are gone — so no step can commit past the suspend point.
|
|
45
|
+
*
|
|
46
|
+
* `'suspended'` is neither `'running'` nor `'pending'`, and both local-ownership
|
|
47
|
+
* predicates (`isInlineWorkflowLocallyOwned`, `hasLocalCheckpointOwnership`) are
|
|
48
|
+
* gated on those two statuses. So once the status flips, the workflow stops
|
|
49
|
+
* registering as locally owned — which is exactly what makes `recoverAll()` skip
|
|
50
|
+
* it AND what lets `engine.resume()` re-drive it from storage instead of taking
|
|
51
|
+
* its local-ownership early return.
|
|
52
|
+
*
|
|
53
|
+
* The execution deadline is absolute wall-clock time: suspension does NOT extend
|
|
54
|
+
* it. The pending `deadline:` timer is deleted durably IN THE SAME COMMIT BATCH
|
|
55
|
+
* as the status flip, and re-armed at the same absolute fire time on resume (or
|
|
56
|
+
* fires immediately if already past). It is a durable delete rather than a
|
|
57
|
+
* `scheduler.cancel()` call because the scheduler is durable-scan-based and
|
|
58
|
+
* resume's re-arm is likewise durable-only (`buildTimerBatchOperations`); folding
|
|
59
|
+
* the delete into the commit makes it atomic with the flip and ordered before any
|
|
60
|
+
* concurrent resume, so an immediate resume cannot have its freshly re-armed
|
|
61
|
+
* deadline deleted by a late fire-and-forget cancel.
|
|
62
|
+
*
|
|
63
|
+
* Worker execution mode is not supported: a worker run cannot be parked without
|
|
64
|
+
* sending it a cancellation. To keep the contract state-dependent (suspend on a
|
|
65
|
+
* non-running workflow is always a no-op), the mode check runs only AFTER the
|
|
66
|
+
* status load confirms the workflow is `running`; a `running` worker workflow
|
|
67
|
+
* throws {@link WorkflowSuspendNotSupportedError}, while a completed or unknown
|
|
68
|
+
* one is a no-op regardless of execution mode.
|
|
69
|
+
*/
|
|
70
|
+
export declare function suspendWorkflow(internals: EngineInternals, workflowId: string, callbacks: TerminationCallbacks): Promise<void>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { KEYS } from "../../../storage/interface.js";
|
|
2
|
+
import { encode } from "../../codec.js";
|
|
3
|
+
import { WorkflowSuspendedEvent } from "../../events.js";
|
|
4
|
+
import { WorkflowSuspendNotSupportedError } from "../errors.js";
|
|
5
|
+
import { dropQueuedInlineWorkflowStart } from "../inline-launch-queue.js";
|
|
6
|
+
import { buildWorkflowVisibilityIndexTransition } from "../workflow-indexes.js";
|
|
7
|
+
import { evictSuspendedWorkflowWaiters } from "./cleanup.js";
|
|
8
|
+
export async function suspendWorkflow(internals, workflowId, callbacks) {
|
|
9
|
+
if (!await callbacks.runSerializedWorkflowStateWrite(workflowId, async () => {
|
|
10
|
+
const state = await callbacks.loadWorkflowState(workflowId);
|
|
11
|
+
if (!state || state.status !== "running")
|
|
12
|
+
return !1;
|
|
13
|
+
if (internals.inlineStrategy === null)
|
|
14
|
+
throw new WorkflowSuspendNotSupportedError("suspend is only supported in inline execution mode; a worker run cannot be paused without cancelling it.");
|
|
15
|
+
internals.inlineStrategy.parkWorkflow(workflowId);
|
|
16
|
+
dropQueuedInlineWorkflowStart(internals, workflowId);
|
|
17
|
+
internals.checkpoints.delete(workflowId);
|
|
18
|
+
internals.parkedInlineWorkflows.delete(workflowId);
|
|
19
|
+
evictSuspendedWorkflowWaiters(internals, workflowId, callbacks);
|
|
20
|
+
const updatedAt = internals.options.getNow(), updatedState = { ...state, status: "suspended", updatedAt };
|
|
21
|
+
await callbacks.commitWorkflowStateOperations(state, [
|
|
22
|
+
{ type: "put", key: KEYS.workflow(workflowId), value: encode(updatedState) },
|
|
23
|
+
...buildWorkflowVisibilityIndexTransition(workflowId, state, updatedState).batchOps,
|
|
24
|
+
...buildDeadlineTimerDeleteOperations(workflowId, state.executionDeadline)
|
|
25
|
+
]);
|
|
26
|
+
return !0;
|
|
27
|
+
}))
|
|
28
|
+
return;
|
|
29
|
+
const event = new WorkflowSuspendedEvent(workflowId);
|
|
30
|
+
callbacks.dispatchEvent(event);
|
|
31
|
+
callbacks.forwardEventToHandle(workflowId, event);
|
|
32
|
+
}
|
|
33
|
+
function buildDeadlineTimerDeleteOperations(workflowId, executionDeadline) {
|
|
34
|
+
if (executionDeadline === void 0)
|
|
35
|
+
return [];
|
|
36
|
+
const timerId = `deadline:${workflowId}`;
|
|
37
|
+
return [
|
|
38
|
+
{ type: "delete", key: KEYS.deadline(executionDeadline, timerId) },
|
|
39
|
+
{ type: "delete", key: `timer-idx:${timerId}` }
|
|
40
|
+
];
|
|
41
|
+
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Thin barrel over the split termination modules. Keeps existing import paths
|
|
3
3
|
* (`./termination.ts`) working while the implementation lives in
|
|
4
|
-
* `./termination/cleanup.ts
|
|
4
|
+
* `./termination/cleanup.ts`, `./termination/complete.ts`, and
|
|
5
|
+
* `./termination/suspend.ts`.
|
|
5
6
|
*/
|
|
6
|
-
export { TERMINAL_WORKFLOW_STATUSES, cleanupTerminalWorkflowDurableState, cleanupTerminalWorkflowImmediately, cleanupTerminalWorkflowMemory, cleanupTerminalWorkflowSynchronously, cleanupWaiters, cleanupWorkflowStorage, finalizeScheduledWorkflowTerminal, handleCleanupError, runDeferredTerminalCleanup, type TerminationCallbacks, } from './termination/cleanup.ts';
|
|
7
|
+
export { TERMINAL_WORKFLOW_STATUSES, cleanupTerminalWorkflowDurableState, cleanupTerminalWorkflowImmediately, cleanupTerminalWorkflowMemory, cleanupTerminalWorkflowSynchronously, cleanupWaiters, cleanupWorkflowStorage, evictSuspendedWorkflowWaiters, finalizeScheduledWorkflowTerminal, handleCleanupError, runDeferredTerminalCleanup, type TerminationCallbacks, } from './termination/cleanup.ts';
|
|
7
8
|
export { buildPendingTimelineOperation, buildTerminalCleanupTimerOperations, cancelWorkflow, completeWorkflow, ensureTerminalCleanupTracked, failWorkflow, finalizePendingTimelineEntry, terminateWorkflow, timeoutWorkflow, } from './termination/complete.ts';
|
|
9
|
+
export { runWorkflowFinalizer, teardownStaleThresholdMs, type FinalizerDriveCallbacks, type TeardownDeadLetterRecord, } from './termination/finalizer.ts';
|
|
10
|
+
export { suspendWorkflow } from './termination/suspend.ts';
|
|
@@ -6,6 +6,7 @@ export {
|
|
|
6
6
|
cleanupTerminalWorkflowSynchronously,
|
|
7
7
|
cleanupWaiters,
|
|
8
8
|
cleanupWorkflowStorage,
|
|
9
|
+
evictSuspendedWorkflowWaiters,
|
|
9
10
|
finalizeScheduledWorkflowTerminal,
|
|
10
11
|
handleCleanupError,
|
|
11
12
|
runDeferredTerminalCleanup
|
|
@@ -21,3 +22,8 @@ export {
|
|
|
21
22
|
terminateWorkflow,
|
|
22
23
|
timeoutWorkflow
|
|
23
24
|
} from "./termination/complete.js";
|
|
25
|
+
export {
|
|
26
|
+
runWorkflowFinalizer,
|
|
27
|
+
teardownStaleThresholdMs
|
|
28
|
+
} from "./termination/finalizer.js";
|
|
29
|
+
export { suspendWorkflow } from "./termination/suspend.js";
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { UpdateCompletedEvent, UpdateReceivedEvent } from "../events.js";
|
|
2
2
|
import { isGeneratorResult } from "../step-context.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
UpdateValidationError
|
|
6
|
-
} from "../updates.js";
|
|
3
|
+
import { UpdateValidationError } from "../updates.js";
|
|
4
|
+
import { notifyConditionWaiters } from "./condition-waiters.js";
|
|
7
5
|
import { trackWaiterKey, untrackWaiterKey } from "./signals.js";
|
|
6
|
+
import { waitForUpdateResponse } from "./waiting-update-response.js";
|
|
8
7
|
export async function update(internals, workflowId, name, payload, options, callbacks) {
|
|
9
8
|
const timeout = options?.timeout ?? 30000;
|
|
10
9
|
await runUpdateValidator(internals, workflowId, name, payload);
|
|
@@ -27,11 +26,13 @@ async function tryInlineUpdateHandler(internals, workflowId, name, payload, call
|
|
|
27
26
|
const result = await invokeUpdateHandler(internals, name, handler, payload);
|
|
28
27
|
callbacks.dispatchEvent(new UpdateCompletedEvent(updateId, workflowId, name, result));
|
|
29
28
|
callbacks.broadcast({ type: "update:completed", workflowId, updateId });
|
|
29
|
+
notifyConditionWaiters(internals, workflowId);
|
|
30
30
|
return { handled: !0, value: result };
|
|
31
31
|
} catch (error) {
|
|
32
32
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
33
33
|
callbacks.dispatchEvent(new UpdateCompletedEvent(updateId, workflowId, name, void 0, errorMessage));
|
|
34
34
|
callbacks.broadcast({ type: "update:completed", workflowId, updateId });
|
|
35
|
+
notifyConditionWaiters(internals, workflowId);
|
|
35
36
|
throw error;
|
|
36
37
|
}
|
|
37
38
|
}
|
|
@@ -51,27 +52,6 @@ async function tryWaitingUpdateHandler(internals, workflowId, name, payload, tim
|
|
|
51
52
|
callbacks.broadcast({ type: "update:completed", workflowId, updateId });
|
|
52
53
|
return { handled: !0, value: result };
|
|
53
54
|
}
|
|
54
|
-
async function waitForUpdateResponse(updateId, payload, timeout, updateWaiter) {
|
|
55
|
-
const { promise: respondPromise, resolve: resolveRespond } = Promise.withResolvers();
|
|
56
|
-
let responded = !1;
|
|
57
|
-
updateWaiter({ payload, respond: (value) => {
|
|
58
|
-
if (responded)
|
|
59
|
-
return;
|
|
60
|
-
responded = !0;
|
|
61
|
-
resolveRespond(value);
|
|
62
|
-
} });
|
|
63
|
-
let timeoutId;
|
|
64
|
-
try {
|
|
65
|
-
return await Promise.race([
|
|
66
|
-
respondPromise,
|
|
67
|
-
new Promise((_resolve, reject) => {
|
|
68
|
-
timeoutId = setTimeout(() => reject(new UpdateTimeoutError(updateId, timeout)), timeout);
|
|
69
|
-
})
|
|
70
|
-
]);
|
|
71
|
-
} finally {
|
|
72
|
-
clearTimeout(timeoutId);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
55
|
async function runCoordinatedUpdate(internals, workflowId, name, payload, timeout, callbacks) {
|
|
76
56
|
const updateId = await internals.updateCoordinator.createRequest(workflowId, name, payload);
|
|
77
57
|
callbacks.schedulePendingInlineUpdateDrain(workflowId);
|
|
@@ -8,6 +8,7 @@ export declare function isValidScheduleIdentifier(value: unknown): value is stri
|
|
|
8
8
|
export declare function coerceScheduleId(scheduleId: string, fieldName: string): string;
|
|
9
9
|
export declare function normalizeScheduleOptions(options: ScheduleOptions | undefined): Required<Pick<ScheduleOptions, 'overlap' | 'backfill'>> & {
|
|
10
10
|
id?: string;
|
|
11
|
+
jitterMs?: number;
|
|
11
12
|
};
|
|
12
13
|
/**
|
|
13
14
|
* A recurrence specification normalized into the discriminated cadence the
|
|
@@ -32,7 +33,7 @@ export declare function decodeScheduleIdentityFields(decoded: Record<string, unk
|
|
|
32
33
|
cronExpression?: string;
|
|
33
34
|
intervalMs?: number;
|
|
34
35
|
}) | null;
|
|
35
|
-
type ScheduleRuntimeFields = Pick<ScheduleState, 'backfill' | 'createdAt' | 'updatedAt' | 'lastFireAt' | 'nextFireAt' | 'currentWorkflowId' | 'queuedRuns'>;
|
|
36
|
+
type ScheduleRuntimeFields = Pick<ScheduleState, 'backfill' | 'jitterMs' | 'createdAt' | 'updatedAt' | 'lastFireAt' | 'lastMissedFireAt' | 'nextFireAt' | 'currentWorkflowId' | 'missedFireCount' | 'queuedRuns'>;
|
|
36
37
|
export declare function decodeScheduleRuntimeFields(decoded: Record<string, unknown>, scheduleId: string): ScheduleRuntimeFields | null;
|
|
37
38
|
export declare function decodeScheduleState(bytes: Uint8Array): ScheduleState | null;
|
|
38
39
|
export {};
|
|
@@ -36,7 +36,7 @@ export function normalizeScheduleOptions(options) {
|
|
|
36
36
|
return { overlap: "skip", backfill: !1 };
|
|
37
37
|
if (typeof options !== "object" || options === null)
|
|
38
38
|
throw Error("options must be an object when provided");
|
|
39
|
-
const { id, overlap, backfill } = options, normalizedOptions = {
|
|
39
|
+
const { id, overlap, backfill, jitter } = options, normalizedOptions = {
|
|
40
40
|
overlap: "skip",
|
|
41
41
|
backfill: !1
|
|
42
42
|
};
|
|
@@ -52,8 +52,25 @@ export function normalizeScheduleOptions(options) {
|
|
|
52
52
|
throw Error("options.backfill must be a boolean when provided");
|
|
53
53
|
normalizedOptions.backfill = backfill;
|
|
54
54
|
}
|
|
55
|
+
if (jitter !== void 0)
|
|
56
|
+
normalizedOptions.jitterMs = normalizeScheduleJitter(jitter, "options.jitter");
|
|
55
57
|
return normalizedOptions;
|
|
56
58
|
}
|
|
59
|
+
function normalizeScheduleJitter(value, fieldName) {
|
|
60
|
+
if (typeof value !== "string" && typeof value !== "number")
|
|
61
|
+
throw Error(`${fieldName} must be a duration string or a number of milliseconds`);
|
|
62
|
+
let milliseconds;
|
|
63
|
+
try {
|
|
64
|
+
milliseconds = parseDuration(value);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
67
|
+
throw Error(`Invalid ${fieldName}: ${message}`, { cause: error });
|
|
68
|
+
}
|
|
69
|
+
const jitterMs = Math.ceil(milliseconds);
|
|
70
|
+
if (!Number.isSafeInteger(jitterMs) || jitterMs <= 0)
|
|
71
|
+
throw Error(`${fieldName} must resolve to a positive number of milliseconds`);
|
|
72
|
+
return jitterMs;
|
|
73
|
+
}
|
|
57
74
|
function normalizeIntervalEvery(every) {
|
|
58
75
|
if (typeof every !== "string" && typeof every !== "number")
|
|
59
76
|
throw Error('Schedule interval "every" must be a duration string or a number of milliseconds');
|
|
@@ -171,6 +188,16 @@ function decodeScheduleBackfill(decoded, scheduleId) {
|
|
|
171
188
|
}
|
|
172
189
|
return backfill;
|
|
173
190
|
}
|
|
191
|
+
function decodeScheduleJitterMs(decoded, scheduleId) {
|
|
192
|
+
const jitterMs = decoded.jitterMs;
|
|
193
|
+
if (jitterMs === void 0)
|
|
194
|
+
return;
|
|
195
|
+
if (typeof jitterMs !== "number" || !Number.isSafeInteger(jitterMs) || jitterMs <= 0) {
|
|
196
|
+
rejectInvalidScheduleRecord(scheduleId, "with invalid jitterMs");
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
return jitterMs;
|
|
200
|
+
}
|
|
174
201
|
function decodeScheduleTimestamps(decoded, scheduleId) {
|
|
175
202
|
const { createdAt, updatedAt } = decoded;
|
|
176
203
|
if (!isValidScheduleTimestamp(createdAt) || !isValidScheduleTimestamp(updatedAt))
|
|
@@ -178,10 +205,14 @@ function decodeScheduleTimestamps(decoded, scheduleId) {
|
|
|
178
205
|
const lastFireAt = decoded.lastFireAt;
|
|
179
206
|
if (lastFireAt !== void 0 && !isValidScheduleTimestamp(lastFireAt))
|
|
180
207
|
return rejectInvalidScheduleRecord(scheduleId, "with invalid lastFireAt");
|
|
208
|
+
const lastMissedFireAt = decoded.lastMissedFireAt;
|
|
209
|
+
if (lastMissedFireAt !== void 0 && !isValidScheduleTimestamp(lastMissedFireAt))
|
|
210
|
+
return rejectInvalidScheduleRecord(scheduleId, "with invalid lastMissedFireAt");
|
|
181
211
|
return {
|
|
182
212
|
createdAt,
|
|
183
213
|
updatedAt,
|
|
184
|
-
...lastFireAt !== void 0 && { lastFireAt }
|
|
214
|
+
...lastFireAt !== void 0 && { lastFireAt },
|
|
215
|
+
...lastMissedFireAt !== void 0 && { lastMissedFireAt }
|
|
185
216
|
};
|
|
186
217
|
}
|
|
187
218
|
function decodeScheduleNextFireAt(decoded, scheduleId) {
|
|
@@ -214,10 +245,23 @@ function decodeScheduleQueuedRuns(decoded, scheduleId) {
|
|
|
214
245
|
}
|
|
215
246
|
return queuedRuns;
|
|
216
247
|
}
|
|
248
|
+
function decodeScheduleMissedFireCount(decoded, scheduleId) {
|
|
249
|
+
const missedFireCount = decoded.missedFireCount;
|
|
250
|
+
if (missedFireCount === void 0)
|
|
251
|
+
return 0;
|
|
252
|
+
if (typeof missedFireCount !== "number" || !Number.isSafeInteger(missedFireCount) || missedFireCount < 0) {
|
|
253
|
+
rejectInvalidScheduleRecord(scheduleId, "with invalid missedFireCount");
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
return missedFireCount;
|
|
257
|
+
}
|
|
217
258
|
export function decodeScheduleRuntimeFields(decoded, scheduleId) {
|
|
218
259
|
const backfill = decodeScheduleBackfill(decoded, scheduleId);
|
|
219
260
|
if (backfill === null)
|
|
220
261
|
return null;
|
|
262
|
+
const jitterMs = decodeScheduleJitterMs(decoded, scheduleId);
|
|
263
|
+
if (jitterMs === null)
|
|
264
|
+
return null;
|
|
221
265
|
const timestamps = decodeScheduleTimestamps(decoded, scheduleId);
|
|
222
266
|
if (timestamps === null)
|
|
223
267
|
return null;
|
|
@@ -230,11 +274,16 @@ export function decodeScheduleRuntimeFields(decoded, scheduleId) {
|
|
|
230
274
|
const queuedRuns = decodeScheduleQueuedRuns(decoded, scheduleId);
|
|
231
275
|
if (queuedRuns === null)
|
|
232
276
|
return null;
|
|
277
|
+
const missedFireCount = decodeScheduleMissedFireCount(decoded, scheduleId);
|
|
278
|
+
if (missedFireCount === null)
|
|
279
|
+
return null;
|
|
233
280
|
return {
|
|
234
281
|
backfill,
|
|
282
|
+
...jitterMs !== void 0 && { jitterMs },
|
|
235
283
|
...timestamps,
|
|
236
284
|
nextFireAt: nextFireAt.value,
|
|
237
285
|
...currentWorkflow.value !== void 0 && { currentWorkflowId: currentWorkflow.value },
|
|
286
|
+
missedFireCount,
|
|
238
287
|
queuedRuns
|
|
239
288
|
};
|
|
240
289
|
}
|
|
@@ -2,6 +2,7 @@ import { decode } from "../codec.js";
|
|
|
2
2
|
import { isRecord } from "../debug-output.js";
|
|
3
3
|
import { normalizeFailureCategory } from "../failure-categories.js";
|
|
4
4
|
import { coerceStartWorkflowId, parseStartWorkflowDuration } from "../start-workflow-validation.js";
|
|
5
|
+
import { DEFAULT_WORKFLOW_VERSION } from "../versioning.js";
|
|
5
6
|
import { isWorkflowTagArray } from "../workflow-tags.js";
|
|
6
7
|
const WORKFLOW_TIMELINE_STATUSES = new Set([
|
|
7
8
|
"running",
|
|
@@ -10,6 +11,29 @@ const WORKFLOW_TIMELINE_STATUSES = new Set([
|
|
|
10
11
|
"cancelled",
|
|
11
12
|
"timed-out"
|
|
12
13
|
]);
|
|
14
|
+
function defineCompleteWorkflowStateFieldNames(fieldNames) {
|
|
15
|
+
return fieldNames;
|
|
16
|
+
}
|
|
17
|
+
const WORKFLOW_STATE_FIELD_NAMES = new Set(defineCompleteWorkflowStateFieldNames([
|
|
18
|
+
"id",
|
|
19
|
+
"type",
|
|
20
|
+
"status",
|
|
21
|
+
"tags",
|
|
22
|
+
"input",
|
|
23
|
+
"result",
|
|
24
|
+
"error",
|
|
25
|
+
"errorStack",
|
|
26
|
+
"failureCategory",
|
|
27
|
+
"terminationReason",
|
|
28
|
+
"versionTuple",
|
|
29
|
+
"executionStateOwnerId",
|
|
30
|
+
"createdAt",
|
|
31
|
+
"startedAt",
|
|
32
|
+
"updatedAt",
|
|
33
|
+
"terminalCleanupToken",
|
|
34
|
+
"executionDeadline",
|
|
35
|
+
"forkedFrom"
|
|
36
|
+
]));
|
|
13
37
|
export function isSanitizedSearchAttributeValue(value) {
|
|
14
38
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean")
|
|
15
39
|
return !0;
|
|
@@ -55,9 +79,10 @@ export function isValidDecodedTags(value) {
|
|
|
55
79
|
return value === void 0 || isWorkflowTagArray(value);
|
|
56
80
|
}
|
|
57
81
|
export function decodeWorkflowState(bytes) {
|
|
58
|
-
const
|
|
59
|
-
if (
|
|
60
|
-
|
|
82
|
+
const decoded = decode(bytes), decodedRecord = isRecord(decoded) ? decoded : void 0;
|
|
83
|
+
if (decodedRecord !== void 0)
|
|
84
|
+
liftFlatVersionTuple(decodedRecord);
|
|
85
|
+
const state = decoded;
|
|
61
86
|
if (!isValidDecodedTags(state.tags)) {
|
|
62
87
|
console.warn(`[weft] Decoded workflow state for "${String(state.id)}" has invalid tags; dropping the malformed tag list from the decoded state.`);
|
|
63
88
|
delete state.tags;
|
|
@@ -76,8 +101,34 @@ export function decodeWorkflowState(bytes) {
|
|
|
76
101
|
console.warn(`[weft] Decoded workflow state for "${String(state.id)}" has an invalid executionStateOwnerId field; falling back to the workflow id as the execution owner. This usually indicates corruption or tampering of the storage record.`);
|
|
77
102
|
delete state.executionStateOwnerId;
|
|
78
103
|
}
|
|
104
|
+
return decodedRecord === void 0 ? state : stripUnknownWorkflowStateFields(state, decodedRecord);
|
|
105
|
+
}
|
|
106
|
+
function stripUnknownWorkflowStateFields(state, stateFields) {
|
|
107
|
+
for (const fieldName of Object.keys(stateFields))
|
|
108
|
+
if (!WORKFLOW_STATE_FIELD_NAMES.has(fieldName))
|
|
109
|
+
delete stateFields[fieldName];
|
|
79
110
|
return state;
|
|
80
111
|
}
|
|
112
|
+
function liftFlatVersionTuple(record) {
|
|
113
|
+
const flatVersion = record.version, hasFlatVersion = typeof flatVersion === "string";
|
|
114
|
+
if (isWorkflowVersionTuple(record.versionTuple)) {
|
|
115
|
+
delete record.version;
|
|
116
|
+
delete record.agentVersion;
|
|
117
|
+
delete record.toolVersions;
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const { agentVersion: flatAgentVersion, toolVersions: flatToolVersions } = record, versionTuple = {
|
|
121
|
+
workflowVersion: hasFlatVersion ? flatVersion : DEFAULT_WORKFLOW_VERSION,
|
|
122
|
+
...typeof flatAgentVersion === "string" && { agentVersion: flatAgentVersion },
|
|
123
|
+
...Array.isArray(flatToolVersions) && flatToolVersions.every((entry) => typeof entry === "string") && {
|
|
124
|
+
toolVersions: flatToolVersions
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
record.versionTuple = versionTuple;
|
|
128
|
+
delete record.version;
|
|
129
|
+
delete record.agentVersion;
|
|
130
|
+
delete record.toolVersions;
|
|
131
|
+
}
|
|
81
132
|
export function normalizeRetentionDuration(value, fieldName) {
|
|
82
133
|
if (value === void 0)
|
|
83
134
|
return;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Park until a waiting `ctx.waitForUpdate` handler responds (via the resolver it
|
|
3
|
+
* registered in `updateWaiters`) or the update times out. Resolves with the
|
|
4
|
+
* handler's response value; rejects with {@link UpdateTimeoutError} when the
|
|
5
|
+
* timeout elapses first. The `respond` callback is single-shot — a late second
|
|
6
|
+
* response is ignored.
|
|
7
|
+
*/
|
|
8
|
+
export declare function waitForUpdateResponse(updateId: string, payload: unknown, timeout: number, updateWaiter: (request: unknown) => void): Promise<unknown>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { UpdateTimeoutError } from "../updates.js";
|
|
2
|
+
export async function waitForUpdateResponse(updateId, payload, timeout, updateWaiter) {
|
|
3
|
+
const { promise: respondPromise, resolve: resolveRespond } = Promise.withResolvers();
|
|
4
|
+
let responded = !1;
|
|
5
|
+
updateWaiter({ payload, respond: (value) => {
|
|
6
|
+
if (responded)
|
|
7
|
+
return;
|
|
8
|
+
responded = !0;
|
|
9
|
+
resolveRespond(value);
|
|
10
|
+
} });
|
|
11
|
+
let timeoutId;
|
|
12
|
+
try {
|
|
13
|
+
return await Promise.race([
|
|
14
|
+
respondPromise,
|
|
15
|
+
new Promise((_resolve, reject) => {
|
|
16
|
+
timeoutId = setTimeout(() => reject(new UpdateTimeoutError(updateId, timeout)), timeout);
|
|
17
|
+
})
|
|
18
|
+
]);
|
|
19
|
+
} finally {
|
|
20
|
+
clearTimeout(timeoutId);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BatchOperation, ConditionalBatchCondition } from '../../storage/interface.ts';
|
|
2
|
+
import type { WorkflowConcurrencyOptions } from '../types.ts';
|
|
3
|
+
import type { EngineInternals } from './internals.ts';
|
|
4
|
+
export type WorkflowConcurrencyStartOperations = {
|
|
5
|
+
stateKey: string;
|
|
6
|
+
operations: BatchOperation[];
|
|
7
|
+
conditions: ConditionalBatchCondition[];
|
|
8
|
+
};
|
|
9
|
+
export declare function buildWorkflowConcurrencyStartOperations(internals: EngineInternals, workflowType: string, workflowId: string, input: unknown, concurrency: WorkflowConcurrencyOptions): Promise<WorkflowConcurrencyStartOperations>;
|
|
10
|
+
export declare function releaseWorkflowConcurrencySlot(internals: EngineInternals, workflowId: string): Promise<void>;
|