@lostgradient/weft 0.3.0 → 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 +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 +46 -5
- package/dist/client/local.d.ts +4 -1
- package/dist/client/local.js +12 -4
- 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 +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 -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 +133 -8
- 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 +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/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 +22 -3
- 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 +27 -27
- 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 +26 -26
- 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 +28 -28
- 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
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
function evaluateConditionOutcome(internals, predicate, deadline) {
|
|
2
|
+
if (predicate())
|
|
3
|
+
return { done: !0, value: deadline === void 0 ? void 0 : !0 };
|
|
4
|
+
if (deadline !== void 0 && internals.options.getNow() >= deadline)
|
|
5
|
+
return { done: !0, value: !1 };
|
|
6
|
+
return { done: !1 };
|
|
7
|
+
}
|
|
8
|
+
export async function processWaitConditionOperation(internals, workflowId, operation, callbacks) {
|
|
9
|
+
const abortSignal = internals.abortController.signal, { predicate, deadline } = operation;
|
|
10
|
+
let settled = !1;
|
|
11
|
+
const complete = (value) => {
|
|
12
|
+
if (settled)
|
|
13
|
+
return;
|
|
14
|
+
settled = !0;
|
|
15
|
+
callbacks.completeOperation(workflowId, value);
|
|
16
|
+
};
|
|
17
|
+
if (abortSignal.aborted)
|
|
18
|
+
return;
|
|
19
|
+
try {
|
|
20
|
+
const initial = evaluateConditionOutcome(internals, predicate, deadline);
|
|
21
|
+
if (initial.done) {
|
|
22
|
+
complete(initial.value);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (deadline !== void 0)
|
|
26
|
+
await callbacks.scheduleConditionDeadline(workflowId, operation.step, deadline);
|
|
27
|
+
try {
|
|
28
|
+
let step = await runConditionWaitStep(internals, workflowId, predicate, deadline, callbacks);
|
|
29
|
+
while (step.status === "continue")
|
|
30
|
+
step = await runConditionWaitStep(internals, workflowId, predicate, deadline, callbacks);
|
|
31
|
+
if (step.status === "complete")
|
|
32
|
+
complete(step.value);
|
|
33
|
+
} finally {
|
|
34
|
+
releaseConditionWaiter(internals, workflowId);
|
|
35
|
+
if (deadline !== void 0)
|
|
36
|
+
await callbacks.cancelConditionDeadline(workflowId, operation.step);
|
|
37
|
+
}
|
|
38
|
+
} catch (error) {
|
|
39
|
+
callbacks.failOperation(workflowId, operation, error);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function runConditionWaitStep(internals, workflowId, predicate, deadline, callbacks) {
|
|
43
|
+
const abortSignal = internals.abortController.signal;
|
|
44
|
+
if (abortSignal.aborted)
|
|
45
|
+
return { status: "stop" };
|
|
46
|
+
const { promise, resolve } = Promise.withResolvers();
|
|
47
|
+
internals.conditionWaiters.set(workflowId, resolve);
|
|
48
|
+
const outcome = abortSignal.aborted ? { done: !0, value: void 0, aborted: !0 } : { ...evaluateConditionOutcome(internals, predicate, deadline), aborted: !1 };
|
|
49
|
+
if (outcome.done) {
|
|
50
|
+
releaseConditionWaiter(internals, workflowId);
|
|
51
|
+
return outcome.aborted ? { status: "stop" } : { status: "complete", value: outcome.value };
|
|
52
|
+
}
|
|
53
|
+
await promise;
|
|
54
|
+
if (abortSignal.aborted)
|
|
55
|
+
return { status: "stop" };
|
|
56
|
+
if (!await callbacks.isWorkflowRunning(workflowId))
|
|
57
|
+
return { status: "stop" };
|
|
58
|
+
return { status: "continue" };
|
|
59
|
+
}
|
|
60
|
+
function releaseConditionWaiter(internals, workflowId) {
|
|
61
|
+
internals.conditionWaiters.delete(workflowId);
|
|
62
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolution of the `ownership` posture options (`Engine.create({ ownership })`)
|
|
3
|
+
* into {@link ResolvedOptions}. Extracted from `construction.ts` to keep that
|
|
4
|
+
* file under the `max-lines` ceiling; mirrors the second-instance resolver's
|
|
5
|
+
* "only validate when the feature is enabled" discipline.
|
|
6
|
+
*
|
|
7
|
+
* @module core/engine/ownership-options
|
|
8
|
+
*/
|
|
9
|
+
import type { EngineConstructorOptions, ResolvedOptions } from './engine-internal-types.ts';
|
|
10
|
+
/** Default lease time-to-live for `ownership: 'lease'`. */
|
|
11
|
+
export declare const DEFAULT_LEASE_TTL_MS = 30000;
|
|
12
|
+
/** Default lease renewal interval for `ownership: 'lease'`. */
|
|
13
|
+
export declare const DEFAULT_LEASE_RENEW_INTERVAL_MS = 5000;
|
|
14
|
+
/** Default boot-time lease acquisition wait window for `ownership: 'lease'`. */
|
|
15
|
+
export declare const DEFAULT_LEASE_WAIT_TIMEOUT_MS = 60000;
|
|
16
|
+
/**
|
|
17
|
+
* Resolve the ownership posture and lease tuning into their `ResolvedOptions`
|
|
18
|
+
* fields. Defaults to `'none'`. The lease durations are documented as "ignored
|
|
19
|
+
* when ownership is not 'lease'", so they are only normalized (and thus only
|
|
20
|
+
* able to throw on an invalid value) when lease ownership is actually enabled —
|
|
21
|
+
* an invalid duration must not make an off-by-default config fatal at boot.
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveOwnershipFields(options: EngineConstructorOptions | undefined): Pick<ResolvedOptions, 'ownershipMode' | 'leaseTtlMs' | 'leaseRenewIntervalMs' | 'leaseWaitTimeoutMs'>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { normalizeRetentionDuration } from "./validation.js";
|
|
2
|
+
export const DEFAULT_LEASE_TTL_MS = 30000, DEFAULT_LEASE_RENEW_INTERVAL_MS = 5000, DEFAULT_LEASE_WAIT_TIMEOUT_MS = 60000;
|
|
3
|
+
export function resolveOwnershipFields(options) {
|
|
4
|
+
const ownershipMode = assertKnownOwnershipMode(options?.ownership ?? "none");
|
|
5
|
+
if (ownershipMode !== "lease")
|
|
6
|
+
return {
|
|
7
|
+
ownershipMode,
|
|
8
|
+
leaseTtlMs: DEFAULT_LEASE_TTL_MS,
|
|
9
|
+
leaseRenewIntervalMs: DEFAULT_LEASE_RENEW_INTERVAL_MS,
|
|
10
|
+
leaseWaitTimeoutMs: DEFAULT_LEASE_WAIT_TIMEOUT_MS
|
|
11
|
+
};
|
|
12
|
+
const leaseTtlMs = normalizeRetentionDuration(options?.leaseTtl, "options.leaseTtl") ?? DEFAULT_LEASE_TTL_MS, leaseRenewIntervalMs = normalizeRetentionDuration(options?.leaseRenewInterval, "options.leaseRenewInterval") ?? DEFAULT_LEASE_RENEW_INTERVAL_MS, leaseWaitTimeoutMs = normalizeRetentionDuration(options?.leaseWaitTimeout, "options.leaseWaitTimeout") ?? DEFAULT_LEASE_WAIT_TIMEOUT_MS;
|
|
13
|
+
assertLeaseTimingCoherent(leaseTtlMs, leaseRenewIntervalMs, leaseWaitTimeoutMs);
|
|
14
|
+
return { ownershipMode, leaseTtlMs, leaseRenewIntervalMs, leaseWaitTimeoutMs };
|
|
15
|
+
}
|
|
16
|
+
function assertKnownOwnershipMode(mode) {
|
|
17
|
+
if (mode !== "none" && mode !== "lease")
|
|
18
|
+
throw Error(`Unknown ownership posture "${String(mode)}". Expected 'none' or 'lease'.`);
|
|
19
|
+
return mode;
|
|
20
|
+
}
|
|
21
|
+
function assertLeaseTimingCoherent(leaseTtlMs, leaseRenewIntervalMs, leaseWaitTimeoutMs) {
|
|
22
|
+
if (leaseTtlMs <= 0 || leaseRenewIntervalMs <= 0 || leaseWaitTimeoutMs <= 0)
|
|
23
|
+
throw Error(`ownership: 'lease' requires positive leaseTtl, leaseRenewInterval, and leaseWaitTimeout (got leaseTtl=${leaseTtlMs}ms, leaseRenewInterval=${leaseRenewIntervalMs}ms, leaseWaitTimeout=${leaseWaitTimeoutMs}ms).`);
|
|
24
|
+
if (leaseRenewIntervalMs >= leaseTtlMs)
|
|
25
|
+
throw Error(`ownership: 'lease' requires leaseRenewInterval (${leaseRenewIntervalMs}ms) to be strictly less than leaseTtl (${leaseTtlMs}ms), so a renewal fires before the lease can lapse.`);
|
|
26
|
+
}
|
|
@@ -14,5 +14,22 @@ export declare function invokeUpdateHandler(internals: EngineInternals, name: st
|
|
|
14
14
|
*/
|
|
15
15
|
export declare function processPendingUpdatesAfterInlineAdvance(internals: EngineInternals, workflowId: string, callbacks: PendingUpdateCallbacks): Promise<void>;
|
|
16
16
|
export declare function schedulePendingInlineUpdateDrain(internals: EngineInternals, workflowId: string, callbacks: PendingUpdateCallbacks): void;
|
|
17
|
+
/**
|
|
18
|
+
* Drain a workflow's buffered coordinated updates and deliver each to its
|
|
19
|
+
* handler exactly once, even when several drains race.
|
|
20
|
+
*
|
|
21
|
+
* Several triggers can fire near-simultaneously: each `engine.update()` schedules
|
|
22
|
+
* a `setTimeout(0)` drain, and the post-advance path drains too. Their consume-
|
|
23
|
+
* deletes are durable (`storage.batch`) and lag the in-memory `getPendingUpdates`
|
|
24
|
+
* scan, so two overlapping drains both see the same pending set. Each update id
|
|
25
|
+
* is therefore CLAIMED synchronously in `deliveredPendingUpdateIds` before
|
|
26
|
+
* delivery (no `await` between the membership check and the add, so a concurrent
|
|
27
|
+
* drain cannot interleave): a racing drain that re-reads the same id skips it.
|
|
28
|
+
*
|
|
29
|
+
* After the drain, re-drive a parked `ctx.waitUntil` once. A coordinated update
|
|
30
|
+
* buffered before `ctx.onUpdate` was registered drains here (not on the inline
|
|
31
|
+
* `tryInlineUpdateHandler` path), and a handler may have mutated the workflow-
|
|
32
|
+
* local state a predicate reads, so the wait must be poked to re-evaluate.
|
|
33
|
+
*/
|
|
17
34
|
export declare function processPendingUpdatesForHandlers(internals: EngineInternals, workflowId: string, callbacks: PendingUpdateCallbacks): Promise<void>;
|
|
18
35
|
export {};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { UpdateCompletedEvent, UpdateReceivedEvent } from "../events.js";
|
|
2
2
|
import { UpdateValidationError } from "../updates.js";
|
|
3
|
+
import { notifyConditionWaiters } from "./condition-waiters.js";
|
|
4
|
+
import { commitFencedEngineWrite } from "./fenced-write.js";
|
|
3
5
|
import {
|
|
4
6
|
extractStandardSchemaIssues,
|
|
5
7
|
invokeUpdateHandler as invokeUpdateHandlerFromInternals
|
|
@@ -71,17 +73,37 @@ export async function processPendingUpdatesForHandlers(internals, workflowId, ca
|
|
|
71
73
|
const pendingUpdates = await internals.updateCoordinator.getPendingUpdates(workflowId);
|
|
72
74
|
if (pendingUpdates.length === 0)
|
|
73
75
|
return;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
let handlerRan = !1;
|
|
77
|
+
try {
|
|
78
|
+
for (const update of pendingUpdates) {
|
|
79
|
+
const handler = handlers.get(update.name);
|
|
80
|
+
if (!handler)
|
|
81
|
+
continue;
|
|
82
|
+
if (!claimPendingUpdateForDelivery(internals, workflowId, update.updateId))
|
|
83
|
+
continue;
|
|
84
|
+
const validatorRejectionError = await runValidatorIfPresent(context, update);
|
|
85
|
+
if (validatorRejectionError !== null) {
|
|
86
|
+
await rejectPendingUpdate(internals, workflowId, update, validatorRejectionError, callbacks);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
handlerRan = !0;
|
|
90
|
+
await deliverPendingUpdate(internals, workflowId, update, handler, callbacks);
|
|
82
91
|
}
|
|
83
|
-
|
|
92
|
+
} finally {
|
|
93
|
+
if (handlerRan)
|
|
94
|
+
notifyConditionWaiters(internals, workflowId);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function claimPendingUpdateForDelivery(internals, workflowId, updateId) {
|
|
98
|
+
let claimed = internals.deliveredPendingUpdateIds.get(workflowId);
|
|
99
|
+
if (claimed === void 0) {
|
|
100
|
+
claimed = new Set;
|
|
101
|
+
internals.deliveredPendingUpdateIds.set(workflowId, claimed);
|
|
84
102
|
}
|
|
103
|
+
if (claimed.has(updateId))
|
|
104
|
+
return !1;
|
|
105
|
+
claimed.add(updateId);
|
|
106
|
+
return !0;
|
|
85
107
|
}
|
|
86
108
|
async function runValidatorIfPresent(context, update) {
|
|
87
109
|
const validator = context.updateValidators?.get(update.name);
|
|
@@ -91,7 +113,7 @@ async function runValidatorIfPresent(context, update) {
|
|
|
91
113
|
}
|
|
92
114
|
async function rejectPendingUpdate(internals, workflowId, update, errorMessage, callbacks) {
|
|
93
115
|
const responseOperations = internals.updateCoordinator.buildResponseOperations(update.updateId, workflowId, void 0, errorMessage, update.idempotencyKey);
|
|
94
|
-
await internals
|
|
116
|
+
await commitFencedEngineWrite(internals, responseOperations, [], () => Error(`Update rejection for workflow "${workflowId}" lost its CAS race.`));
|
|
95
117
|
callbacks.broadcast({ type: "update:completed", workflowId, updateId: update.updateId });
|
|
96
118
|
}
|
|
97
119
|
async function deliverPendingUpdate(internals, workflowId, update, handler, callbacks) {
|
|
@@ -103,7 +125,7 @@ async function deliverPendingUpdate(internals, workflowId, update, handler, call
|
|
|
103
125
|
error = handlerError instanceof Error ? handlerError.message : String(handlerError);
|
|
104
126
|
}
|
|
105
127
|
const responseOperations = internals.updateCoordinator.buildResponseOperations(update.updateId, workflowId, result, error, update.idempotencyKey);
|
|
106
|
-
await internals
|
|
128
|
+
await commitFencedEngineWrite(internals, responseOperations, [], () => Error(`Update response for workflow "${workflowId}" lost its CAS race.`));
|
|
107
129
|
callbacks.dispatchEvent(new UpdateCompletedEvent(update.updateId, workflowId, update.name, result, error));
|
|
108
130
|
callbacks.broadcast({ type: "update:completed", workflowId, updateId: update.updateId });
|
|
109
131
|
}
|
|
@@ -4,7 +4,7 @@ export async function query(internals, workflowId, name, input) {
|
|
|
4
4
|
const inlineStrategy = internals.inlineStrategy;
|
|
5
5
|
if (!inlineStrategy)
|
|
6
6
|
throw Error("Workflow queries are not supported when using the worker execution strategy.");
|
|
7
|
-
const context = inlineStrategy.getContext(workflowId);
|
|
7
|
+
const context = inlineStrategy.getContext(workflowId) ?? inlineStrategy.getParkedContext(workflowId);
|
|
8
8
|
if (!context)
|
|
9
9
|
return;
|
|
10
10
|
const queryHandler = context.queryHandlers.get(name);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { EngineInternals } from './internals.ts';
|
|
2
2
|
export type RegistrationCallbacks = {
|
|
3
3
|
ensureRetentionSweepInterval: () => void;
|
|
4
|
+
dispatchEvent: (event: Event) => void;
|
|
4
5
|
};
|
|
5
6
|
export declare function register(internals: EngineInternals, definition: unknown, callbacks: RegistrationCallbacks): void;
|
|
6
7
|
export declare function resolveWorkflowTypeTarget(internals: EngineInternals, target: string | Function, _callbacks: RegistrationCallbacks): string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ActivityRegistry } from "../activity-registry.js";
|
|
2
|
+
import { WorkflowDefinitionRegisteredEvent } from "../events.js";
|
|
2
3
|
import {
|
|
3
4
|
activity,
|
|
4
5
|
validateDefinitionSchemaMetadata
|
|
@@ -31,16 +32,29 @@ function buildBaseRegistrationEntry(name, registration) {
|
|
|
31
32
|
...registration.outputSchema === void 0 ? {} : {
|
|
32
33
|
outputSchema: validateDefinitionSchemaMetadata(registration.outputSchema, `registration("${name}").outputSchema`)
|
|
33
34
|
},
|
|
34
|
-
...normalizedRetention !== null && { retention: normalizedRetention }
|
|
35
|
+
...normalizedRetention !== null && { retention: normalizedRetention },
|
|
36
|
+
...registration.concurrency !== void 0 ? {
|
|
37
|
+
concurrency: normalizeWorkflowConcurrencyOptions(registration.concurrency, `registration("${name}").concurrency`)
|
|
38
|
+
} : {}
|
|
35
39
|
};
|
|
36
40
|
}
|
|
41
|
+
function normalizeWorkflowConcurrencyOptions(concurrency, fieldName) {
|
|
42
|
+
if (!Number.isInteger(concurrency.max) || concurrency.max < 1)
|
|
43
|
+
throw RangeError(`${fieldName}.max must be a positive integer`);
|
|
44
|
+
if (concurrency.key !== void 0 && typeof concurrency.key !== "function")
|
|
45
|
+
throw TypeError(`${fieldName}.key must be a function when provided`);
|
|
46
|
+
return Object.freeze({
|
|
47
|
+
max: concurrency.max,
|
|
48
|
+
...concurrency.key === void 0 ? {} : { key: concurrency.key }
|
|
49
|
+
});
|
|
50
|
+
}
|
|
37
51
|
function applyOptionalRegistrationFields(entry, registration) {
|
|
38
|
-
if (registration.migrate)
|
|
39
|
-
entry.migrate = registration.migrate;
|
|
40
52
|
if (registration.searchAttributes && Object.keys(registration.searchAttributes).length > 0)
|
|
41
53
|
entry.searchAttributes = registration.searchAttributes;
|
|
42
54
|
if (registration.constraints && registration.constraints.length > 0)
|
|
43
55
|
entry.constraints = registration.constraints;
|
|
56
|
+
if (registration.finalizer !== void 0)
|
|
57
|
+
entry.finalizer = registration.finalizer;
|
|
44
58
|
}
|
|
45
59
|
function buildRegistrationEntry(name, registration) {
|
|
46
60
|
const entry = buildBaseRegistrationEntry(name, registration);
|
|
@@ -55,6 +69,7 @@ function commitWorkflowDefinition(internals, definition, callbacks) {
|
|
|
55
69
|
internals.registrations.set(name, entry);
|
|
56
70
|
callbacks.ensureRetentionSweepInterval();
|
|
57
71
|
internals.workflowTypesByHandler.set(definition.handler, name);
|
|
72
|
+
callbacks.dispatchEvent(new WorkflowDefinitionRegisteredEvent(name));
|
|
58
73
|
}
|
|
59
74
|
function hasNonNullObjectField(value, key) {
|
|
60
75
|
if (!(key in value))
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ScheduleState } from '../types.ts';
|
|
2
|
+
type JitteredSchedule = Pick<ScheduleState, 'id' | 'jitterMs'>;
|
|
3
|
+
export declare function computeScheduleJitterOffset(scheduleId: string, nominalFireAt: number, jitterMs: number | undefined): number;
|
|
4
|
+
export declare function resolveEffectiveScheduleFireAt(schedule: JitteredSchedule, nominalFireAt: number): number;
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { hashString } from "../../runtime/portable.js";
|
|
2
|
+
export function computeScheduleJitterOffset(scheduleId, nominalFireAt, jitterMs) {
|
|
3
|
+
if (jitterMs === void 0 || jitterMs <= 0)
|
|
4
|
+
return 0;
|
|
5
|
+
const hash = BigInt(`0x${hashString(`${scheduleId}\x00${nominalFireAt}`)}`);
|
|
6
|
+
return Number(hash % BigInt(jitterMs));
|
|
7
|
+
}
|
|
8
|
+
export function resolveEffectiveScheduleFireAt(schedule, nominalFireAt) {
|
|
9
|
+
return nominalFireAt + computeScheduleJitterOffset(schedule.id, nominalFireAt, schedule.jitterMs);
|
|
10
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ScheduleState } from '../types.ts';
|
|
2
|
+
import type { EngineInternals } from './internals.ts';
|
|
3
|
+
import type { ScheduleCallbacks } from './schedules.ts';
|
|
4
|
+
/**
|
|
5
|
+
* Launch one scheduled occurrence's workflow run and emit `schedule:fired`.
|
|
6
|
+
*
|
|
7
|
+
* This is the single chokepoint every occurrence launch flows through — initial
|
|
8
|
+
* cadence ticks, `cancel-running` replacements, and `queue`-drained runs — so it
|
|
9
|
+
* is the one place that reliably holds the launched `workflowId` across all
|
|
10
|
+
* overlap policies. The blocked policies (`skip`, and `queue` while a run is
|
|
11
|
+
* active) never reach here, so they correctly do not fire.
|
|
12
|
+
*
|
|
13
|
+
* `occurrence` is the scheduled grid timestamp the run was due, threaded from the
|
|
14
|
+
* timer loop. It is `undefined` for a `queue`-drained run, whose grid slot was
|
|
15
|
+
* tracked only as a count and whose original timestamp is therefore gone.
|
|
16
|
+
*/
|
|
17
|
+
export declare function startScheduledRun(internals: EngineInternals, state: ScheduleState, callbacks: Pick<ScheduleCallbacks, 'startWorkflow' | 'failWorkflow' | 'handleCleanupError'>, occurrence?: number): Promise<string>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { KEYS } from "../../storage/interface.js";
|
|
2
|
+
import { encode } from "../codec.js";
|
|
3
|
+
import { ScheduleFiredEvent } from "../events.js";
|
|
4
|
+
import { unavailableServicesError } from "./lifecycle/recovered-services.js";
|
|
5
|
+
import { EMPTY_STORAGE_VALUE } from "./lifecycle/shared.js";
|
|
6
|
+
export async function startScheduledRun(internals, state, callbacks, occurrence) {
|
|
7
|
+
const workflowId = crypto.randomUUID(), scheduleRunOperations = state.overlap === "allow" ? [] : [{ type: "put", key: KEYS.scheduleRun(workflowId), value: encode(state.id) }], resolution = await resolveScheduledRunServices(internals, workflowId, state);
|
|
8
|
+
if (resolution !== null) {
|
|
9
|
+
scheduleRunOperations.push({ type: "put", key: KEYS.workflowHasServices(workflowId), value: EMPTY_STORAGE_VALUE }, { type: "put", key: KEYS.terminalCleanupNeeded(workflowId), value: EMPTY_STORAGE_VALUE });
|
|
10
|
+
internals.workflowsNeedingTerminalCleanup.add(workflowId);
|
|
11
|
+
if (resolution.status === "available")
|
|
12
|
+
internals.workflowServices.set(workflowId, resolution.services);
|
|
13
|
+
}
|
|
14
|
+
await callbacks.startWorkflow(state.workflowType, state.input, { id: workflowId }, scheduleRunOperations);
|
|
15
|
+
internals.engine.dispatchEvent(new ScheduleFiredEvent(state.id, workflowId, internals.options.getNow(), occurrence));
|
|
16
|
+
if (resolution !== null && resolution.status === "unavailable") {
|
|
17
|
+
const unavailableError = unavailableServicesError(workflowId, resolution.reason);
|
|
18
|
+
try {
|
|
19
|
+
await callbacks.failWorkflow(workflowId, unavailableError);
|
|
20
|
+
} catch (error) {
|
|
21
|
+
callbacks.handleCleanupError("startScheduledRun", error, workflowId);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return workflowId;
|
|
25
|
+
}
|
|
26
|
+
async function resolveScheduledRunServices(internals, workflowId, state) {
|
|
27
|
+
const resolver = internals.options.resolveWorkflowServices;
|
|
28
|
+
if (internals.inlineStrategy === null || !resolver)
|
|
29
|
+
return null;
|
|
30
|
+
try {
|
|
31
|
+
return await resolver({ workflowId, workflowType: state.workflowType, input: state.input });
|
|
32
|
+
} catch (error) {
|
|
33
|
+
return {
|
|
34
|
+
status: "unavailable",
|
|
35
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -1,6 +1,16 @@
|
|
|
1
|
+
import { ScheduleMissedFireEvent } from "../events/schedule-events.js";
|
|
2
|
+
import { resolveEffectiveScheduleFireAt } from "./schedule-jitter.js";
|
|
1
3
|
import { collectDueScheduleOccurrences, getNextScheduleOccurrence } from "./schedule-occurrence.js";
|
|
2
4
|
import { loadScheduleState, writeScheduleState } from "./storage-io.js";
|
|
3
|
-
const SCHEDULE_LATE_GRACE_MILLISECONDS = 1000, MAX_SCHEDULE_BACKFILL_OCCURRENCES_PER_TICK = 256;
|
|
5
|
+
const SCHEDULE_LATE_GRACE_MILLISECONDS = 1000, MAX_SCHEDULE_BACKFILL_OCCURRENCES_PER_TICK = 256, MAX_MISSED_FIRE_COUNT_PER_TICK = MAX_SCHEDULE_BACKFILL_OCCURRENCES_PER_TICK;
|
|
6
|
+
|
|
7
|
+
class ScheduleStatePersistenceError extends Error {
|
|
8
|
+
scheduleId;
|
|
9
|
+
constructor(scheduleId, cause) {
|
|
10
|
+
super(`Failed to persist schedule "${scheduleId}" while processing its timer`, { cause });
|
|
11
|
+
this.scheduleId = scheduleId;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
4
14
|
export async function handleScheduleTimer(internals, entry, callbacks) {
|
|
5
15
|
const state = await loadScheduleState(internals, entry.workflowId);
|
|
6
16
|
if (!isCurrentActiveScheduleTimer(state, entry))
|
|
@@ -10,28 +20,43 @@ export async function handleScheduleTimer(internals, entry, callbacks) {
|
|
|
10
20
|
const now = internals.options.getNow(), work = planScheduleTimerWork(state, entry, now);
|
|
11
21
|
if (!work)
|
|
12
22
|
return;
|
|
13
|
-
|
|
14
|
-
nextState =
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
if (work.occurrencesToProcess.length === 0) {
|
|
24
|
+
nextState = {
|
|
25
|
+
...nextState,
|
|
26
|
+
updatedAt: now,
|
|
27
|
+
nextFireAt: resolveNextScheduleFireAt(nextState, work, now),
|
|
28
|
+
...work.missedOccurrences && {
|
|
29
|
+
lastMissedFireAt: work.missedOccurrences.lastMissedFireAt,
|
|
30
|
+
missedFireCount: nextState.missedFireCount + work.missedOccurrences.count
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
await persistScheduleTimerState(internals, nextState);
|
|
34
|
+
if (work.missedOccurrences)
|
|
35
|
+
internals.engine.dispatchEvent(new ScheduleMissedFireEvent(nextState.id, work.missedOccurrences.count, work.missedOccurrences.windowStart, work.missedOccurrences.windowEnd));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
nextState = await processScheduleTimerOccurrences(internals, state, work, now, callbacks, {
|
|
39
|
+
onProcessedState: (processedState) => {
|
|
40
|
+
nextState = processedState;
|
|
41
|
+
}
|
|
20
42
|
});
|
|
21
43
|
} catch (error) {
|
|
44
|
+
if (error instanceof ScheduleStatePersistenceError)
|
|
45
|
+
throw error;
|
|
22
46
|
await pauseScheduleAfterTimerFailure(internals, nextState, error);
|
|
23
47
|
}
|
|
24
48
|
}
|
|
25
49
|
function isCurrentActiveScheduleTimer(state, entry) {
|
|
26
|
-
return state?.status === "active" && state.nextFireAt === entry.fireAt;
|
|
50
|
+
return state?.status === "active" && state.nextFireAt !== null && resolveEffectiveScheduleFireAt(state, state.nextFireAt) === entry.fireAt;
|
|
27
51
|
}
|
|
28
52
|
function planScheduleTimerWork(state, entry, now) {
|
|
29
53
|
const dueOccurrences = collectDueScheduleOccurrences(state, state.nextFireAt, Math.max(now, entry.fireAt), state.backfill ? MAX_SCHEDULE_BACKFILL_OCCURRENCES_PER_TICK : 2);
|
|
30
54
|
if (dueOccurrences.length === 0)
|
|
31
55
|
return null;
|
|
32
|
-
if (!state.backfill && now -
|
|
56
|
+
if (!state.backfill && now - entry.fireAt > SCHEDULE_LATE_GRACE_MILLISECONDS)
|
|
33
57
|
return {
|
|
34
58
|
dueOccurrences,
|
|
59
|
+
missedOccurrences: countMissedScheduleOccurrences(state, state.nextFireAt, now),
|
|
35
60
|
occurrencesToProcess: [],
|
|
36
61
|
skipMissedOccurrences: !0
|
|
37
62
|
};
|
|
@@ -42,29 +67,68 @@ function planScheduleTimerWork(state, entry, now) {
|
|
|
42
67
|
skipMissedOccurrences: !1
|
|
43
68
|
};
|
|
44
69
|
}
|
|
70
|
+
function countMissedScheduleOccurrences(state, firstDueAt, throughTimestamp) {
|
|
71
|
+
let count = 0, occurrence = firstDueAt, lastMissedFireAt = firstDueAt;
|
|
72
|
+
while (occurrence <= throughTimestamp && count < MAX_MISSED_FIRE_COUNT_PER_TICK) {
|
|
73
|
+
count += 1;
|
|
74
|
+
lastMissedFireAt = occurrence;
|
|
75
|
+
const nextOccurrence = getNextScheduleOccurrence(state, occurrence);
|
|
76
|
+
if (nextOccurrence <= occurrence)
|
|
77
|
+
throw Error(`Schedule "${state.id}" produced a non-advancing occurrence`);
|
|
78
|
+
occurrence = nextOccurrence;
|
|
79
|
+
}
|
|
80
|
+
const cappedBeforeThroughTimestamp = occurrence <= throughTimestamp;
|
|
81
|
+
return {
|
|
82
|
+
count,
|
|
83
|
+
lastMissedFireAt,
|
|
84
|
+
windowStart: firstDueAt,
|
|
85
|
+
windowEnd: cappedBeforeThroughTimestamp ? lastMissedFireAt : throughTimestamp
|
|
86
|
+
};
|
|
87
|
+
}
|
|
45
88
|
function resolveNextScheduleFireAt(state, work, now) {
|
|
46
89
|
if (work.skipMissedOccurrences)
|
|
47
|
-
return getNextScheduleOccurrence(state, now);
|
|
90
|
+
return getNextScheduleOccurrence(state, work.missedOccurrences?.lastMissedFireAt ?? now);
|
|
48
91
|
const anchorOccurrence = work.occurrencesToProcess.at(-1) ?? work.dueOccurrences.at(-1);
|
|
49
92
|
return getNextScheduleOccurrence(state, anchorOccurrence);
|
|
50
93
|
}
|
|
51
|
-
async function processScheduleTimerOccurrences(internals, state,
|
|
94
|
+
async function processScheduleTimerOccurrences(internals, state, work, now, callbacks, options) {
|
|
52
95
|
let nextState = state;
|
|
53
|
-
for (const occurrence of occurrencesToProcess) {
|
|
96
|
+
for (const [index, occurrence] of work.occurrencesToProcess.entries()) {
|
|
97
|
+
const finalOccurrence = index === work.occurrencesToProcess.length - 1;
|
|
54
98
|
nextState = {
|
|
55
|
-
...await callbacks.applyScheduleOccurrence(nextState),
|
|
99
|
+
...await callbacks.applyScheduleOccurrence(nextState, occurrence),
|
|
56
100
|
lastFireAt: occurrence,
|
|
57
101
|
updatedAt: now
|
|
58
102
|
};
|
|
59
|
-
|
|
60
|
-
|
|
103
|
+
if (finalOccurrence)
|
|
104
|
+
nextState = {
|
|
105
|
+
...nextState,
|
|
106
|
+
nextFireAt: resolveNextScheduleFireAt(nextState, work, now)
|
|
107
|
+
};
|
|
108
|
+
options.onProcessedState(nextState);
|
|
109
|
+
await persistScheduleTimerState(internals, nextState, { includeTimer: finalOccurrence });
|
|
61
110
|
if (state.backfill && nextState.currentWorkflowId !== void 0) {
|
|
62
111
|
nextState = await callbacks.settleBackfillScheduleState(nextState);
|
|
63
|
-
|
|
112
|
+
if (finalOccurrence) {
|
|
113
|
+
nextState = {
|
|
114
|
+
...nextState,
|
|
115
|
+
updatedAt: now,
|
|
116
|
+
nextFireAt: resolveNextScheduleFireAt(nextState, work, now)
|
|
117
|
+
};
|
|
118
|
+
await persistScheduleTimerState(internals, nextState);
|
|
119
|
+
}
|
|
120
|
+
options.onProcessedState(nextState);
|
|
64
121
|
}
|
|
65
122
|
}
|
|
66
123
|
return nextState;
|
|
67
124
|
}
|
|
125
|
+
async function persistScheduleTimerState(internals, state, options) {
|
|
126
|
+
try {
|
|
127
|
+
await writeScheduleState(internals, state, options);
|
|
128
|
+
} catch (error) {
|
|
129
|
+
throw new ScheduleStatePersistenceError(state.id, error);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
68
132
|
async function pauseScheduleAfterTimerFailure(internals, state, error) {
|
|
69
133
|
const errorNow = internals.options.getNow(), pausedState = {
|
|
70
134
|
...state,
|
|
@@ -2,6 +2,7 @@ import type { BatchOperation } from '../../storage/interface.ts';
|
|
|
2
2
|
import type { PaginatedResult, ScheduleFilter, ScheduleOptions, ScheduleSpec, ScheduleState, ScheduleSummary, WorkflowState } from '../types.ts';
|
|
3
3
|
import type { EngineInternals } from './internals.ts';
|
|
4
4
|
import { ScheduleHandle } from './schedule-handle.ts';
|
|
5
|
+
export { startScheduledRun } from './schedule-run.ts';
|
|
5
6
|
export { handleScheduleTimer } from './schedule-timer.ts';
|
|
6
7
|
export type RefreshedScheduleState = {
|
|
7
8
|
state: ScheduleState;
|
|
@@ -15,20 +16,22 @@ export type ScheduleCallbacks = {
|
|
|
15
16
|
cancelWorkflow: (workflowId: string) => Promise<void>;
|
|
16
17
|
getWorkflowResult: (workflowId: string) => Promise<unknown>;
|
|
17
18
|
refreshScheduledWorkflowState: (state: ScheduleState) => Promise<RefreshedScheduleState>;
|
|
18
|
-
startScheduledRun: (state: ScheduleState) => Promise<string>;
|
|
19
|
-
applyScheduleOccurrence: (state: ScheduleState) => Promise<ScheduleState>;
|
|
19
|
+
startScheduledRun: (state: ScheduleState, occurrence?: number) => Promise<string>;
|
|
20
|
+
applyScheduleOccurrence: (state: ScheduleState, occurrence?: number) => Promise<ScheduleState>;
|
|
20
21
|
settleBackfillScheduleState: (state: ScheduleState) => Promise<ScheduleState>;
|
|
21
22
|
flushQueuedInlineWorkflowStartsDirectly: () => Promise<void>;
|
|
23
|
+
failWorkflow: (workflowId: string, error: Error) => Promise<void>;
|
|
24
|
+
handleCleanupError: (source: string, error: unknown, workflowId: string) => void;
|
|
22
25
|
};
|
|
23
26
|
export declare function schedule(internals: EngineInternals, type: string, input: unknown, spec: string | ScheduleSpec, options?: ScheduleOptions): Promise<ScheduleHandle>;
|
|
24
27
|
export declare function listSchedules(internals: EngineInternals, filter?: ScheduleFilter): Promise<PaginatedResult<ScheduleSummary>>;
|
|
28
|
+
export declare function recoverOrphanedScheduleTimers(internals: EngineInternals): Promise<void>;
|
|
25
29
|
export declare function toScheduleSummary(state: ScheduleState): ScheduleSummary;
|
|
26
30
|
export declare function pauseSchedule(internals: EngineInternals, scheduleId: string): Promise<void>;
|
|
27
31
|
export declare function resumeSchedule(internals: EngineInternals, scheduleId: string): Promise<void>;
|
|
28
32
|
export declare function cancelSchedule(internals: EngineInternals, scheduleId: string): Promise<void>;
|
|
29
33
|
export declare function updateSchedule(internals: EngineInternals, scheduleId: string, newSpec: string | ScheduleSpec): Promise<void>;
|
|
30
34
|
export declare function refreshScheduledWorkflowState(internals: EngineInternals, state: ScheduleState, callbacks: Pick<ScheduleCallbacks, 'loadWorkflowState'>): Promise<RefreshedScheduleState>;
|
|
31
|
-
export declare function
|
|
32
|
-
export declare function applyScheduleOccurrence(_internals: EngineInternals, state: ScheduleState, callbacks: ScheduleCallbacks): Promise<ScheduleState>;
|
|
35
|
+
export declare function applyScheduleOccurrence(_internals: EngineInternals, state: ScheduleState, callbacks: ScheduleCallbacks, occurrence?: number): Promise<ScheduleState>;
|
|
33
36
|
export declare function settleBackfillScheduleState(internals: EngineInternals, state: ScheduleState, callbacks: Pick<ScheduleCallbacks, 'flushQueuedInlineWorkflowStartsDirectly' | 'refreshScheduledWorkflowState'>): Promise<ScheduleState>;
|
|
34
37
|
export declare function handleScheduledWorkflowTerminal(internals: EngineInternals, workflowId: string, callbacks: ScheduleCallbacks): Promise<void>;
|