@lostgradient/weft 0.3.0 → 0.5.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 +79 -24
- package/dist/cli/conformance.js +7 -1
- package/dist/cli/generated/operation-client.generated.d.ts +28 -13
- package/dist/cli/generated/operation-client.generated.js +1 -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 +79 -78
- package/dist/client/handle-delegation.d.ts +3 -2
- package/dist/client/handle-delegation.js +3 -1
- package/dist/client/http-client-requests.d.ts +2 -1
- package/dist/client/http-client-requests.js +7 -0
- package/dist/client/http-client.d.ts +9 -6
- package/dist/client/http-client.js +10 -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 +61 -5
- package/dist/client/local-handles.d.ts +22 -0
- package/dist/client/local-handles.js +23 -0
- package/dist/client/local.d.ts +6 -3
- package/dist/client/local.js +12 -26
- package/dist/client/start-body.d.ts +4 -3
- 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 +100 -6
- 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 +9 -5
- package/dist/core/context/index.js +17 -12
- package/dist/core/context/internals.d.ts +20 -0
- package/dist/core/context/internals.js +3 -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 +6 -1
- package/dist/core/context/run-operation.js +41 -87
- 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 +46 -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 -0
- package/dist/core/engine/construction.js +21 -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 +13 -0
- package/dist/core/engine/engine-create-types.d.ts +14 -4
- package/dist/core/engine/engine-internal-types.d.ts +26 -3
- package/dist/core/engine/errors.d.ts +47 -0
- package/dist/core/engine/errors.js +20 -0
- 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/handles.d.ts +8 -0
- package/dist/core/engine/index.d.ts +34 -16
- package/dist/core/engine/index.js +136 -9
- package/dist/core/engine/inline-parking.js +3 -2
- package/dist/core/engine/internals.d.ts +107 -3
- 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/persist.js +10 -32
- 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 +16 -9
- 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 +9 -0
- package/dist/core/engine/lifecycle/start-commit.js +50 -8
- 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.d.ts +3 -2
- package/dist/core/engine/lifecycle/start-or-signal.js +11 -81
- 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 +4 -4
- package/dist/core/engine/lifecycle/start.js +17 -9
- package/dist/core/engine/lifecycle/transition.js +17 -5
- package/dist/core/engine/lifecycle.d.ts +1 -1
- package/dist/core/engine/list-candidate-resolution.js +2 -2
- package/dist/core/engine/listing.js +9 -5
- package/dist/core/engine/operations-activity.d.ts +6 -13
- package/dist/core/engine/operations-activity.js +26 -53
- package/dist/core/engine/operations-coordination.d.ts +10 -0
- package/dist/core/engine/operations-coordination.js +44 -9
- 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/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-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 +7 -4
- package/dist/core/engine/schedules.js +37 -16
- 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/signals.d.ts +18 -2
- package/dist/core/engine/signals.js +42 -21
- 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 +25 -6
- package/dist/core/engine/termination/cleanup.d.ts +3 -1
- package/dist/core/engine/termination/cleanup.js +25 -1
- package/dist/core/engine/termination/complete.js +44 -6
- 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 +3 -1
- package/dist/core/engine/termination.d.ts +1 -0
- package/dist/core/engine/termination.js +4 -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 +32 -5
- 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 +4 -5
- 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 +18 -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 +88 -23
- package/dist/core/events/workflow-events.js +26 -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/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 +34 -0
- package/dist/core/start-workflow-validation.js +19 -0
- 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 +80 -61
- package/dist/core/types/bulk.d.ts +50 -9
- package/dist/core/types/checkpoint.d.ts +44 -8
- package/dist/core/types/list-options.d.ts +146 -0
- package/dist/core/types/list-options.js +0 -0
- package/dist/core/types/options.d.ts +121 -165
- package/dist/core/types/schedules.d.ts +39 -3
- package/dist/core/types/services-resolution.d.ts +2 -2
- 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 +42 -11
- 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 +84 -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.d.ts +4 -0
- package/dist/core/types.js +4 -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 +16 -0
- 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/format.js +1 -6
- package/dist/diagnostics/types.d.ts +4 -5
- package/dist/diagnostics/validate.d.ts +0 -1
- package/dist/diagnostics/version-check.d.ts +1 -1
- package/dist/diagnostics/version-check.js +4 -9
- package/dist/index.d.ts +12 -10
- package/dist/index.js +29 -3
- package/dist/json-schema.js +3 -3
- package/dist/mcp/cli.js +19 -19
- package/dist/mcp/dispatcher.js +1 -1
- package/dist/mcp/http.js +16 -6
- 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 +59 -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 +23 -23
- package/dist/server/index.d.ts +32 -2
- package/dist/server/index.js +32 -32
- 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/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 +6 -1
- package/dist/server/operations/start-or-signal-workflow.js +14 -24
- package/dist/server/operations/start-workflow-options.d.ts +6 -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 +8 -23
- 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/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 +3 -1
- package/dist/server/rest-bindings.js +12 -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-polling.js +61 -20
- 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 +38 -30
- package/dist/server/serve-internals.d.ts +3 -1
- package/dist/server/serve-internals.js +18 -2
- package/dist/server/task-state.d.ts +30 -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 +30 -30
- package/dist/storage/auto.js +1 -1
- package/dist/storage/bun-sql.js +24 -0
- 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 +76 -4
- package/dist/storage/indexeddb.js +1 -1
- package/dist/storage/interface.d.ts +163 -0
- package/dist/storage/interface.js +1 -1
- package/dist/storage/key-prefixes.d.ts +1 -1
- package/dist/storage/key-prefixes.js +10 -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 +30 -3
- package/dist/storage/neon-value-mapping.js +12 -0
- package/dist/storage/neon.d.ts +16 -0
- package/dist/storage/neon.js +9 -4
- package/dist/storage/node-sqlite.js +23 -0
- package/dist/storage/postgres-key-value-queries.d.ts +69 -44
- package/dist/storage/postgres-key-value-queries.js +62 -24
- package/dist/storage/resolve.js +1 -1
- package/dist/storage/scoped-storage.js +1 -1
- package/dist/storage/testing.d.ts +168 -0
- package/dist/storage/testing.js +2 -0
- 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 +20 -20
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker/protocol.js +1 -1
- 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 +5 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { BatchOperation, ConditionalBatchCondition } from '../../../storage/interface.ts';
|
|
2
2
|
import type { Checkpoint, StartOptions, TimerEntry, WorkflowState } from '../../types.ts';
|
|
3
3
|
import type { EngineInternals } from '../internals.ts';
|
|
4
|
+
import type { WorkflowConcurrencyStartOperations } from '../workflow-concurrency.ts';
|
|
4
5
|
import { type LifecycleCallbacks, type RegistrationEntry } from './shared.ts';
|
|
5
6
|
/**
|
|
6
7
|
* Builds the id-dependent operations and compare-and-swap preconditions for an
|
|
@@ -34,7 +35,15 @@ export type StartBatchContext = {
|
|
|
34
35
|
delayedStartTimer: TimerEntry | undefined;
|
|
35
36
|
persistedWorkflowStartHeaders: Map<string, string> | undefined;
|
|
36
37
|
additionalStartOperations: BatchOperation[] | undefined;
|
|
38
|
+
buildWorkflowConcurrencyStartOperations: (() => Promise<WorkflowConcurrencyStartOperations | undefined>) | undefined;
|
|
37
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;
|
|
38
47
|
};
|
|
39
48
|
/**
|
|
40
49
|
* Assemble the start batch — folding in the id-dependent idempotency mapping and
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import { requireStorageCapability,
|
|
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";
|
|
2
7
|
import { buildStartBatchOperations } from "./start-batch.js";
|
|
3
8
|
|
|
4
9
|
export class StartIdempotencyRaceLostError extends Error {
|
|
@@ -7,13 +12,36 @@ export class StartIdempotencyRaceLostError extends Error {
|
|
|
7
12
|
this.name = "StartIdempotencyRaceLostError";
|
|
8
13
|
}
|
|
9
14
|
}
|
|
15
|
+
const WORKFLOW_CONCURRENCY_ADMISSION_MAX_ATTEMPTS = 5;
|
|
10
16
|
async function persistStartBatch(internals, startOperations, conditions) {
|
|
11
|
-
if (conditions ===
|
|
12
|
-
await internals
|
|
17
|
+
if (conditions.length === 0) {
|
|
18
|
+
await commitFencedEngineWrite(internals, startOperations, [], () => Error("Workflow start lost its CAS race."));
|
|
13
19
|
return !0;
|
|
14
20
|
}
|
|
15
|
-
requireStorageCapability(internals.storage, "conditionalBatch", "start
|
|
16
|
-
return
|
|
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
|
+
}));
|
|
17
45
|
}
|
|
18
46
|
function mergeAdditionalStartOperations(additional, idempotent) {
|
|
19
47
|
if (idempotent === void 0 || idempotent.length === 0)
|
|
@@ -21,7 +49,21 @@ function mergeAdditionalStartOperations(additional, idempotent) {
|
|
|
21
49
|
return [...additional ?? [], ...idempotent];
|
|
22
50
|
}
|
|
23
51
|
export async function buildAndCommitStartBatch(context, buildIdempotentStartOperations) {
|
|
24
|
-
const { internals, workflowId, state, checkpoint, registration, options } = context,
|
|
25
|
-
|
|
26
|
-
|
|
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);
|
|
27
69
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create-and-deliver machinery for {@link startOrSignal}: building the atomic
|
|
3
|
+
* start-with-signal batch, running it, and recovering from every way the create
|
|
4
|
+
* can lose its CAS (keyed-mapping loss, caller-`id` reservation collision, or a
|
|
5
|
+
* pre-buffered signal). Split from `start-or-signal.ts` to keep that module
|
|
6
|
+
* focused on the public `startOrSignal` / `startWithIdempotency` entry points.
|
|
7
|
+
*
|
|
8
|
+
* @module core/engine/lifecycle/start-or-signal-create
|
|
9
|
+
*/
|
|
10
|
+
import type { StartOptions, StartOrSignalSignal } from '../../types.ts';
|
|
11
|
+
import { type StartOrSignalOutcome, type WorkflowHandle } from '../handles.ts';
|
|
12
|
+
import type { EngineInternals } from '../internals.ts';
|
|
13
|
+
import { type BuildIdempotentStartOperations } from './start-commit.ts';
|
|
14
|
+
import { type StartOrSignalCallbacks } from './start-or-signal-resolution.ts';
|
|
15
|
+
/**
|
|
16
|
+
* Build the `(workflowId) => { operations, conditions }` callback that folds the
|
|
17
|
+
* idempotency mapping and (optionally) the create-batch signal into the start
|
|
18
|
+
* batch, gated on the mapping key being absent. Every caller supplies at least
|
|
19
|
+
* one of `idempotencyKey` / `signal` (the plain start path skips this builder
|
|
20
|
+
* entirely), so the returned callback always contributes at least one operation.
|
|
21
|
+
*/
|
|
22
|
+
export declare function idempotentStartOperationsFor(internals: EngineInternals, idempotencyKey: string | undefined, signal: {
|
|
23
|
+
name: string;
|
|
24
|
+
payload: unknown;
|
|
25
|
+
signalId: string;
|
|
26
|
+
} | undefined): BuildIdempotentStartOperations;
|
|
27
|
+
/**
|
|
28
|
+
* A resolved start-or-signal handle paired with which atomic path produced it
|
|
29
|
+
* (#466), computed during the call at zero extra cost.
|
|
30
|
+
*/
|
|
31
|
+
export type StartOrSignalResult<TResult = unknown> = {
|
|
32
|
+
handle: WorkflowHandle<TResult>;
|
|
33
|
+
outcome: StartOrSignalOutcome;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Create the workflow and deliver the signal atomically, recovering from a lost
|
|
37
|
+
* create batch:
|
|
38
|
+
*
|
|
39
|
+
* - **Lost to a keyed winner** — idempotency-mapping CAS loss
|
|
40
|
+
* ({@link StartIdempotencyRaceLostError} on the keyed path): the mapping commits
|
|
41
|
+
* atomically with the record, so the winner is guaranteed committed — resolve it
|
|
42
|
+
* and signal it (or conflict if terminal).
|
|
43
|
+
* - **Lost to a caller-`id` winner** — collision on the winner's in-memory
|
|
44
|
+
* `pendingStarts` reservation ({@link WorkflowAlreadyExistsError}): the
|
|
45
|
+
* reservation is held BEFORE the durable commit, so it may clear without a run
|
|
46
|
+
* ever existing (the winner aborted: storage failure, oversized payload, a
|
|
47
|
+
* throwing start interceptor). Wait for the reservation to clear, then signal a
|
|
48
|
+
* committed winner or — if it aborted — retry the create. Bounded by
|
|
49
|
+
* {@link CALLER_ID_CREATE_MAX_ATTEMPTS}.
|
|
50
|
+
* - **Signal already buffered** — `StartIdempotencyRaceLostError` on the
|
|
51
|
+
* caller-`id` path: the only CAS condition there is the signal's `sigres:`
|
|
52
|
+
* accepted-response marker, so the loss means a signal with this signalId was
|
|
53
|
+
* pre-buffered and (the batch being atomic) the `wf:` record was NOT written.
|
|
54
|
+
* Plain-create the workflow; the buffered signal is consumed on first drive
|
|
55
|
+
* (scan-then-park), and the caller's payload loses to the pre-buffered one by
|
|
56
|
+
* the same first-wins dedup.
|
|
57
|
+
*/
|
|
58
|
+
export declare function createWithSignalOrFallback(internals: EngineInternals, type: string, input: unknown, signalSpec: StartOrSignalSignal, signalId: string, options: StartOptions | undefined, callbacks: StartOrSignalCallbacks): Promise<StartOrSignalResult>;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { KEYS } from "../../../storage/interface.js";
|
|
2
|
+
import { encode } from "../../codec.js";
|
|
3
|
+
import { WorkflowAlreadyExistsError } from "../errors.js";
|
|
4
|
+
import { buildCreateBatchSignalOperations } from "../signals.js";
|
|
5
|
+
import {
|
|
6
|
+
StartIdempotencyRaceLostError
|
|
7
|
+
} from "./start-commit.js";
|
|
8
|
+
import {
|
|
9
|
+
requireWinnerId,
|
|
10
|
+
resolveCallerIdWinnerOrRetry,
|
|
11
|
+
resolveWinnerWithSignal
|
|
12
|
+
} from "./start-or-signal-resolution.js";
|
|
13
|
+
import { startWorkflow } from "./start.js";
|
|
14
|
+
export function idempotentStartOperationsFor(internals, idempotencyKey, signal) {
|
|
15
|
+
return (workflowId) => {
|
|
16
|
+
const operations = [], conditions = [];
|
|
17
|
+
if (idempotencyKey !== void 0) {
|
|
18
|
+
const key = KEYS.startIdempotency(idempotencyKey);
|
|
19
|
+
operations.push({
|
|
20
|
+
type: "put",
|
|
21
|
+
key,
|
|
22
|
+
value: encode({ workflowId })
|
|
23
|
+
});
|
|
24
|
+
conditions.push({ key, expectedValue: null });
|
|
25
|
+
}
|
|
26
|
+
if (signal !== void 0) {
|
|
27
|
+
const built = buildCreateBatchSignalOperations(internals, workflowId, signal.name, signal.payload, signal.signalId);
|
|
28
|
+
operations.push(...built.operations);
|
|
29
|
+
conditions.push(built.condition);
|
|
30
|
+
}
|
|
31
|
+
return { operations, conditions };
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const CALLER_ID_CREATE_MAX_ATTEMPTS = 5;
|
|
35
|
+
export async function createWithSignalOrFallback(internals, type, input, signalSpec, signalId, options, callbacks) {
|
|
36
|
+
const idempotencyKey = options?.idempotencyKey;
|
|
37
|
+
for (let attempt = 0;attempt < CALLER_ID_CREATE_MAX_ATTEMPTS; attempt += 1) {
|
|
38
|
+
const outcome = await resolveCreateRaceOutcome(internals, options, async () => {
|
|
39
|
+
return startWorkflow(internals, type, input, options, void 0, callbacks, idempotentStartOperationsFor(internals, idempotencyKey, {
|
|
40
|
+
name: signalSpec.name,
|
|
41
|
+
payload: signalSpec.payload,
|
|
42
|
+
signalId
|
|
43
|
+
}));
|
|
44
|
+
});
|
|
45
|
+
if (outcome.kind === "created")
|
|
46
|
+
return { handle: outcome.handle, outcome: "started" };
|
|
47
|
+
if (outcome.kind === "lost-keyed")
|
|
48
|
+
return {
|
|
49
|
+
handle: await resolveWinnerWithSignal(internals, outcome.id, signalSpec, signalId, callbacks, outcome.idempotencyKey),
|
|
50
|
+
outcome: "signalled"
|
|
51
|
+
};
|
|
52
|
+
if (outcome.kind === "lost-caller-id") {
|
|
53
|
+
const resolved = await resolveCallerIdWinnerOrRetry(internals, outcome.id, signalSpec, signalId, callbacks);
|
|
54
|
+
if (resolved !== void 0)
|
|
55
|
+
return { handle: resolved, outcome: "signalled" };
|
|
56
|
+
} else {
|
|
57
|
+
const resolved = await plainCreateBufferedSignalOrResolve(internals, type, input, signalSpec, signalId, options, callbacks);
|
|
58
|
+
if (resolved !== void 0)
|
|
59
|
+
return resolved;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
throw Error(`startOrSignal could not create workflow "${options?.id ?? "<generated>"}" after ${CALLER_ID_CREATE_MAX_ATTEMPTS} attempts: each concurrent same-id winner aborted before its durable commit.`);
|
|
63
|
+
}
|
|
64
|
+
async function plainCreateBufferedSignalOrResolve(internals, type, input, signalSpec, signalId, options, callbacks) {
|
|
65
|
+
try {
|
|
66
|
+
return {
|
|
67
|
+
handle: await startWorkflow(internals, type, input, options, void 0, callbacks),
|
|
68
|
+
outcome: "started"
|
|
69
|
+
};
|
|
70
|
+
} catch (error) {
|
|
71
|
+
if (!(error instanceof WorkflowAlreadyExistsError))
|
|
72
|
+
throw error;
|
|
73
|
+
const resolved = await resolveCallerIdWinnerOrRetry(internals, error.workflowId, signalSpec, signalId, callbacks);
|
|
74
|
+
return resolved === void 0 ? void 0 : { handle: resolved, outcome: "signalled" };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function resolveCreateRaceOutcome(internals, options, runCreate) {
|
|
78
|
+
try {
|
|
79
|
+
return { kind: "created", handle: await runCreate() };
|
|
80
|
+
} catch (error) {
|
|
81
|
+
if (error instanceof WorkflowAlreadyExistsError)
|
|
82
|
+
return { kind: "lost-caller-id", id: error.workflowId };
|
|
83
|
+
if (error instanceof StartIdempotencyRaceLostError) {
|
|
84
|
+
const idempotencyKey = options?.idempotencyKey;
|
|
85
|
+
if (idempotencyKey !== void 0)
|
|
86
|
+
return {
|
|
87
|
+
kind: "lost-keyed",
|
|
88
|
+
id: await requireWinnerId(internals, idempotencyKey),
|
|
89
|
+
idempotencyKey
|
|
90
|
+
};
|
|
91
|
+
return { kind: "signal-already-buffered" };
|
|
92
|
+
}
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -2,8 +2,9 @@ import type { StartOptions, StartOrSignalSignal } from '../../types.ts';
|
|
|
2
2
|
import { type WorkflowHandle } from '../handles.ts';
|
|
3
3
|
import type { EngineInternals } from '../internals.ts';
|
|
4
4
|
import { type LifecycleCallbacks } from './shared.ts';
|
|
5
|
+
import { type StartOrSignalResult } from './start-or-signal-create.ts';
|
|
5
6
|
import { type StartOrSignalCallbacks } from './start-or-signal-resolution.ts';
|
|
6
|
-
export type { StartOrSignalCallbacks };
|
|
7
|
+
export type { StartOrSignalCallbacks, StartOrSignalResult };
|
|
7
8
|
/**
|
|
8
9
|
* Enforce at-most-once start for a given `idempotencyKey`. On the first call,
|
|
9
10
|
* the workflow record and a `startIdempotency(key) → { workflowId }` mapping
|
|
@@ -42,4 +43,4 @@ export declare function startWithIdempotency(internals: EngineInternals, type: s
|
|
|
42
43
|
* convergence primitive. Use `idempotencyKey` (id-free convergence) or
|
|
43
44
|
* `id` + `signalId` when concurrent callers must converge.
|
|
44
45
|
*/
|
|
45
|
-
export declare function startOrSignal(internals: EngineInternals, type: string, input: unknown, signalSpec: StartOrSignalSignal, options: StartOptions | undefined, callbacks: StartOrSignalCallbacks): Promise<
|
|
46
|
+
export declare function startOrSignal(internals: EngineInternals, type: string, input: unknown, signalSpec: StartOrSignalSignal, options: StartOptions | undefined, callbacks: StartOrSignalCallbacks): Promise<StartOrSignalResult>;
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { KEYS, requireStorageCapability } from "../../../storage/interface.js";
|
|
2
|
-
import { encode } from "../../codec.js";
|
|
3
2
|
import {
|
|
3
|
+
assertIdAndIdempotencyKeyExclusive,
|
|
4
|
+
assertOnTerminalConflictUnsupported,
|
|
4
5
|
assertValidIdempotencyKey,
|
|
6
|
+
assertValidOnTerminalConflict,
|
|
5
7
|
StartWorkflowValidationError
|
|
6
8
|
} from "../../start-workflow-validation.js";
|
|
7
|
-
import { IdempotencyKeyPurgedError
|
|
8
|
-
import {
|
|
9
|
+
import { IdempotencyKeyPurgedError } from "../errors.js";
|
|
10
|
+
import { StartIdempotencyRaceLostError } from "./start-commit.js";
|
|
9
11
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
createWithSignalOrFallback,
|
|
13
|
+
idempotentStartOperationsFor
|
|
14
|
+
} from "./start-or-signal-create.js";
|
|
12
15
|
import {
|
|
13
16
|
requireWinnerId,
|
|
14
|
-
resolveCallerIdWinnerOrRetry,
|
|
15
17
|
resolveExistingRunOrThrowPurged,
|
|
16
18
|
resolveIdempotencyKeyWorkflowId,
|
|
17
|
-
resolveWinnerWithSignal,
|
|
18
19
|
signalOrConflictExistingWorkflow
|
|
19
20
|
} from "./start-or-signal-resolution.js";
|
|
20
21
|
import { startWorkflow } from "./start.js";
|
|
@@ -25,26 +26,6 @@ function resolveSignalId(signalSpec, idempotencyKey) {
|
|
|
25
26
|
return signalSpec.signalId;
|
|
26
27
|
throw new StartWorkflowValidationError("startOrSignal requires either signal.signalId or options.idempotencyKey to identify the signal to deliver. (Concurrent callers converge on one workflow and one signal only with a shared idempotencyKey, or a shared id plus signalId; a bare signalId starts a fresh run per caller.)");
|
|
27
28
|
}
|
|
28
|
-
function idempotentStartOperationsFor(internals, idempotencyKey, signal) {
|
|
29
|
-
return (workflowId) => {
|
|
30
|
-
const operations = [], conditions = [];
|
|
31
|
-
if (idempotencyKey !== void 0) {
|
|
32
|
-
const key = KEYS.startIdempotency(idempotencyKey);
|
|
33
|
-
operations.push({
|
|
34
|
-
type: "put",
|
|
35
|
-
key,
|
|
36
|
-
value: encode({ workflowId })
|
|
37
|
-
});
|
|
38
|
-
conditions.push({ key, expectedValue: null });
|
|
39
|
-
}
|
|
40
|
-
if (signal !== void 0) {
|
|
41
|
-
const built = buildCreateBatchSignalOperations(internals, workflowId, signal.name, signal.payload, signal.signalId);
|
|
42
|
-
operations.push(...built.operations);
|
|
43
|
-
conditions.push(built.condition);
|
|
44
|
-
}
|
|
45
|
-
return { operations, conditions };
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
29
|
export async function startWithIdempotency(internals, type, input, options, callbacks) {
|
|
49
30
|
requireStorageCapability(internals.storage, "conditionalBatch", "start idempotency");
|
|
50
31
|
const { idempotencyKey } = options;
|
|
@@ -52,6 +33,7 @@ export async function startWithIdempotency(internals, type, input, options, call
|
|
|
52
33
|
throw new StartWorkflowValidationError("startWithIdempotency requires options.idempotencyKey");
|
|
53
34
|
assertValidIdempotencyKey(idempotencyKey, "options.idempotencyKey");
|
|
54
35
|
assertIdAndIdempotencyKeyExclusive(options);
|
|
36
|
+
assertValidOnTerminalConflict(options);
|
|
55
37
|
const existingId = await resolveIdempotencyKeyWorkflowId(internals, idempotencyKey);
|
|
56
38
|
if (existingId !== void 0)
|
|
57
39
|
return callbacks.getHandle(await resolveExistingRunOrThrowPurged(internals, existingId));
|
|
@@ -63,10 +45,6 @@ export async function startWithIdempotency(internals, type, input, options, call
|
|
|
63
45
|
}
|
|
64
46
|
return callbacks.getHandle(await resolveExistingRunOrThrowPurged(internals, await requireWinnerId(internals, idempotencyKey)));
|
|
65
47
|
}
|
|
66
|
-
function assertIdAndIdempotencyKeyExclusive(options) {
|
|
67
|
-
if (options.id !== void 0 && options.idempotencyKey !== void 0)
|
|
68
|
-
throw new StartWorkflowValidationError("options.id and options.idempotencyKey are mutually exclusive: idempotency assigns its own workflow id and dedups through the idempotency key. Provide one or the other.");
|
|
69
|
-
}
|
|
70
48
|
function validateStartOrSignalConvergence(signalSpec, options) {
|
|
71
49
|
const idempotencyKey = options?.idempotencyKey;
|
|
72
50
|
if (idempotencyKey === void 0)
|
|
@@ -78,64 +56,16 @@ function validateStartOrSignalConvergence(signalSpec, options) {
|
|
|
78
56
|
}
|
|
79
57
|
export async function startOrSignal(internals, type, input, signalSpec, options, callbacks) {
|
|
80
58
|
requireStorageCapability(internals.storage, "conditionalBatch", "startOrSignal");
|
|
59
|
+
assertOnTerminalConflictUnsupported(options, "startOrSignal");
|
|
81
60
|
const idempotencyKey = options?.idempotencyKey;
|
|
82
61
|
validateStartOrSignalConvergence(signalSpec, options);
|
|
83
62
|
const signalId = resolveSignalId(signalSpec, idempotencyKey), mappedId = idempotencyKey !== void 0 ? await resolveIdempotencyKeyWorkflowId(internals, idempotencyKey) : void 0, existingId = mappedId ?? options?.id;
|
|
84
63
|
if (existingId !== void 0) {
|
|
85
64
|
const resolved = await signalOrConflictExistingWorkflow(internals, existingId, signalSpec, signalId, callbacks);
|
|
86
65
|
if (resolved !== void 0)
|
|
87
|
-
return resolved;
|
|
66
|
+
return { handle: resolved, outcome: "signalled" };
|
|
88
67
|
if (mappedId !== void 0)
|
|
89
68
|
throw new IdempotencyKeyPurgedError(mappedId);
|
|
90
69
|
}
|
|
91
70
|
return createWithSignalOrFallback(internals, type, input, signalSpec, signalId, options, callbacks);
|
|
92
71
|
}
|
|
93
|
-
const CALLER_ID_CREATE_MAX_ATTEMPTS = 5;
|
|
94
|
-
async function createWithSignalOrFallback(internals, type, input, signalSpec, signalId, options, callbacks) {
|
|
95
|
-
const idempotencyKey = options?.idempotencyKey;
|
|
96
|
-
for (let attempt = 0;attempt < CALLER_ID_CREATE_MAX_ATTEMPTS; attempt += 1) {
|
|
97
|
-
const outcome = await resolveCreateRaceOutcome(internals, options, async () => {
|
|
98
|
-
return startWorkflow(internals, type, input, options, void 0, callbacks, idempotentStartOperationsFor(internals, idempotencyKey, {
|
|
99
|
-
name: signalSpec.name,
|
|
100
|
-
payload: signalSpec.payload,
|
|
101
|
-
signalId
|
|
102
|
-
}));
|
|
103
|
-
});
|
|
104
|
-
if (outcome.kind === "created")
|
|
105
|
-
return outcome.handle;
|
|
106
|
-
if (outcome.kind === "lost-keyed")
|
|
107
|
-
return resolveWinnerWithSignal(internals, outcome.id, signalSpec, signalId, callbacks, outcome.idempotencyKey);
|
|
108
|
-
const resolved = outcome.kind === "lost-caller-id" ? await resolveCallerIdWinnerOrRetry(internals, outcome.id, signalSpec, signalId, callbacks) : await plainCreateBufferedSignalOrResolve(internals, type, input, signalSpec, signalId, options, callbacks);
|
|
109
|
-
if (resolved !== void 0)
|
|
110
|
-
return resolved;
|
|
111
|
-
}
|
|
112
|
-
throw Error(`startOrSignal could not create workflow "${options?.id ?? "<generated>"}" after ${CALLER_ID_CREATE_MAX_ATTEMPTS} attempts: each concurrent same-id winner aborted before its durable commit.`);
|
|
113
|
-
}
|
|
114
|
-
async function plainCreateBufferedSignalOrResolve(internals, type, input, signalSpec, signalId, options, callbacks) {
|
|
115
|
-
try {
|
|
116
|
-
return await startWorkflow(internals, type, input, options, void 0, callbacks);
|
|
117
|
-
} catch (error) {
|
|
118
|
-
if (!(error instanceof WorkflowAlreadyExistsError))
|
|
119
|
-
throw error;
|
|
120
|
-
return resolveCallerIdWinnerOrRetry(internals, error.workflowId, signalSpec, signalId, callbacks);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
async function resolveCreateRaceOutcome(internals, options, runCreate) {
|
|
124
|
-
try {
|
|
125
|
-
return { kind: "created", handle: await runCreate() };
|
|
126
|
-
} catch (error) {
|
|
127
|
-
if (error instanceof WorkflowAlreadyExistsError)
|
|
128
|
-
return { kind: "lost-caller-id", id: error.workflowId };
|
|
129
|
-
if (error instanceof StartIdempotencyRaceLostError) {
|
|
130
|
-
const idempotencyKey = options?.idempotencyKey;
|
|
131
|
-
if (idempotencyKey !== void 0)
|
|
132
|
-
return {
|
|
133
|
-
kind: "lost-keyed",
|
|
134
|
-
id: await requireWinnerId(internals, idempotencyKey),
|
|
135
|
-
idempotencyKey
|
|
136
|
-
};
|
|
137
|
-
return { kind: "signal-already-buffered" };
|
|
138
|
-
}
|
|
139
|
-
throw error;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { BatchOperation } from '../../../storage/interface.ts';
|
|
2
|
+
import type { StartWorkflowOptions, WorkflowState } from '../../types.ts';
|
|
3
|
+
import type { EngineInternals } from '../internals.ts';
|
|
4
|
+
import { type LifecycleCallbacks } from './shared.ts';
|
|
5
|
+
/**
|
|
6
|
+
* Decide what a caller-supplied workflow id that already has a persisted record
|
|
7
|
+
* means, WITHOUT performing any destructive action. Only invoked when the caller
|
|
8
|
+
* supplied the id — a generated v4 UUID is effectively unique, so skipping this
|
|
9
|
+
* read keeps generated-id starts on the single-write hot path.
|
|
10
|
+
*
|
|
11
|
+
* - default (`'error'`): throw {@link WorkflowAlreadyExistsError} (the existing
|
|
12
|
+
* contract — a duplicate id is always a conflict).
|
|
13
|
+
* - `'start-new'` on a **terminal** run: return that run's {@link WorkflowState}
|
|
14
|
+
* so the caller can purge it *after* all deterministic new-run validation has
|
|
15
|
+
* succeeded. This keeps the destructive purge as the last possible step before
|
|
16
|
+
* the atomic create commit, so a restart that is rejected by any later
|
|
17
|
+
* validation (payload size, execution-timeout overflow, a start interceptor
|
|
18
|
+
* throwing) leaves the prior terminal run intact.
|
|
19
|
+
* - `'start-new'` on a **non-terminal** run: throw
|
|
20
|
+
* {@link WorkflowAlreadyExistsError} — `'start-new'` never displaces a live run.
|
|
21
|
+
* - `'start-new'` on a **terminal** run that still owes a finalizer (#446): throw
|
|
22
|
+
* {@link WorkflowTeardownPendingError} (transient). The displacing purge would
|
|
23
|
+
* delete the finalizer payload before the resource is torn down, leaking it, so
|
|
24
|
+
* the restart is refused until teardown settles (which clears the marker).
|
|
25
|
+
*
|
|
26
|
+
* Returns `null` when there is no existing record (the create proceeds normally).
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveTerminalConflictForRestart(internals: EngineInternals, workflowId: string, options: StartWorkflowOptions | undefined): Promise<WorkflowState | null>;
|
|
29
|
+
/**
|
|
30
|
+
* Prepare a prior terminal run for displacement by a `'start-new'` restart WITHOUT
|
|
31
|
+
* committing the destructive delete. Returns the storage delete operations (for the
|
|
32
|
+
* caller to fold into the atomic create batch so purge-and-recreate land as one
|
|
33
|
+
* unit) and clears the OLD run's in-memory caches up front — before the new run
|
|
34
|
+
* writes its own caches under the reused id, so the clear cannot wipe fresh
|
|
35
|
+
* entries. `clearPurgedWorkflowInMemoryState` runs `cleanupWaiters` to settle the
|
|
36
|
+
* old run's pending signal/update/sleep waiters; it only needs
|
|
37
|
+
* `swallowPromiseRejection`, which `LifecycleCallbacks` already exposes.
|
|
38
|
+
*/
|
|
39
|
+
export declare function prepareTerminalRunPurge(internals: EngineInternals, state: WorkflowState, callbacks: LifecycleCallbacks): Promise<BatchOperation[]>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { KEYS, storageHas } from "../../../storage/interface.js";
|
|
2
|
+
import {
|
|
3
|
+
clearPurgedWorkflowInMemoryState,
|
|
4
|
+
collectWorkflowPurgeDeleteOperations
|
|
5
|
+
} from "../bulk-operations-purge.js";
|
|
6
|
+
import { WorkflowAlreadyExistsError, WorkflowTeardownPendingError } from "../errors.js";
|
|
7
|
+
import { cleanupWaiters } from "../termination/cleanup.js";
|
|
8
|
+
import { decodeWorkflowState, isTerminalWorkflowStatus } from "../validation.js";
|
|
9
|
+
export async function resolveTerminalConflictForRestart(internals, workflowId, options) {
|
|
10
|
+
const existingBytes = await internals.storage.get(KEYS.workflow(workflowId));
|
|
11
|
+
if (existingBytes === null)
|
|
12
|
+
return null;
|
|
13
|
+
if (options?.onTerminalConflict !== "start-new")
|
|
14
|
+
throw new WorkflowAlreadyExistsError(workflowId);
|
|
15
|
+
const existingState = decodeWorkflowState(existingBytes);
|
|
16
|
+
if (!isTerminalWorkflowStatus(existingState.status))
|
|
17
|
+
throw new WorkflowAlreadyExistsError(workflowId);
|
|
18
|
+
if (await storageHas(internals.storage, KEYS.teardownOwed(workflowId)))
|
|
19
|
+
throw new WorkflowTeardownPendingError(workflowId);
|
|
20
|
+
return existingState;
|
|
21
|
+
}
|
|
22
|
+
export async function prepareTerminalRunPurge(internals, state, callbacks) {
|
|
23
|
+
const cleanupWaitersForStart = (id) => cleanupWaiters(internals, id, {
|
|
24
|
+
swallowPromiseRejection: callbacks.swallowPromiseRejection
|
|
25
|
+
}), deleteOperations = await collectWorkflowPurgeDeleteOperations(internals, state);
|
|
26
|
+
clearPurgedWorkflowInMemoryState(internals, state.id, cleanupWaitersForStart);
|
|
27
|
+
return deleteOperations;
|
|
28
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { BatchOperation } from '../../../storage/interface.ts';
|
|
2
|
-
import type { Checkpoint, Duration, StartOptions, TimerEntry, WorkflowState } from '../../types.ts';
|
|
2
|
+
import type { Checkpoint, Duration, StartOptions, StartWorkflowOptions, TimerEntry, WorkflowState } from '../../types.ts';
|
|
3
3
|
import { type WorkflowVersionTuple } from '../../workflow-version-tuple.ts';
|
|
4
4
|
import { type WorkflowHandle } from '../handles.ts';
|
|
5
5
|
import type { EngineInternals } from '../internals.ts';
|
|
6
6
|
import { type LifecycleCallbacks } from './shared.ts';
|
|
7
7
|
import { type BuildIdempotentStartOperations } from './start-commit.ts';
|
|
8
|
-
export declare function start(internals: EngineInternals, type: string, input: unknown, options:
|
|
9
|
-
export declare function startWorkflow(internals: EngineInternals, type: string, input: unknown, options:
|
|
8
|
+
export declare function start(internals: EngineInternals, type: string, input: unknown, options: StartWorkflowOptions | undefined, callbacks: LifecycleCallbacks): Promise<WorkflowHandle>;
|
|
9
|
+
export declare function startWorkflow(internals: EngineInternals, type: string, input: unknown, options: StartWorkflowOptions | undefined, additionalStartOperations: BatchOperation[] | undefined, callbacks: LifecycleCallbacks, buildIdempotentStartOperations?: BuildIdempotentStartOperations): Promise<WorkflowHandle>;
|
|
10
10
|
export declare function resolveScheduledStartAt(internals: EngineInternals, options: StartOptions | undefined, submissionTime: number, callbacks: LifecycleCallbacks): number | undefined;
|
|
11
11
|
export declare function parseStartOptionDuration(_internals: EngineInternals, duration: Duration, fieldName: 'options.executionTimeout' | 'options.startAfter', _callbacks: LifecycleCallbacks): number;
|
|
12
|
-
export declare function createInitialWorkflowState(internals: EngineInternals, workflowId: string, type: string, input: unknown, versionTuple: WorkflowVersionTuple, options: StartOptions | undefined, tags: string[] | undefined, executionStateOwnerId: string, delayedStartTimer: TimerEntry | undefined, callbacks: LifecycleCallbacks): WorkflowState;
|
|
12
|
+
export declare function createInitialWorkflowState(internals: EngineInternals, workflowId: string, type: string, input: unknown, versionTuple: WorkflowVersionTuple, options: StartOptions | undefined, tags: string[] | undefined, executionStateOwnerId: string | undefined, delayedStartTimer: TimerEntry | undefined, callbacks: LifecycleCallbacks): WorkflowState;
|
|
13
13
|
export declare function createInitialCheckpoint(internals: EngineInternals, workflowId: string, workflowVersion: string, options: StartOptions | undefined, _callbacks: LifecycleCallbacks): Checkpoint;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { KEYS } from "../../../storage/interface.js";
|
|
2
1
|
import { createCheckpoint } from "../../checkpoint.js";
|
|
3
2
|
import { assertPayloadWithinLimit } from "../../payload-size.js";
|
|
4
3
|
import { normalizeStorageTimestamp } from "../../scheduler.js";
|
|
5
4
|
import {
|
|
6
5
|
StartWorkflowValidationError,
|
|
7
6
|
assertExclusiveStartWorkflowOptions,
|
|
7
|
+
assertValidOnTerminalConflict,
|
|
8
8
|
coerceStartWorkflowId,
|
|
9
9
|
coerceStartWorkflowTimestamp,
|
|
10
10
|
parseStartWorkflowDuration
|
|
@@ -13,6 +13,7 @@ import { forgetCommittedCheckpointBytes } from "../checkpoint-commit-snapshots.j
|
|
|
13
13
|
import { WorkflowAlreadyExistsError, WorkflowNotRegisteredError } from "../errors.js";
|
|
14
14
|
import { createDelayedStartTimerEntry } from "../operations-time.js";
|
|
15
15
|
import { selectPersistedWorkflowStartHeaders } from "../state-utilities.js";
|
|
16
|
+
import { buildWorkflowConcurrencyStartOperations } from "../workflow-concurrency.js";
|
|
16
17
|
import { createWorkflowVersionTuple } from "./persist.js";
|
|
17
18
|
import {
|
|
18
19
|
createWorkflowHandle,
|
|
@@ -25,13 +26,17 @@ import {
|
|
|
25
26
|
beginExecutionAwaitingLiveness,
|
|
26
27
|
runWorkflowStartInterceptor
|
|
27
28
|
} from "./start-exec.js";
|
|
29
|
+
import {
|
|
30
|
+
prepareTerminalRunPurge,
|
|
31
|
+
resolveTerminalConflictForRestart
|
|
32
|
+
} from "./start-terminal-conflict-purge.js";
|
|
28
33
|
export async function start(internals, type, input, options, callbacks) {
|
|
29
34
|
return startWorkflow(internals, type, input, options, void 0, callbacks);
|
|
30
35
|
}
|
|
31
36
|
function prepareStartWorkflow(internals, options, callbacks) {
|
|
32
37
|
const callerProvidedId = options?.id !== void 0, workflowId = options?.id !== void 0 ? coerceStartWorkflowId(options.id, "options.id") : crypto.randomUUID(), parentHeaders = internals.pendingParentHeaders;
|
|
33
38
|
internals.pendingParentHeaders = void 0;
|
|
34
|
-
const
|
|
39
|
+
const pendingExecutionStateOwnerId = internals.pendingExecutionStateOwnerId, executionStateOwnerId = pendingExecutionStateOwnerId === null ? void 0 : pendingExecutionStateOwnerId ?? workflowId;
|
|
35
40
|
internals.pendingExecutionStateOwnerId = void 0;
|
|
36
41
|
const submissionTime = internals.options.getNow(), scheduledStartAt = resolveScheduledStartAt(internals, options, submissionTime, callbacks), normalizedTags = normalizeStartWorkflowTags(internals, options?.tags, void 0, callbacks), delayedStartTimer = scheduledStartAt !== void 0 && scheduledStartAt > submissionTime ? createDelayedStartTimerEntry(internals, workflowId, scheduledStartAt, options, {
|
|
37
42
|
parseStartOptionDuration: (value, fieldName) => parseStartOptionDuration(internals, value, fieldName, callbacks)
|
|
@@ -62,7 +67,9 @@ export async function startWorkflow(internals, type, input, options, additionalS
|
|
|
62
67
|
const registration = internals.registrations.get(type);
|
|
63
68
|
if (!registration)
|
|
64
69
|
throw new WorkflowNotRegisteredError(type);
|
|
70
|
+
const workflowConcurrency = registration.concurrency;
|
|
65
71
|
assertServicesSupportedForMode(internals, options);
|
|
72
|
+
assertValidOnTerminalConflict(options);
|
|
66
73
|
const preparation = prepareStartWorkflow(internals, options, callbacks), { workflowId, callerProvidedId, parentHeaders, executionStateOwnerId, delayedStartTimer } = preparation;
|
|
67
74
|
assertDeferSupported(internals, options, Boolean(delayedStartTimer));
|
|
68
75
|
if (internals.pendingStarts.has(workflowId))
|
|
@@ -70,12 +77,9 @@ export async function startWorkflow(internals, type, input, options, additionalS
|
|
|
70
77
|
internals.pendingStarts.add(workflowId);
|
|
71
78
|
let startSucceeded = !1;
|
|
72
79
|
try {
|
|
73
|
-
|
|
74
|
-
if (await internals.storage.get(KEYS.workflow(workflowId)) !== null)
|
|
75
|
-
throw new WorkflowAlreadyExistsError(workflowId);
|
|
76
|
-
}
|
|
80
|
+
const terminalRunToPurge = callerProvidedId ? await resolveTerminalConflictForRestart(internals, workflowId, options) : null;
|
|
77
81
|
assertPayloadWithinLimit(input, internals.options.payloadSizePolicy.maxBytes, "workflow input");
|
|
78
|
-
const versionTuple = createWorkflowVersionTuple(internals, registration, callbacks), state = createInitialWorkflowState(internals, workflowId, type, input, versionTuple, options, preparation.normalizedTags, executionStateOwnerId, delayedStartTimer, callbacks), checkpoint = createInitialCheckpoint(internals, workflowId, versionTuple.workflowVersion, options, callbacks), workflowStartHeaders = runWorkflowStartInterceptor(internals, workflowId, type, input, parentHeaders, callbacks), persistedWorkflowStartHeaders = selectPersistedWorkflowStartHeaders(workflowStartHeaders);
|
|
82
|
+
const versionTuple = createWorkflowVersionTuple(internals, registration, callbacks), state = createInitialWorkflowState(internals, workflowId, type, input, versionTuple, options, preparation.normalizedTags, executionStateOwnerId, delayedStartTimer, callbacks), checkpoint = createInitialCheckpoint(internals, workflowId, versionTuple.workflowVersion, options, callbacks), workflowStartHeaders = runWorkflowStartInterceptor(internals, workflowId, type, input, parentHeaders, callbacks), persistedWorkflowStartHeaders = selectPersistedWorkflowStartHeaders(workflowStartHeaders), purgeDeleteOperations = terminalRunToPurge !== null ? await prepareTerminalRunPurge(internals, terminalRunToPurge, callbacks) : void 0;
|
|
79
83
|
internals.checkpoints.set(workflowId, checkpoint);
|
|
80
84
|
setWorkflowStartHeaders(internals, workflowId, workflowStartHeaders, callbacks);
|
|
81
85
|
internals.workflowVersionTuples.set(workflowId, versionTuple);
|
|
@@ -89,12 +93,16 @@ export async function startWorkflow(internals, type, input, options, additionalS
|
|
|
89
93
|
delayedStartTimer,
|
|
90
94
|
persistedWorkflowStartHeaders,
|
|
91
95
|
additionalStartOperations,
|
|
92
|
-
|
|
96
|
+
buildWorkflowConcurrencyStartOperations: workflowConcurrency === void 0 ? void 0 : () => buildWorkflowConcurrencyStartOperations(internals, type, workflowId, input, workflowConcurrency),
|
|
97
|
+
callbacks,
|
|
98
|
+
purgeDeleteOperations
|
|
93
99
|
}, buildIdempotentStartOperations);
|
|
94
100
|
if (options?.services !== void 0) {
|
|
95
101
|
internals.workflowServices.set(workflowId, options.services);
|
|
96
102
|
internals.workflowsNeedingTerminalCleanup.add(workflowId);
|
|
97
103
|
}
|
|
104
|
+
if (workflowConcurrency !== void 0)
|
|
105
|
+
internals.workflowsNeedingTerminalCleanup.add(workflowId);
|
|
98
106
|
const handle = createWorkflowHandle(internals, workflowId, callbacks);
|
|
99
107
|
await beginExecutionAwaitingLiveness(internals, {
|
|
100
108
|
type,
|
|
@@ -137,7 +145,7 @@ function buildInitialIdentitySlice(workflowId, type, input, versionTuple, execut
|
|
|
137
145
|
status: delayedStartTimer ? "pending" : "running",
|
|
138
146
|
input,
|
|
139
147
|
versionTuple,
|
|
140
|
-
executionStateOwnerId,
|
|
148
|
+
...executionStateOwnerId !== void 0 && { executionStateOwnerId },
|
|
141
149
|
createdAt: now,
|
|
142
150
|
...!delayedStartTimer && { startedAt: now },
|
|
143
151
|
updatedAt: now,
|