@lostgradient/weft 0.2.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +123 -43
- package/dist/cli/conformance.js +7 -1
- package/dist/cli/generated/operation-client.generated.d.ts +55 -13
- package/dist/cli/generated/operation-client.generated.js +3 -0
- package/dist/cli/help-text.d.ts +1 -1
- package/dist/cli/help-text.js +1 -0
- package/dist/cli/operation-catalog-snapshot.d.ts +8 -0
- package/dist/cli/operation-catalog-snapshot.js +11 -0
- package/dist/cli/parse-schedule-arguments.js +3 -1
- package/dist/cli/schedule.js +2 -1
- package/dist/cli/types.d.ts +1 -0
- package/dist/cli-main.js +80 -79
- package/dist/client/handle-delegation.d.ts +7 -2
- package/dist/client/handle-delegation.js +9 -1
- package/dist/client/http-client-requests.d.ts +4 -1
- package/dist/client/http-client-requests.js +10 -0
- package/dist/client/http-client.d.ts +10 -4
- package/dist/client/http-client.js +18 -1
- package/dist/client/http-request.d.ts +11 -1
- package/dist/client/http-request.js +17 -7
- package/dist/client/index.d.ts +1 -1
- package/dist/client/interface.d.ts +100 -4
- package/dist/client/local.d.ts +7 -1
- package/dist/client/local.js +17 -2
- package/dist/client/start-body.d.ts +9 -2
- package/dist/client/start-body.js +13 -4
- package/dist/core/byte-arrays.d.ts +5 -0
- package/dist/core/byte-arrays.js +5 -0
- package/dist/core/checkpoint/lifecycle.d.ts +3 -0
- package/dist/core/checkpoint/lifecycle.js +9 -4
- package/dist/core/checkpoint/serialization.js +12 -5
- package/dist/core/codec/extension-codec.d.ts +16 -0
- package/dist/core/codec/extension-codec.js +104 -8
- package/dist/core/codec/index.d.ts +1 -0
- package/dist/core/codec/index.js +1 -0
- package/dist/core/codec/serializer-registry.d.ts +122 -0
- package/dist/core/codec/serializer-registry.js +51 -0
- package/dist/core/context/activity-retry-state.d.ts +38 -0
- package/dist/core/context/activity-retry-state.js +89 -0
- package/dist/core/context/activity-schedule-to-close.d.ts +159 -0
- package/dist/core/context/activity-schedule-to-close.js +69 -0
- package/dist/core/context/child-workflow-pipe.d.ts +5 -5
- package/dist/core/context/child-workflow-pipe.js +15 -2
- package/dist/core/context/context-presence.d.ts +19 -0
- package/dist/core/context/context-presence.js +13 -0
- package/dist/core/context/durable-operations.d.ts +25 -0
- package/dist/core/context/durable-operations.js +64 -0
- package/dist/core/context/index.d.ts +18 -5
- package/dist/core/context/index.js +17 -12
- package/dist/core/context/internals.d.ts +29 -0
- package/dist/core/context/internals.js +6 -1
- package/dist/core/context/operation-request.d.ts +35 -0
- package/dist/core/context/parallel-cache-entry.d.ts +14 -5
- package/dist/core/context/run-operation.d.ts +21 -3
- package/dist/core/context/run-operation.js +56 -93
- package/dist/core/context/session-state.js +7 -8
- package/dist/core/context/speculative-child.js +2 -0
- package/dist/core/context/types.d.ts +15 -0
- package/dist/core/context/version-patching.d.ts +8 -0
- package/dist/core/context/version-patching.js +40 -0
- package/dist/core/context/workflow-logger.d.ts +98 -0
- package/dist/core/context/workflow-logger.js +68 -0
- package/dist/core/engine/activity-heartbeat-tracking.d.ts +64 -0
- package/dist/core/engine/activity-heartbeat-tracking.js +42 -0
- package/dist/core/engine/activity-per-attempt-timeout.d.ts +41 -0
- package/dist/core/engine/activity-per-attempt-timeout.js +36 -0
- package/dist/core/engine/activity-reconciliation.d.ts +1 -0
- package/dist/core/engine/activity-reconciliation.js +12 -1
- package/dist/core/engine/activity-resolution.d.ts +23 -0
- package/dist/core/engine/activity-resolution.js +37 -0
- package/dist/core/engine/aggregate.js +66 -30
- package/dist/core/engine/async-activity-completion.d.ts +23 -6
- package/dist/core/engine/async-activity-completion.js +53 -12
- package/dist/core/engine/attributes-tags.js +9 -4
- package/dist/core/engine/bulk-operations-purge.d.ts +26 -0
- package/dist/core/engine/bulk-operations-purge.js +38 -3
- package/dist/core/engine/bulk-operations-shared.d.ts +2 -0
- package/dist/core/engine/bulk-operations-shared.js +8 -2
- package/dist/core/engine/bulk-operations.d.ts +4 -1
- package/dist/core/engine/bulk-operations.js +235 -24
- package/dist/core/engine/callback-creators-bundles.d.ts +9 -0
- package/dist/core/engine/callback-creators-bundles.js +30 -2
- package/dist/core/engine/callback-creators-core.js +6 -4
- package/dist/core/engine/callback-creators-router.js +10 -0
- package/dist/core/engine/callback-creators-schedule.d.ts +2 -2
- package/dist/core/engine/callback-creators-schedule.js +12 -8
- package/dist/core/engine/candidate-read-batching.d.ts +6 -0
- package/dist/core/engine/candidate-read-batching.js +1 -0
- package/dist/core/engine/checkpoint-io.js +61 -25
- package/dist/core/engine/checkpoint-reads.js +3 -2
- package/dist/core/engine/checkpoint-replay.d.ts +20 -0
- package/dist/core/engine/checkpoint-replay.js +242 -0
- package/dist/core/engine/checkpoint-side-effects.d.ts +23 -0
- package/dist/core/engine/checkpoint-side-effects.js +35 -0
- package/dist/core/engine/child-workflow-cancellation.d.ts +10 -0
- package/dist/core/engine/child-workflow-cancellation.js +40 -0
- package/dist/core/engine/child-workflow.js +27 -4
- package/dist/core/engine/condition-waiters.d.ts +14 -0
- package/dist/core/engine/condition-waiters.js +5 -0
- package/dist/core/engine/construction.d.ts +3 -1
- package/dist/core/engine/construction.js +30 -8
- package/dist/core/engine/coordination-branch-executors.d.ts +70 -0
- package/dist/core/engine/coordination-branch-executors.js +107 -0
- package/dist/core/engine/deferred-consume-envelope.d.ts +59 -0
- package/dist/core/engine/deferred-consume-envelope.js +14 -0
- package/dist/core/engine/disposal.js +25 -0
- package/dist/core/engine/engine-create-types.d.ts +14 -18
- package/dist/core/engine/engine-internal-types.d.ts +38 -3
- package/dist/core/engine/engine-leak-warnings.d.ts +6 -0
- package/dist/core/engine/engine-leak-warnings.js +4 -0
- package/dist/core/engine/engine-runtime-helpers.d.ts +17 -0
- package/dist/core/engine/engine-runtime-helpers.js +26 -5
- package/dist/core/engine/errors.d.ts +121 -0
- package/dist/core/engine/errors.js +45 -1
- package/dist/core/engine/event-log-compaction.d.ts +8 -0
- package/dist/core/engine/event-log-compaction.js +20 -2
- package/dist/core/engine/fenced-write.d.ts +65 -0
- package/dist/core/engine/fenced-write.js +71 -0
- package/dist/core/engine/finalizer-state.d.ts +28 -0
- package/dist/core/engine/finalizer-state.js +16 -0
- package/dist/core/engine/handle-result.js +1 -1
- package/dist/core/engine/handles.d.ts +97 -40
- package/dist/core/engine/handles.js +25 -27
- package/dist/core/engine/index.d.ts +125 -15
- package/dist/core/engine/index.js +207 -11
- package/dist/core/engine/inline-launch-queue.d.ts +14 -0
- package/dist/core/engine/inline-launch-queue.js +32 -7
- package/dist/core/engine/inline-parking.js +3 -2
- package/dist/core/engine/internals.d.ts +125 -13
- package/dist/core/engine/lease-codec.d.ts +35 -0
- package/dist/core/engine/lease-codec.js +32 -0
- package/dist/core/engine/lease-deposition.d.ts +66 -0
- package/dist/core/engine/lease-deposition.js +10 -0
- package/dist/core/engine/lease-errors.d.ts +99 -0
- package/dist/core/engine/lease-errors.js +30 -0
- package/dist/core/engine/lease-manager.d.ts +114 -0
- package/dist/core/engine/lease-manager.js +135 -0
- package/dist/core/engine/lifecycle/fork-helpers.js +1 -7
- package/dist/core/engine/lifecycle/persist.js +15 -52
- package/dist/core/engine/lifecycle/recovered-services.d.ts +8 -6
- package/dist/core/engine/lifecycle/recovered-services.js +18 -3
- package/dist/core/engine/lifecycle/resume.js +39 -11
- package/dist/core/engine/lifecycle/shared.d.ts +8 -1
- package/dist/core/engine/lifecycle/start-batch.d.ts +1 -1
- package/dist/core/engine/lifecycle/start-batch.js +2 -1
- package/dist/core/engine/lifecycle/start-commit.d.ts +56 -0
- package/dist/core/engine/lifecycle/start-commit.js +69 -0
- package/dist/core/engine/lifecycle/start-exec.d.ts +30 -2
- package/dist/core/engine/lifecycle/start-exec.js +38 -0
- package/dist/core/engine/lifecycle/start-or-signal-create.d.ts +58 -0
- package/dist/core/engine/lifecycle/start-or-signal-create.js +95 -0
- package/dist/core/engine/lifecycle/start-or-signal-resolution.d.ts +79 -0
- package/dist/core/engine/lifecycle/start-or-signal-resolution.js +60 -0
- package/dist/core/engine/lifecycle/start-or-signal.d.ts +46 -0
- package/dist/core/engine/lifecycle/start-or-signal.js +71 -0
- package/dist/core/engine/lifecycle/start-terminal-conflict-purge.d.ts +39 -0
- package/dist/core/engine/lifecycle/start-terminal-conflict-purge.js +28 -0
- package/dist/core/engine/lifecycle/start.d.ts +6 -6
- package/dist/core/engine/lifecycle/start.js +47 -45
- package/dist/core/engine/lifecycle/transition.js +17 -5
- package/dist/core/engine/lifecycle.d.ts +3 -2
- package/dist/core/engine/lifecycle.js +9 -2
- package/dist/core/engine/list-candidate-resolution.js +2 -2
- package/dist/core/engine/listing.js +10 -6
- package/dist/core/engine/operations-activity.d.ts +4 -11
- package/dist/core/engine/operations-activity.js +22 -49
- package/dist/core/engine/operations-coordination.d.ts +10 -0
- package/dist/core/engine/operations-coordination.js +43 -8
- package/dist/core/engine/operations-router.d.ts +6 -0
- package/dist/core/engine/operations-router.js +2 -0
- package/dist/core/engine/operations-speculate.js +6 -2
- package/dist/core/engine/operations-stream.js +12 -2
- package/dist/core/engine/operations-time.d.ts +4 -2
- package/dist/core/engine/operations-time.js +14 -2
- package/dist/core/engine/operations-wait-condition.d.ts +23 -0
- package/dist/core/engine/operations-wait-condition.js +62 -0
- package/dist/core/engine/ownership-options.d.ts +23 -0
- package/dist/core/engine/ownership-options.js +26 -0
- package/dist/core/engine/payload-size-policy.d.ts +3 -0
- package/dist/core/engine/payload-size-policy.js +4 -0
- package/dist/core/engine/pending-updates.d.ts +17 -0
- package/dist/core/engine/pending-updates.js +33 -11
- package/dist/core/engine/persisted-data-version.d.ts +5 -9
- package/dist/core/engine/persisted-data-version.js +4 -5
- package/dist/core/engine/queries.js +1 -1
- package/dist/core/engine/registration.d.ts +1 -0
- package/dist/core/engine/registration.js +18 -3
- package/dist/core/engine/schedule-handle.d.ts +45 -0
- package/dist/core/engine/schedule-handle.js +26 -0
- package/dist/core/engine/schedule-jitter.d.ts +5 -0
- package/dist/core/engine/schedule-jitter.js +10 -0
- package/dist/core/engine/schedule-run.d.ts +17 -0
- package/dist/core/engine/schedule-run.js +38 -0
- package/dist/core/engine/schedule-timer.js +81 -17
- package/dist/core/engine/schedules.d.ts +8 -5
- package/dist/core/engine/schedules.js +44 -19
- package/dist/core/engine/search-attribute-records.d.ts +4 -0
- package/dist/core/engine/search-attribute-records.js +17 -0
- package/dist/core/engine/second-instance-detector.d.ts +96 -0
- package/dist/core/engine/second-instance-detector.js +108 -0
- package/dist/core/engine/signals.d.ts +38 -0
- package/dist/core/engine/signals.js +55 -19
- package/dist/core/engine/state-utilities.d.ts +49 -2
- package/dist/core/engine/state-utilities.js +114 -3
- package/dist/core/engine/storage-io.d.ts +16 -2
- package/dist/core/engine/storage-io.js +26 -5
- package/dist/core/engine/stream-chunk-loading.d.ts +2 -0
- package/dist/core/engine/stream-chunk-loading.js +24 -1
- package/dist/core/engine/sub-operation.js +22 -3
- package/dist/core/engine/termination/cleanup.d.ts +28 -1
- package/dist/core/engine/termination/cleanup.js +44 -2
- package/dist/core/engine/termination/complete.js +48 -9
- package/dist/core/engine/termination/finalizer-activity.d.ts +53 -0
- package/dist/core/engine/termination/finalizer-activity.js +30 -0
- package/dist/core/engine/termination/finalizer-claim.d.ts +110 -0
- package/dist/core/engine/termination/finalizer-claim.js +80 -0
- package/dist/core/engine/termination/finalizer.d.ts +48 -0
- package/dist/core/engine/termination/finalizer.js +159 -0
- package/dist/core/engine/termination/suspend.d.ts +70 -0
- package/dist/core/engine/termination/suspend.js +41 -0
- package/dist/core/engine/termination.d.ts +5 -2
- package/dist/core/engine/termination.js +6 -0
- package/dist/core/engine/updates.js +5 -25
- package/dist/core/engine/validation/schedule.d.ts +2 -1
- package/dist/core/engine/validation/schedule.js +51 -2
- package/dist/core/engine/validation.js +54 -3
- package/dist/core/engine/waiting-update-response.d.ts +8 -0
- package/dist/core/engine/waiting-update-response.js +22 -0
- package/dist/core/engine/workflow-concurrency.d.ts +10 -0
- package/dist/core/engine/workflow-concurrency.js +136 -0
- package/dist/core/engine/workflow-feed.d.ts +9 -8
- package/dist/core/engine/workflow-feed.js +4 -1
- package/dist/core/engine/workflow-indexes.d.ts +9 -0
- package/dist/core/engine/workflow-indexes.js +10 -0
- package/dist/core/engine/workflow-state-stream.js +33 -13
- package/dist/core/engine/workflow-visibility-queries.d.ts +2 -2
- package/dist/core/engine-helpers.js +1 -0
- package/dist/core/events/activity-events.d.ts +43 -12
- package/dist/core/events/activity-events.js +28 -0
- package/dist/core/events/attribute-events.d.ts +2 -3
- package/dist/core/events/event-map.d.ts +19 -12
- package/dist/core/events/index.d.ts +1 -0
- package/dist/core/events/index.js +1 -0
- package/dist/core/events/schedule-events.d.ts +71 -0
- package/dist/core/events/schedule-events.js +29 -0
- package/dist/core/events/signal-events.d.ts +4 -6
- package/dist/core/events/system-events.d.ts +29 -19
- package/dist/core/events/system-events.js +26 -0
- package/dist/core/events/update-events.d.ts +6 -8
- package/dist/core/events/workflow-events.d.ts +108 -20
- package/dist/core/events/workflow-events.js +35 -0
- package/dist/core/failure-categories.js +5 -17
- package/dist/core/fault-code.d.ts +9 -3
- package/dist/core/fault-code.js +1 -0
- package/dist/core/inline-execution-strategy.context-options.d.ts +69 -0
- package/dist/core/inline-execution-strategy.context-options.js +56 -0
- package/dist/core/inline-execution-strategy.d.ts +31 -36
- package/dist/core/inline-execution-strategy.js +16 -27
- package/dist/core/list-filter-validation.d.ts +1 -1
- package/dist/core/list-filter-validation.js +2 -1
- package/dist/core/payload-size.d.ts +1 -1
- package/dist/core/persisted-data-incompatible-error.d.ts +9 -7
- package/dist/core/review/events.d.ts +6 -8
- package/dist/core/scheduler/scheduler-class.d.ts +10 -1
- package/dist/core/scheduler/scheduler-class.js +38 -11
- package/dist/core/scheduler/timer-batch.js +9 -1
- package/dist/core/scheduler/timer-sources.d.ts +1 -0
- package/dist/core/scheduler/timer-sources.js +11 -5
- package/dist/core/session-state.d.ts +0 -1
- package/dist/core/session-state.js +2 -2
- package/dist/core/start-workflow-validation.d.ts +56 -0
- package/dist/core/start-workflow-validation.js +30 -1
- package/dist/core/step-context.d.ts +10 -6
- package/dist/core/step-context.js +7 -15
- package/dist/core/types/activity-verification.d.ts +67 -0
- package/dist/core/types/activity-verification.js +0 -0
- package/dist/core/types/activity.d.ts +86 -64
- package/dist/core/types/bulk.d.ts +50 -9
- package/dist/core/types/checkpoint.d.ts +44 -8
- package/dist/core/types/identity.d.ts +8 -1
- package/dist/core/types/launch-metadata.d.ts +33 -0
- package/dist/core/types/launch-metadata.js +0 -0
- package/dist/core/types/list-options.d.ts +146 -0
- package/dist/core/types/list-options.js +0 -0
- package/dist/core/types/message-handles.d.ts +25 -0
- package/dist/core/types/options.d.ts +165 -215
- package/dist/core/types/reviews.d.ts +2 -1
- package/dist/core/types/schedules.d.ts +39 -3
- package/dist/core/types/services-resolution.d.ts +47 -0
- package/dist/core/types/services-resolution.js +0 -0
- package/dist/core/types/state.d.ts +11 -11
- package/dist/core/types/workflow-builder-runtime.d.ts +12 -3
- package/dist/core/types/workflow-builder-runtime.js +11 -2
- package/dist/core/types/workflow-builder.d.ts +47 -15
- package/dist/core/types/workflow-concurrency.d.ts +39 -0
- package/dist/core/types/workflow-concurrency.js +0 -0
- package/dist/core/types/workflow-context.d.ts +157 -14
- package/dist/core/types/workflow-definition.d.ts +53 -10
- package/dist/core/types/workflow-function.d.ts +101 -9
- package/dist/core/types/workflow-log.d.ts +98 -0
- package/dist/core/types/workflow-log.js +0 -0
- package/dist/core/types/workflow-registries.d.ts +14 -3
- package/dist/core/types/workflow-registry.d.ts +3 -0
- package/dist/core/types/workflow-snapshot.d.ts +29 -0
- package/dist/core/types/workflow-snapshot.js +0 -0
- package/dist/core/types.d.ts +7 -0
- package/dist/core/types.js +7 -0
- package/dist/core/versioning.d.ts +9 -39
- package/dist/core/versioning.js +2 -12
- package/dist/core/weft-error.d.ts +44 -1
- package/dist/core/weft-error.js +19 -1
- package/dist/core/worker-execution-strategy-options.d.ts +26 -0
- package/dist/core/worker-execution-strategy.js +40 -36
- package/dist/core/worker-inbound-message.d.ts +38 -0
- package/dist/core/worker-inbound-message.js +37 -0
- package/dist/core/worker-log-abuse-counter.d.ts +175 -0
- package/dist/core/worker-log-abuse-counter.js +107 -0
- package/dist/core/worker-message-helpers.d.ts +47 -0
- package/dist/core/worker-message-helpers.js +26 -0
- package/dist/core/worker-protocol-guard.js +1 -1
- package/dist/core/worker-protocol-log.d.ts +56 -0
- package/dist/core/worker-protocol-log.js +18 -0
- package/dist/core/worker-protocol.d.ts +23 -0
- package/dist/core/worker-protocol.js +12 -2
- package/dist/core/workflow-version-tuple.d.ts +3 -9
- package/dist/core/workflow-version-tuple.js +2 -3
- package/dist/diagnostics/doctor.js +6 -3
- package/dist/diagnostics/format.js +3 -8
- package/dist/diagnostics/types.d.ts +5 -5
- package/dist/diagnostics/validate.d.ts +0 -1
- package/dist/diagnostics/version-check.d.ts +1 -1
- package/dist/diagnostics/version-check.js +10 -13
- package/dist/index.d.ts +13 -11
- package/dist/index.js +39 -4
- package/dist/json-schema.js +3 -3
- package/dist/mcp/cli.js +35 -35
- package/dist/mcp/dispatcher.js +1 -1
- package/dist/mcp/http.js +16 -6
- package/dist/mcp/list-filter.js +2 -1
- package/dist/mcp/protocol.d.ts +2 -0
- package/dist/mcp/protocol.js +1 -1
- package/dist/mcp/session.d.ts +16 -0
- package/dist/mcp/session.js +60 -6
- package/dist/mcp/tools.js +73 -6
- package/dist/observability/index.js +2 -2
- package/dist/server/asyncapi-channels.js +5 -2
- package/dist/server/attribute-filters.d.ts +8 -3
- package/dist/server/attribute-filters.js +6 -1
- package/dist/server/authentication/api-key.d.ts +2 -1
- package/dist/server/authentication/api-key.js +5 -2
- package/dist/server/authentication/constant-time-api-key.d.ts +15 -0
- package/dist/server/authentication/constant-time-api-key.js +24 -0
- package/dist/server/authentication/index.d.ts +1 -1
- package/dist/server/authentication/index.js +7 -4
- package/dist/server/authentication/rotating-api-key-store.d.ts +5 -3
- package/dist/server/authentication/rotating-api-key-store.js +19 -11
- package/dist/server/engine-event-feed-backend.d.ts +4 -5
- package/dist/server/fault-to-http.js +8 -1
- package/dist/server/fault-to-json-rpc.js +1 -0
- package/dist/server/fleet-event-feed.d.ts +31 -0
- package/dist/server/fleet-event-feed.js +157 -0
- package/dist/server/handler/index.js +1 -1
- package/dist/server/handler/response-helpers.js +2 -1
- package/dist/server/handler/route-dispatch.d.ts +6 -3
- package/dist/server/handler/route-dispatch.js +2 -2
- package/dist/server/handler.js +31 -31
- package/dist/server/index.d.ts +32 -2
- package/dist/server/index.js +35 -35
- package/dist/server/interactive-operations.js +1 -0
- package/dist/server/json-rpc-transport-helpers.d.ts +1 -0
- package/dist/server/json-rpc-transport-helpers.js +2 -1
- package/dist/server/json-rpc-websocket-runtime.d.ts +11 -2
- package/dist/server/json-rpc-websocket-runtime.js +1 -0
- package/dist/server/json-rpc-websocket-subscriptions.d.ts +10 -0
- package/dist/server/json-rpc-websocket-subscriptions.js +29 -0
- package/dist/server/json-rpc-websocket-types.d.ts +22 -0
- package/dist/server/json-rpc-websocket-types.js +0 -0
- package/dist/server/json-rpc-websocket-validation.js +20 -4
- package/dist/server/json-rpc-websocket.d.ts +2 -43
- package/dist/server/json-rpc-websocket.js +57 -74
- package/dist/server/openapi.d.ts +2 -1
- package/dist/server/openapi.js +1 -3
- package/dist/server/openrpc-document-schema.d.ts +78 -0
- package/dist/server/openrpc-document-schema.js +27 -1
- package/dist/server/openrpc-errors.d.ts +3 -0
- package/dist/server/openrpc-errors.js +2 -1
- package/dist/server/openrpc.js +32 -0
- package/dist/server/operation-catalog/index.d.ts +1 -1
- package/dist/server/operation-catalog/pipeline-helpers.js +1 -0
- package/dist/server/operation-catalog/pipeline-stages.js +26 -12
- package/dist/server/operation-catalog/pipeline.js +8 -1
- package/dist/server/operation-catalog/registry.js +13 -0
- package/dist/server/operation-catalog/types.d.ts +20 -9
- package/dist/server/operation-fault.d.ts +10 -0
- package/dist/server/operation-fault.js +2 -0
- package/dist/server/operation-registry.d.ts +12 -11
- package/dist/server/operation-registry.js +12 -3
- package/dist/server/operations/aggregate-workflows.d.ts +15 -15
- package/dist/server/operations/async-activity.d.ts +2 -2
- package/dist/server/operations/async-activity.js +12 -7
- package/dist/server/operations/bulk-cancel-workflows.d.ts +1 -1
- package/dist/server/operations/bulk-cancel-workflows.js +2 -2
- package/dist/server/operations/bulk-delete-workflows.d.ts +1 -1
- package/dist/server/operations/bulk-delete-workflows.js +2 -2
- package/dist/server/operations/bulk-filter-helpers.d.ts +8 -6
- package/dist/server/operations/bulk-filter-helpers.js +54 -24
- package/dist/server/operations/bulk-mutate-workflow-tags.d.ts +11 -9
- package/dist/server/operations/bulk-mutate-workflow-tags.js +2 -2
- package/dist/server/operations/bulk-operation-helpers.d.ts +2 -2
- package/dist/server/operations/bulk-retry-failed-workflows.d.ts +7 -0
- package/dist/server/operations/bulk-retry-failed-workflows.js +64 -0
- package/dist/server/operations/bulk-signal-workflows.d.ts +11 -9
- package/dist/server/operations/bulk-signal-workflows.js +2 -2
- package/dist/server/operations/cancel-schedule.d.ts +1 -1
- package/dist/server/operations/create-schedule.d.ts +3 -1
- package/dist/server/operations/create-schedule.js +29 -11
- package/dist/server/operations/fleet-events-subscription.d.ts +54 -0
- package/dist/server/operations/fleet-events-subscription.js +99 -0
- package/dist/server/operations/fork-workflow.d.ts +1 -1
- package/dist/server/operations/fork-workflow.js +3 -2
- package/dist/server/operations/get-checkpoint-at.d.ts +1 -1
- package/dist/server/operations/get-registry.d.ts +1 -1
- package/dist/server/operations/get-retention-overview.d.ts +1 -1
- package/dist/server/operations/get-review.d.ts +1 -1
- package/dist/server/operations/get-schedule.d.ts +1 -1
- package/dist/server/operations/get-stream-chunks.d.ts +1 -1
- package/dist/server/operations/get-system-metrics.d.ts +2 -2
- package/dist/server/operations/get-task-diagnostics.d.ts +45 -6
- package/dist/server/operations/get-task-diagnostics.js +101 -7
- package/dist/server/operations/get-update-result.d.ts +1 -1
- package/dist/server/operations/get-workflow-attributes.d.ts +1 -1
- package/dist/server/operations/get-workflow-events.d.ts +1 -1
- package/dist/server/operations/get-workflow-result.d.ts +1 -1
- package/dist/server/operations/get-workflow-timeline.d.ts +1 -1
- package/dist/server/operations/get-workflow.d.ts +1 -1
- package/dist/server/operations/list-checkpoints.d.ts +1 -1
- package/dist/server/operations/list-reviews.d.ts +1 -1
- package/dist/server/operations/list-schedules.d.ts +1 -1
- package/dist/server/operations/list-task-queues.d.ts +2 -2
- package/dist/server/operations/list-workers.d.ts +2 -2
- package/dist/server/operations/list-workflows.d.ts +1 -1
- package/dist/server/operations/operation-helpers.d.ts +16 -1
- package/dist/server/operations/operation-helpers.js +15 -3
- package/dist/server/operations/pause-schedule.d.ts +1 -1
- package/dist/server/operations/purge-workflows.d.ts +5 -5
- package/dist/server/operations/purge-workflows.js +2 -2
- package/dist/server/operations/query-workflow.d.ts +1 -1
- package/dist/server/operations/query-workflow.js +3 -2
- package/dist/server/operations/recover-all.d.ts +1 -1
- package/dist/server/operations/replay-workflow.d.ts +1 -1
- package/dist/server/operations/resume-schedule.d.ts +1 -1
- package/dist/server/operations/resume-workflow.js +2 -2
- package/dist/server/operations/set-workflow-attributes.d.ts +1 -1
- package/dist/server/operations/set-workflow-attributes.js +6 -3
- package/dist/server/operations/signal-workflow.js +8 -3
- package/dist/server/operations/single-workflow-tag-mutation.js +13 -3
- package/dist/server/operations/start-or-signal-workflow.d.ts +44 -0
- package/dist/server/operations/start-or-signal-workflow.js +130 -0
- package/dist/server/operations/start-workflow-options.d.ts +38 -0
- package/dist/server/operations/start-workflow-options.js +63 -0
- package/dist/server/operations/start-workflow-rest-input.d.ts +14 -0
- package/dist/server/operations/start-workflow-rest-input.js +31 -0
- package/dist/server/operations/start-workflow.d.ts +1 -1
- package/dist/server/operations/start-workflow.js +15 -92
- package/dist/server/operations/storage.d.ts +6 -6
- package/dist/server/operations/storage.js +24 -14
- package/dist/server/operations/stream-workflow-sse.d.ts +1 -1
- package/dist/server/operations/submit-review-decision.d.ts +1 -1
- package/dist/server/operations/submit-review-decision.js +6 -3
- package/dist/server/operations/suspend-workflow.d.ts +13 -0
- package/dist/server/operations/suspend-workflow.js +36 -0
- package/dist/server/operations/update-schedule.d.ts +1 -1
- package/dist/server/operations/update-schedule.js +7 -4
- package/dist/server/operations/update-workflow.d.ts +1 -1
- package/dist/server/operations/update-workflow.js +7 -3
- package/dist/server/operations/worker-drain.d.ts +8 -8
- package/dist/server/operations/worker-drain.js +11 -8
- package/dist/server/operations/workflow-events-subscription.d.ts +7 -8
- package/dist/server/operations/workflow-events-subscription.js +43 -8
- package/dist/server/rest-binding.d.ts +21 -8
- package/dist/server/rest-bindings.js +24 -0
- package/dist/server/rest-body.d.ts +10 -0
- package/dist/server/rest-body.js +80 -0
- package/dist/server/runtime/authentication-bridge.d.ts +1 -0
- package/dist/server/runtime/authentication-bridge.js +33 -6
- package/dist/server/runtime/client-visible-events.d.ts +3 -0
- package/dist/server/runtime/client-visible-events.js +65 -0
- package/dist/server/runtime/context.d.ts +7 -0
- package/dist/server/runtime/event-broadcasting.d.ts +6 -0
- package/dist/server/runtime/event-broadcasting.js +72 -38
- package/dist/server/runtime/retry.d.ts +1 -0
- package/dist/server/runtime/retry.js +14 -0
- package/dist/server/runtime/shutdown.d.ts +7 -6
- package/dist/server/runtime/shutdown.js +6 -1
- package/dist/server/runtime/task-dispatch.js +5 -3
- package/dist/server/runtime/task-polling.d.ts +16 -2
- package/dist/server/runtime/task-polling.js +80 -24
- package/dist/server/runtime/task-reconciliation.js +9 -1
- package/dist/server/runtime/task-result-resolution.d.ts +15 -0
- package/dist/server/runtime/task-result-resolution.js +81 -0
- package/dist/server/runtime/websocket-stream.d.ts +20 -1
- package/dist/server/runtime/websocket-stream.js +173 -7
- package/dist/server/runtime/websocket-upgrade.js +22 -3
- package/dist/server/runtime/websocket-worker.d.ts +1 -1
- package/dist/server/runtime/websocket-worker.js +46 -30
- package/dist/server/serve-internals.d.ts +11 -1
- package/dist/server/serve-internals.js +20 -2
- package/dist/server/task-state.d.ts +38 -0
- package/dist/server/task-state.js +28 -0
- package/dist/server/workflow-event-feed.d.ts +36 -115
- package/dist/server/workflow-event-feed.js +92 -27
- package/dist/service-worker/index.js +31 -31
- package/dist/storage/auto.js +1 -1
- package/dist/storage/bun-sql.js +24 -0
- package/dist/storage/capabilities.d.ts +10 -2
- package/dist/storage/capabilities.js +2 -2
- package/dist/storage/compressed-storage.js +1 -1
- package/dist/storage/default-scope.d.ts +7 -4
- package/dist/storage/http.js +2 -2
- package/dist/storage/index.d.ts +81 -4
- package/dist/storage/indexeddb.js +1 -1
- package/dist/storage/interface.d.ts +189 -0
- package/dist/storage/interface.js +1 -1
- package/dist/storage/key-prefixes.d.ts +1 -1
- package/dist/storage/key-prefixes.js +12 -0
- package/dist/storage/lmdb.d.ts +4 -3
- package/dist/storage/lmdb.js +1 -1
- package/dist/storage/memory.js +1 -1
- package/dist/storage/neon-batch.d.ts +30 -0
- package/dist/storage/neon-batch.js +30 -0
- package/dist/storage/neon-value-mapping.d.ts +74 -0
- package/dist/storage/neon-value-mapping.js +23 -0
- package/dist/storage/neon.d.ts +124 -0
- package/dist/storage/neon.js +15 -0
- package/dist/storage/node-sqlite-loader.d.ts +71 -0
- package/dist/storage/node-sqlite-loader.js +41 -0
- package/dist/storage/node-sqlite.d.ts +1 -19
- package/dist/storage/node-sqlite.js +61 -32
- package/dist/storage/postgres-key-value-queries.d.ts +104 -0
- package/dist/storage/postgres-key-value-queries.js +101 -0
- package/dist/storage/resolve.d.ts +2 -165
- package/dist/storage/resolve.js +1 -1
- package/dist/storage/scoped-storage.js +1 -1
- package/dist/storage/storage-configuration.d.ts +209 -0
- package/dist/storage/storage-configuration.js +0 -0
- package/dist/storage/testing.d.ts +168 -0
- package/dist/storage/testing.js +2 -0
- package/dist/storage/text-value-store.d.ts +9 -9
- package/dist/storage/turso.d.ts +8 -0
- package/dist/storage/turso.js +2 -2
- package/dist/storage/typed-storage.js +1 -1
- package/dist/storage/web-extension.js +1 -1
- package/dist/testing/index.js +35 -35
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker/index.js +9 -5
- package/dist/worker/long-poll.js +4 -0
- package/dist/worker/protocol-messages.d.ts +20 -0
- package/dist/worker/protocol-schemas.d.ts +32 -0
- package/dist/worker/protocol-schemas.js +8 -4
- package/dist/worker/protocol-task-result.d.ts +28 -0
- package/dist/worker/protocol-task-result.js +76 -0
- package/dist/worker/protocol.d.ts +4 -15
- package/dist/worker/protocol.js +1 -1
- package/dist/worker/registry/fair-share.d.ts +29 -0
- package/dist/worker/registry/fair-share.js +30 -0
- package/dist/worker/registry/routing.d.ts +18 -0
- package/dist/worker/registry/routing.js +14 -0
- package/dist/worker/registry/types.d.ts +7 -0
- package/dist/worker/registry.d.ts +16 -1
- package/dist/worker/registry.js +24 -36
- package/dist/workers/worker-replay-state.d.ts +32 -0
- package/dist/workers/worker-replay-state.js +35 -0
- package/dist/workers/worker-state-namespace.d.ts +21 -0
- package/dist/workers/worker-state-namespace.js +13 -0
- package/dist/workers/workflow-runner.d.ts +19 -15
- package/dist/workers/workflow-runner.js +72 -60
- package/dist/workers/workflow-worker-entry.js +5 -2
- package/package.json +21 -4
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { ActivityContext } from '../types.ts';
|
|
2
|
+
import type { EngineInternals } from './internals.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Per-step heartbeat tracking for {@link ActivityContext.lastHeartbeatDetails}.
|
|
5
|
+
*
|
|
6
|
+
* The store is keyed `workflowId -> step` (not `workflowId` alone) so a retry of
|
|
7
|
+
* an activity step reads the heartbeat ITS prior attempt recorded — and so a
|
|
8
|
+
* later step's first attempt never inherits an earlier step's heartbeat, and
|
|
9
|
+
* concurrent `ctx.all` activities never clobber one another. The step is stable
|
|
10
|
+
* across retry attempts (assigned once at `stepIndex++`). Held only in engine
|
|
11
|
+
* memory and cleared by workflowId (the outer key) on terminal cleanup and purge.
|
|
12
|
+
*/
|
|
13
|
+
/** Record the heartbeat the current attempt of a step sent. */
|
|
14
|
+
export declare function recordLastHeartbeatForStep(internals: EngineInternals, workflowId: string, step: number, details: unknown): void;
|
|
15
|
+
/** Read the heartbeat a prior attempt of this step recorded, or `undefined`. */
|
|
16
|
+
export declare function readLastHeartbeatForStep(internals: EngineInternals, workflowId: string, step: number): unknown;
|
|
17
|
+
/**
|
|
18
|
+
* Drop the heartbeat tracked for a single step once that step has completed
|
|
19
|
+
* successfully — after inline verify, and (on the idempotency path) after the
|
|
20
|
+
* reconciliation write, so a verify-rejection retry still reads its prior
|
|
21
|
+
* attempt's heartbeat. The plain path has no reconciliation write; both paths
|
|
22
|
+
* call this only at their successful return. Removes the inner-map entry and
|
|
23
|
+
* drops the outer workflow entry when its last step clears, so a long-lived
|
|
24
|
+
* workflow doesn't accumulate stale per-step heartbeats. Clearing late is
|
|
25
|
+
* harmless (bounded by terminal cleanup); clearing early would strip the
|
|
26
|
+
* resumable-batch heartbeat a retry depends on, so this is only ever called from
|
|
27
|
+
* the non-speculative success path.
|
|
28
|
+
*/
|
|
29
|
+
export declare function clearLastHeartbeatForStep(internals: EngineInternals, workflowId: string, step: number): void;
|
|
30
|
+
/**
|
|
31
|
+
* #493: in development mode, emit a COARSE warning when an inline activity RETRY
|
|
32
|
+
* (`attempt > 1`) starts with no `lastHeartbeatDetails` — the closest runtime
|
|
33
|
+
* proxy for the resumable-batch footgun. We cannot distinguish "the prior attempt
|
|
34
|
+
* never heartbeated" (benign) from "the heartbeat was discarded by a process
|
|
35
|
+
* restart" (the dangerous case): the distinguishing fact is the wiped in-memory
|
|
36
|
+
* state, gone by definition. So the message names BOTH possibilities and never
|
|
37
|
+
* claims a restart happened. The gates (development, inline, attempt, missing
|
|
38
|
+
* heartbeat) are read straight off the code below; two facts are NOT derivable
|
|
39
|
+
* from it:
|
|
40
|
+
*
|
|
41
|
+
* - It fires on the speculative path too. A speculative `attempt > 1` that later
|
|
42
|
+
* rolls back still ran twice and still lost any resume payload, so the footgun
|
|
43
|
+
* is real regardless — letting it warn is the deliberate, honest choice.
|
|
44
|
+
* - It pairs with {@link clearLastHeartbeatForStep} without interference: the
|
|
45
|
+
* clear fires only on SUCCESS (a step that never retries) and this reads
|
|
46
|
+
* `undefined` only on a RETRY, and a cleared step is a completed step that by
|
|
47
|
+
* definition will not be retried.
|
|
48
|
+
*
|
|
49
|
+
* The inline gate keys on `!activityWorkerDispatcher` because dispatch is
|
|
50
|
+
* engine-wide today; the heartbeat cache is only ever written on the inline path,
|
|
51
|
+
* so whenever a dispatcher exists the cache is structurally empty and the gate is
|
|
52
|
+
* required to suppress a false warning on every worker retry. A future per-activity
|
|
53
|
+
* routing model would need this gate to key on the resolved per-dispatch mode
|
|
54
|
+
* instead.
|
|
55
|
+
*/
|
|
56
|
+
export declare function warnIfRetryMissingHeartbeat(internals: EngineInternals, workflowId: string, step: number, attempt: number): void;
|
|
57
|
+
/**
|
|
58
|
+
* Build the {@link ActivityContext} handed to an inline activity function. The
|
|
59
|
+
* signal comes from the per-workflow AbortController (so workflow cancellation
|
|
60
|
+
* aborts it); `lastHeartbeatDetails` and `heartbeat` are wired to the per-step
|
|
61
|
+
* tracking above; `completeAsync` is supplied by the caller (it owns the
|
|
62
|
+
* async-completion token machinery).
|
|
63
|
+
*/
|
|
64
|
+
export declare function buildActivityContext(internals: EngineInternals, workflowId: string, step: number, signal: AbortSignal, completeAsync: () => never): ActivityContext;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { DevelopmentWarningEvent } from "../events.js";
|
|
2
|
+
export function recordLastHeartbeatForStep(internals, workflowId, step, details) {
|
|
3
|
+
let byStep = internals.lastHeartbeatDetailsByStep.get(workflowId);
|
|
4
|
+
if (byStep === void 0) {
|
|
5
|
+
byStep = new Map;
|
|
6
|
+
internals.lastHeartbeatDetailsByStep.set(workflowId, byStep);
|
|
7
|
+
}
|
|
8
|
+
byStep.set(step, details);
|
|
9
|
+
}
|
|
10
|
+
export function readLastHeartbeatForStep(internals, workflowId, step) {
|
|
11
|
+
return internals.lastHeartbeatDetailsByStep.get(workflowId)?.get(step);
|
|
12
|
+
}
|
|
13
|
+
export function clearLastHeartbeatForStep(internals, workflowId, step) {
|
|
14
|
+
const byStep = internals.lastHeartbeatDetailsByStep.get(workflowId);
|
|
15
|
+
if (byStep === void 0)
|
|
16
|
+
return;
|
|
17
|
+
byStep.delete(step);
|
|
18
|
+
if (byStep.size === 0)
|
|
19
|
+
internals.lastHeartbeatDetailsByStep.delete(workflowId);
|
|
20
|
+
}
|
|
21
|
+
export function warnIfRetryMissingHeartbeat(internals, workflowId, step, attempt) {
|
|
22
|
+
if (!internals.options.development)
|
|
23
|
+
return;
|
|
24
|
+
if (internals.activityWorkerDispatcher)
|
|
25
|
+
return;
|
|
26
|
+
if (attempt <= 1)
|
|
27
|
+
return;
|
|
28
|
+
if (readLastHeartbeatForStep(internals, workflowId, step) !== void 0)
|
|
29
|
+
return;
|
|
30
|
+
internals.engine.dispatchEvent(new DevelopmentWarningEvent(workflowId, `Activity retry (attempt ${attempt}) at step ${step} has no lastHeartbeatDetails. Either the previous attempt never recorded heartbeat details (it never called heartbeat(), or called it with no details), or the engine process restarted and discarded the in-memory heartbeat (it is not durable). The resumable-batch pattern only resumes across in-process retries; design the activity to restart cleanly when lastHeartbeatDetails is undefined.`, [`step.${step}.lastHeartbeatDetails`]));
|
|
31
|
+
}
|
|
32
|
+
export function buildActivityContext(internals, workflowId, step, signal, completeAsync) {
|
|
33
|
+
return {
|
|
34
|
+
signal,
|
|
35
|
+
lastHeartbeatDetails: readLastHeartbeatForStep(internals, workflowId, step),
|
|
36
|
+
heartbeat: (details) => {
|
|
37
|
+
internals.heartbeatDetails.set(workflowId, details);
|
|
38
|
+
recordLastHeartbeatForStep(internals, workflowId, step, details);
|
|
39
|
+
},
|
|
40
|
+
completeAsync
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { ContextOperationRequest } from '../context.ts';
|
|
2
|
+
import type { EngineInternals } from './internals.ts';
|
|
3
|
+
type ActivityOperation = Extract<ContextOperationRequest, {
|
|
4
|
+
type: 'activity';
|
|
5
|
+
}>;
|
|
6
|
+
/**
|
|
7
|
+
* Resolve the per-attempt `timeout` setup for an activity attempt (#494).
|
|
8
|
+
*
|
|
9
|
+
* The cap is INLINE-only: worker-mode per-attempt bounds are governed by
|
|
10
|
+
* `visibilityTimeout`, and racing the engine's await against a deadline while a
|
|
11
|
+
* remote worker keeps running would orphan its result and risk double-execution on
|
|
12
|
+
* the next visibility-timeout re-dispatch. When a cap is configured, a fresh
|
|
13
|
+
* per-attempt `AbortController` drives cooperative cancellation; its signal is
|
|
14
|
+
* composited with the workflow-wide signal so the activity's `ctx.signal` aborts on
|
|
15
|
+
* EITHER workflow cancellation OR a per-attempt timeout — without the timeout
|
|
16
|
+
* reaching back to cancel the whole workflow (which would also poison the next
|
|
17
|
+
* retry's signal).
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolvePerAttemptTimeout(internals: EngineInternals, workflowId: string, operation: ActivityOperation): {
|
|
20
|
+
perAttemptTimeoutMs: number | undefined;
|
|
21
|
+
attemptAbortController: AbortController | undefined;
|
|
22
|
+
activitySignal: AbortSignal;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Bound a single inline activity attempt by its per-attempt `timeout` (#494).
|
|
26
|
+
*
|
|
27
|
+
* When `timeoutMs` is set and the attempt does not settle first, the returned
|
|
28
|
+
* promise rejects with {@link ActivityPerAttemptTimeoutError} and the per-attempt
|
|
29
|
+
* `AbortController` is aborted with that same error — so the activity's composite
|
|
30
|
+
* `ctx.signal` flips, letting a cooperating activity stop promptly. Weft cannot
|
|
31
|
+
* forcibly preempt the activity function: a non-cooperating activity keeps running
|
|
32
|
+
* in the background until it returns; only the workflow stops awaiting it. The
|
|
33
|
+
* abandoned invocation's eventual settlement is swallowed so it never surfaces as
|
|
34
|
+
* an unhandled rejection after the race has moved on. The timed-out rejection
|
|
35
|
+
* flows through the normal retry path, so a retry policy gets a fresh attempt with
|
|
36
|
+
* a fresh cap (and a fresh per-attempt controller).
|
|
37
|
+
*
|
|
38
|
+
* Returns the invocation unchanged (no timer armed) when no cap is configured.
|
|
39
|
+
*/
|
|
40
|
+
export declare function withPerAttemptTimeout(invocation: unknown, timeoutMs: number | undefined, activityName: string, attempt: number, attemptAbortController: AbortController | undefined): Promise<unknown>;
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ActivityPerAttemptTimeoutError,
|
|
3
|
+
parsePerAttemptTimeoutMs
|
|
4
|
+
} from "../context/activity-schedule-to-close.js";
|
|
5
|
+
export function resolvePerAttemptTimeout(internals, workflowId, operation) {
|
|
6
|
+
const workflowAbortController = internals.inlineStrategy?.getAbortController(workflowId), perAttemptTimeoutMs = internals.activityWorkerDispatcher ? void 0 : parsePerAttemptTimeoutMs(operation.options?.timeout), attemptAbortController = perAttemptTimeoutMs === void 0 ? void 0 : new AbortController, activitySignal = composeActivitySignal(workflowAbortController?.signal, attemptAbortController?.signal);
|
|
7
|
+
return { perAttemptTimeoutMs, attemptAbortController, activitySignal };
|
|
8
|
+
}
|
|
9
|
+
function composeActivitySignal(workflowSignal, attemptSignal) {
|
|
10
|
+
const signals = [workflowSignal, attemptSignal].filter((signal) => signal !== void 0), [first] = signals;
|
|
11
|
+
if (first === void 0)
|
|
12
|
+
return new AbortController().signal;
|
|
13
|
+
if (signals.length === 1)
|
|
14
|
+
return first;
|
|
15
|
+
return AbortSignal.any(signals);
|
|
16
|
+
}
|
|
17
|
+
export async function withPerAttemptTimeout(invocation, timeoutMs, activityName, attempt, attemptAbortController) {
|
|
18
|
+
if (timeoutMs === void 0)
|
|
19
|
+
return invocation;
|
|
20
|
+
const activityPromise = Promise.resolve(invocation);
|
|
21
|
+
activityPromise.catch(() => {});
|
|
22
|
+
let timer;
|
|
23
|
+
const deadline = new Promise((_resolve, reject) => {
|
|
24
|
+
timer = setTimeout(() => {
|
|
25
|
+
const error = new ActivityPerAttemptTimeoutError(activityName, attempt, timeoutMs);
|
|
26
|
+
reject(error);
|
|
27
|
+
attemptAbortController?.abort(error);
|
|
28
|
+
}, timeoutMs);
|
|
29
|
+
});
|
|
30
|
+
try {
|
|
31
|
+
return await Promise.race([activityPromise, deadline]);
|
|
32
|
+
} finally {
|
|
33
|
+
if (timer !== void 0)
|
|
34
|
+
clearTimeout(timer);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -101,6 +101,7 @@ export declare function resolveStartedActivityReconciliationRecord(internals: En
|
|
|
101
101
|
completedResult: unknown;
|
|
102
102
|
}>;
|
|
103
103
|
export declare function writeActivityReconciliationTransition(storage: Storage, reference: ActivityReconciliationReference, expectedRecord: ActivityReconciliationRecord, nextRecord: ActivityReconciliationRecord): Promise<void>;
|
|
104
|
+
export declare function stageActivityReconciliationTransitionWithAtomicWorkflowCommit(internals: EngineInternals, workflowId: string, reference: ActivityReconciliationReference, expectedRecord: ActivityReconciliationRecord, nextRecord: ActivityReconciliationRecord): void;
|
|
104
105
|
export declare function normalizePreDispatchVerificationResult(result: ActivityVerificationResult): 'not-completed' | 'completed-result-unavailable' | 'indeterminate' | {
|
|
105
106
|
result: unknown;
|
|
106
107
|
};
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
import { decode, encode } from "../codec.js";
|
|
7
7
|
import { assertPayloadWithinLimit } from "../payload-size.js";
|
|
8
8
|
import { WeftError } from "../weft-error.js";
|
|
9
|
+
import { stageAtomicWorkflowCommitSideEffects } from "./checkpoint-side-effects.js";
|
|
9
10
|
|
|
10
11
|
export class ActivityReconciliationCapabilityError extends WeftError {
|
|
11
12
|
constructor() {
|
|
@@ -95,9 +96,19 @@ export async function resolveStartedActivityReconciliationRecord(internals, work
|
|
|
95
96
|
return { completedResult: normalized.result };
|
|
96
97
|
}
|
|
97
98
|
export async function writeActivityReconciliationTransition(storage, reference, expectedRecord, nextRecord) {
|
|
98
|
-
|
|
99
|
+
const sideEffects = buildActivityReconciliationTransitionSideEffects(reference, expectedRecord, nextRecord);
|
|
100
|
+
if (!await storageConditionalBatch(storage, sideEffects.conditions, sideEffects.operations))
|
|
99
101
|
throw new ActivityReconciliationConflictError("Activity reconciliation completion lost compare-and-set ownership.");
|
|
100
102
|
}
|
|
103
|
+
export function stageActivityReconciliationTransitionWithAtomicWorkflowCommit(internals, workflowId, reference, expectedRecord, nextRecord) {
|
|
104
|
+
stageAtomicWorkflowCommitSideEffects(internals, workflowId, buildActivityReconciliationTransitionSideEffects(reference, expectedRecord, nextRecord));
|
|
105
|
+
}
|
|
106
|
+
function buildActivityReconciliationTransitionSideEffects(reference, expectedRecord, nextRecord) {
|
|
107
|
+
return {
|
|
108
|
+
conditions: [{ key: reference.key, expectedValue: encode(expectedRecord) }],
|
|
109
|
+
operations: [{ type: "put", key: reference.key, value: encode(nextRecord) }]
|
|
110
|
+
};
|
|
111
|
+
}
|
|
101
112
|
export function normalizePreDispatchVerificationResult(result) {
|
|
102
113
|
if (result === "not-completed")
|
|
103
114
|
return "not-completed";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ContextOperationRequest } from '../context.ts';
|
|
2
|
+
import type { EngineInternals } from './internals.ts';
|
|
3
|
+
import type { ActivityFunctionWithMetadata } from './operations-activity.ts';
|
|
4
|
+
type ActivityOperation = Extract<ContextOperationRequest, {
|
|
5
|
+
type: 'activity';
|
|
6
|
+
}>;
|
|
7
|
+
/**
|
|
8
|
+
* Resolve the activity callable along with its attached metadata (compensation,
|
|
9
|
+
* verification). Returns `undefined` when no registry and no `operation.fn`
|
|
10
|
+
* resolve the name — the metadata path treats a miss as advisory rather than
|
|
11
|
+
* fatal.
|
|
12
|
+
*/
|
|
13
|
+
export declare function getActivityFunctionWithMetadata(internals: EngineInternals, workflowId: string, operation: ActivityOperation): ActivityFunctionWithMetadata | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Resolve the activity function for a given operation. Uses the same
|
|
16
|
+
* per-workflow-first-then-global ordering as `getActivityFunctionWithMetadata`.
|
|
17
|
+
* For inline-mode callers that pass an `operation.fn` directly, the registries
|
|
18
|
+
* are still consulted first so a workflow's locally-scoped activity wins over
|
|
19
|
+
* the bare callable. Throws `ActivityResolutionError` when neither path
|
|
20
|
+
* resolves.
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveActivityFunction(internals: EngineInternals, workflowId: string, operation: ActivityOperation): (...arguments_: unknown[]) => unknown;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ActivityResolutionError } from "./errors.js";
|
|
2
|
+
function resolveActivityViaRegistries(internals, workflowId, activityName) {
|
|
3
|
+
const workflowType = internals.workflowTypeByWorkflowId.get(workflowId);
|
|
4
|
+
if (workflowType !== void 0) {
|
|
5
|
+
const perWorkflow = internals.activityRegistriesByWorkflow.get(workflowType);
|
|
6
|
+
if (perWorkflow !== void 0) {
|
|
7
|
+
const perWorkflowFn = perWorkflow.resolve(activityName);
|
|
8
|
+
if (perWorkflowFn)
|
|
9
|
+
return { fn: perWorkflowFn, workflowType };
|
|
10
|
+
}
|
|
11
|
+
const globalFn = internals.activityRegistry.resolve(activityName);
|
|
12
|
+
if (globalFn)
|
|
13
|
+
return { fn: globalFn, workflowType };
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const globalFn = internals.activityRegistry.resolve(activityName);
|
|
17
|
+
if (globalFn)
|
|
18
|
+
return { fn: globalFn, workflowType: "<unknown>" };
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
export function getActivityFunctionWithMetadata(internals, workflowId, operation) {
|
|
22
|
+
const resolved = resolveActivityViaRegistries(internals, workflowId, operation.activityName);
|
|
23
|
+
if (resolved)
|
|
24
|
+
return resolved.fn;
|
|
25
|
+
if (typeof operation.fn === "function")
|
|
26
|
+
return operation.fn;
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
export function resolveActivityFunction(internals, workflowId, operation) {
|
|
30
|
+
const resolved = resolveActivityViaRegistries(internals, workflowId, operation.activityName);
|
|
31
|
+
if (resolved)
|
|
32
|
+
return resolved.fn;
|
|
33
|
+
if (operation.fn)
|
|
34
|
+
return operation.fn;
|
|
35
|
+
const workflowType = internals.workflowTypeByWorkflowId.get(workflowId) ?? "<unknown>";
|
|
36
|
+
throw new ActivityResolutionError(workflowType, operation.activityName);
|
|
37
|
+
}
|
|
@@ -5,12 +5,16 @@ import {
|
|
|
5
5
|
MAX_AGGREGATE_DISTINCT_KEYS,
|
|
6
6
|
normalizeAggregateOptions
|
|
7
7
|
} from "../aggregate-validation.js";
|
|
8
|
-
import { decode } from "../codec.js";
|
|
9
8
|
import { normalizeListFilter } from "../list-filter-validation.js";
|
|
10
9
|
import { WeftError } from "../weft-error.js";
|
|
11
10
|
import { normalizeWorkflowTags } from "../workflow-tags.js";
|
|
11
|
+
import { CONSTRAINED_ID_CHUNK_SIZE } from "./candidate-read-batching.js";
|
|
12
12
|
import { resolveListCandidateIds } from "./list-candidate-resolution.js";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
readSearchAttributesForFilter,
|
|
15
|
+
readSearchAttributesForStates
|
|
16
|
+
} from "./search-attribute-records.js";
|
|
17
|
+
import { decodeSearchAttributeRecord, matchesListFilter } from "./state-utilities.js";
|
|
14
18
|
import { decodeWorkflowState } from "./validation.js";
|
|
15
19
|
import { MAX_LIST_SCAN_ROWS, WorkflowListScanCapExceededError } from "./workflow-indexes.js";
|
|
16
20
|
import { isTopLevelWorkflowStateKey } from "./workflow-state-stream.js";
|
|
@@ -27,19 +31,6 @@ const ATTRIBUTE_VALUE_TO_KEY = (value) => {
|
|
|
27
31
|
return value.join(",");
|
|
28
32
|
return String(value);
|
|
29
33
|
};
|
|
30
|
-
async function resolveDimensionKey(internals, state, groupBy) {
|
|
31
|
-
if (groupBy === "status")
|
|
32
|
-
return state.status;
|
|
33
|
-
if (groupBy === "type")
|
|
34
|
-
return state.type;
|
|
35
|
-
if (groupBy === "failureCategory")
|
|
36
|
-
return state.failureCategory ?? null;
|
|
37
|
-
const attributeBytes = await internals.storage.get(KEYS.attribute(state.id));
|
|
38
|
-
if (!attributeBytes)
|
|
39
|
-
return null;
|
|
40
|
-
const attributes = decode(attributeBytes);
|
|
41
|
-
return ATTRIBUTE_VALUE_TO_KEY(attributes[groupBy.attribute]);
|
|
42
|
-
}
|
|
43
34
|
|
|
44
35
|
export class UnknownAggregateAttributeError extends WeftError {
|
|
45
36
|
attribute;
|
|
@@ -72,8 +63,8 @@ function validateAggregateInputs(internals, filter, options, executionOptions) {
|
|
|
72
63
|
distinctKeyCap: executionOptions.distinctKeyCap ?? MAX_AGGREGATE_DISTINCT_KEYS
|
|
73
64
|
};
|
|
74
65
|
}
|
|
75
|
-
|
|
76
|
-
const
|
|
66
|
+
function accumulateAggregateKey(key, distinctKeyCap, accumulator) {
|
|
67
|
+
const current = accumulator.counts.get(key);
|
|
77
68
|
if (current === void 0) {
|
|
78
69
|
if (accumulator.counts.size >= distinctKeyCap)
|
|
79
70
|
throw new AggregateDistinctKeyCapExceededError(distinctKeyCap);
|
|
@@ -82,32 +73,77 @@ async function accumulateAggregateState(internals, state, groupBy, distinctKeyCa
|
|
|
82
73
|
accumulator.counts.set(key, current + 1);
|
|
83
74
|
accumulator.total += 1;
|
|
84
75
|
}
|
|
76
|
+
async function resolveDimensionKeys(internals, states, groupBy, searchAttributesByWorkflowId = new Map) {
|
|
77
|
+
if (groupBy === "status")
|
|
78
|
+
return states.map((state) => state.status);
|
|
79
|
+
if (groupBy === "type")
|
|
80
|
+
return states.map((state) => state.type);
|
|
81
|
+
if (groupBy === "failureCategory")
|
|
82
|
+
return states.map((state) => state.failureCategory ?? null);
|
|
83
|
+
return resolveAttributeDimensionKeys(internals, states, groupBy, searchAttributesByWorkflowId);
|
|
84
|
+
}
|
|
85
|
+
async function resolveAttributeDimensionKeys(internals, states, groupBy, searchAttributesByWorkflowId) {
|
|
86
|
+
const keys = [];
|
|
87
|
+
for (let start = 0;start < states.length; start += CONSTRAINED_ID_CHUNK_SIZE) {
|
|
88
|
+
const stateChunk = states.slice(start, start + CONSTRAINED_ID_CHUNK_SIZE), statesNeedingReads = stateChunk.filter((state) => !searchAttributesByWorkflowId.has(state.id)), attributeBytesByWorkflowId = new Map;
|
|
89
|
+
await Promise.all(statesNeedingReads.map(async (state) => {
|
|
90
|
+
attributeBytesByWorkflowId.set(state.id, await internals.storage.get(KEYS.attribute(state.id)));
|
|
91
|
+
}));
|
|
92
|
+
for (const state of stateChunk) {
|
|
93
|
+
const attributes = searchAttributesByWorkflowId.has(state.id) ? searchAttributesByWorkflowId.get(state.id) ?? null : decodeSearchAttributeRecord(attributeBytesByWorkflowId.get(state.id) ?? null);
|
|
94
|
+
if (attributes === null) {
|
|
95
|
+
keys.push(null);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
keys.push(ATTRIBUTE_VALUE_TO_KEY(attributes[groupBy.attribute]));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return keys;
|
|
102
|
+
}
|
|
103
|
+
async function accumulateAggregateStates(internals, states, groupBy, distinctKeyCap, accumulator, searchAttributesByWorkflowId) {
|
|
104
|
+
const dimensionKeys = await resolveDimensionKeys(internals, states, groupBy, searchAttributesByWorkflowId);
|
|
105
|
+
for (const key of dimensionKeys)
|
|
106
|
+
accumulateAggregateKey(key, distinctKeyCap, accumulator);
|
|
107
|
+
}
|
|
85
108
|
async function accumulateFromConstrainedIds(internals, constrainedIds, normalizedFilter, normalizedTagFilters, groupBy, distinctKeyCap, accumulator) {
|
|
86
|
-
|
|
109
|
+
const orderedIds = [...constrainedIds];
|
|
110
|
+
if (orderedIds.length > MAX_LIST_SCAN_ROWS)
|
|
87
111
|
throw new WorkflowListScanCapExceededError(MAX_LIST_SCAN_ROWS);
|
|
88
|
-
for (
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
112
|
+
for (let start = 0;start < orderedIds.length; start += CONSTRAINED_ID_CHUNK_SIZE) {
|
|
113
|
+
const idChunk = orderedIds.slice(start, start + CONSTRAINED_ID_CHUNK_SIZE), stateBytesChunk = await Promise.all(idChunk.map((workflowId) => internals.storage.get(KEYS.workflow(workflowId)))), searchAttributesByWorkflowId = await readSearchAttributesForStates(internals, stateBytesChunk, normalizedFilter), matchingStates = [];
|
|
114
|
+
for (const stateBytes of stateBytesChunk) {
|
|
115
|
+
if (!stateBytes)
|
|
116
|
+
continue;
|
|
117
|
+
const state = decodeWorkflowState(stateBytes);
|
|
118
|
+
if (!matchesListFilter(state, normalizedFilter, constrainedIds, normalizedTagFilters, searchAttributesByWorkflowId.get(state.id) ?? null))
|
|
119
|
+
continue;
|
|
120
|
+
matchingStates.push(state);
|
|
121
|
+
}
|
|
122
|
+
await accumulateAggregateStates(internals, matchingStates, groupBy, distinctKeyCap, accumulator, searchAttributesByWorkflowId);
|
|
96
123
|
}
|
|
97
124
|
}
|
|
98
125
|
async function accumulateFromFullScan(internals, normalizedFilter, normalizedTagFilters, groupBy, distinctKeyCap, accumulator) {
|
|
99
|
-
let scanned = 0;
|
|
126
|
+
let scanned = 0, matchingStates = [], matchingSearchAttributesByWorkflowId = new Map;
|
|
100
127
|
for await (const [storageKey, value] of internals.storage.scan("wf:")) {
|
|
101
128
|
if (!isTopLevelWorkflowStateKey(storageKey))
|
|
102
129
|
continue;
|
|
103
130
|
scanned += 1;
|
|
104
131
|
if (scanned > MAX_LIST_SCAN_ROWS)
|
|
105
132
|
throw new WorkflowListScanCapExceededError(MAX_LIST_SCAN_ROWS);
|
|
106
|
-
const state = decodeWorkflowState(value);
|
|
107
|
-
if (!matchesListFilter(state, normalizedFilter, null, normalizedTagFilters))
|
|
133
|
+
const state = decodeWorkflowState(value), searchAttributes = await readSearchAttributesForFilter(internals, state.id, normalizedFilter);
|
|
134
|
+
if (!matchesListFilter(state, normalizedFilter, null, normalizedTagFilters, searchAttributes))
|
|
108
135
|
continue;
|
|
109
|
-
|
|
136
|
+
matchingStates.push(state);
|
|
137
|
+
if (searchAttributes !== null)
|
|
138
|
+
matchingSearchAttributesByWorkflowId.set(state.id, searchAttributes);
|
|
139
|
+
if (matchingStates.length === CONSTRAINED_ID_CHUNK_SIZE) {
|
|
140
|
+
await accumulateAggregateStates(internals, matchingStates, groupBy, distinctKeyCap, accumulator, matchingSearchAttributesByWorkflowId);
|
|
141
|
+
matchingStates = [];
|
|
142
|
+
matchingSearchAttributesByWorkflowId = new Map;
|
|
143
|
+
}
|
|
110
144
|
}
|
|
145
|
+
if (matchingStates.length > 0)
|
|
146
|
+
await accumulateAggregateStates(internals, matchingStates, groupBy, distinctKeyCap, accumulator, matchingSearchAttributesByWorkflowId);
|
|
111
147
|
}
|
|
112
148
|
function finalizeAggregateResult(accumulator, requestedLimit) {
|
|
113
149
|
const sortedGroups = [...accumulator.counts.entries()].map(([groupKey, count]) => ({ key: groupKey, count })).toSorted((left, right) => {
|
|
@@ -22,7 +22,10 @@
|
|
|
22
22
|
* across replay. After an engine restart, `recoverAll()` replays the workflow
|
|
23
23
|
* from its checkpoint; the deferred activity re-runs, re-defers, and produces
|
|
24
24
|
* the *same* token. A callback that arrives after the crash therefore still
|
|
25
|
-
* resolves the correct activity.
|
|
25
|
+
* resolves the correct activity. If that callback races `recoverAll()` and
|
|
26
|
+
* arrives after token recovery but before replay has adopted the workflow
|
|
27
|
+
* generator, the engine buffers the completion or failure outcome and drains it
|
|
28
|
+
* when replay reaches the same deterministic token.
|
|
26
29
|
*
|
|
27
30
|
* Internal-only. Imported from `src/core/engine/**` and the `ActivityContext`
|
|
28
31
|
* construction path.
|
|
@@ -30,6 +33,12 @@
|
|
|
30
33
|
import type { OperationOutcome } from '../types.ts';
|
|
31
34
|
import { WeftError } from '../weft-error.ts';
|
|
32
35
|
import type { EngineInternals } from './internals.ts';
|
|
36
|
+
type AsyncActivityResolutionCallbacks = {
|
|
37
|
+
feedOperationResult: (workflowId: string, outcome: OperationOutcome, originalReason?: {
|
|
38
|
+
value: unknown;
|
|
39
|
+
}) => void;
|
|
40
|
+
finalizeTimeline: (workflowId: string, status: 'completed' | 'failed', output: unknown) => void;
|
|
41
|
+
};
|
|
33
42
|
/**
|
|
34
43
|
* Per-workflow prefix for all async-activity storage keys. Used by cleanup and
|
|
35
44
|
* purge paths that need to sweep every async-activity record for a workflow
|
|
@@ -80,6 +89,15 @@ export type PendingAsyncActivity = {
|
|
|
80
89
|
readonly attempt: number;
|
|
81
90
|
readonly createdAt: number;
|
|
82
91
|
};
|
|
92
|
+
export type PendingAsyncActivityResolution = {
|
|
93
|
+
readonly token: string;
|
|
94
|
+
readonly outcome: OperationOutcome;
|
|
95
|
+
readonly originalReason?: {
|
|
96
|
+
value: unknown;
|
|
97
|
+
};
|
|
98
|
+
readonly timelineStatus: 'completed' | 'failed';
|
|
99
|
+
readonly timelineOutput: unknown;
|
|
100
|
+
};
|
|
83
101
|
/**
|
|
84
102
|
* Derive the durable, deterministic task token for an async activity.
|
|
85
103
|
*
|
|
@@ -106,7 +124,7 @@ export declare function registerPendingAsyncActivity(internals: EngineInternals,
|
|
|
106
124
|
* out-of-band completion resumes it. Keeps the operation-pipeline catch site a
|
|
107
125
|
* one-liner.
|
|
108
126
|
*/
|
|
109
|
-
export declare function parkDeferredAsyncActivity(internals: EngineInternals, deferral: AsyncActivityDeferral, details: Omit<PendingAsyncActivity, 'token' | 'createdAt'
|
|
127
|
+
export declare function parkDeferredAsyncActivity(internals: EngineInternals, deferral: AsyncActivityDeferral, details: Omit<PendingAsyncActivity, 'token' | 'createdAt'>, callbacks: AsyncActivityResolutionCallbacks): Promise<never>;
|
|
110
128
|
/**
|
|
111
129
|
* Reload pending async-activity records from storage into memory. Called by
|
|
112
130
|
* `recoverAll()` so a token minted before a crash is resolvable again — even
|
|
@@ -117,7 +135,7 @@ export declare function recoverPendingAsyncActivities(internals: EngineInternals
|
|
|
117
135
|
* Complete a deferred activity out-of-band with `result`, resuming the parked
|
|
118
136
|
* workflow as though the activity had returned `result` inline.
|
|
119
137
|
*/
|
|
120
|
-
export declare function completeAsyncActivity(internals: EngineInternals, token: string, result: unknown,
|
|
138
|
+
export declare function completeAsyncActivity(internals: EngineInternals, token: string, result: unknown, callbacks: AsyncActivityResolutionCallbacks): Promise<void>;
|
|
121
139
|
/**
|
|
122
140
|
* Drive a generator that may yield promises — the workflow interceptor's
|
|
123
141
|
* `activity` hook returns such a generator. Forwards rejections into the
|
|
@@ -136,6 +154,5 @@ export declare function driveWorkflowInterceptorGenerator(generator: Generator<u
|
|
|
136
154
|
* that threw — so the workflow's own try/catch and any configured retry policy
|
|
137
155
|
* apply unchanged.
|
|
138
156
|
*/
|
|
139
|
-
export declare function failAsyncActivity(internals: EngineInternals, token: string, error: unknown,
|
|
140
|
-
|
|
141
|
-
}) => void, finalizeTimeline: (workflowId: string, status: 'completed' | 'failed', output: unknown) => void): Promise<void>;
|
|
157
|
+
export declare function failAsyncActivity(internals: EngineInternals, token: string, error: unknown, callbacks: AsyncActivityResolutionCallbacks): Promise<void>;
|
|
158
|
+
export {};
|
|
@@ -53,7 +53,12 @@ export async function registerPendingAsyncActivity(internals, pending) {
|
|
|
53
53
|
if (!alreadyRegistered)
|
|
54
54
|
internals.engine.dispatchEvent(new ActivityAsyncPendingEvent(pending.token, pending.operationId, pending.workflowId, pending.activityName, pending.attempt));
|
|
55
55
|
}
|
|
56
|
-
export async function parkDeferredAsyncActivity(internals, deferral, details) {
|
|
56
|
+
export async function parkDeferredAsyncActivity(internals, deferral, details, callbacks) {
|
|
57
|
+
const queuedResolution = takePendingAsyncActivityResolution(internals, details.workflowId, deferral.token);
|
|
58
|
+
if (queuedResolution !== void 0) {
|
|
59
|
+
deliverPendingAsyncActivityResolution(details.workflowId, queuedResolution, callbacks);
|
|
60
|
+
return new Promise(() => {});
|
|
61
|
+
}
|
|
57
62
|
await registerPendingAsyncActivity(internals, {
|
|
58
63
|
token: deferral.token,
|
|
59
64
|
createdAt: internals.options.getNow(),
|
|
@@ -90,14 +95,52 @@ async function consumePendingAsyncActivity(internals, token) {
|
|
|
90
95
|
}
|
|
91
96
|
return pending;
|
|
92
97
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
98
|
+
function shouldBufferPendingAsyncActivityResolution(internals, workflowId) {
|
|
99
|
+
return internals.inlineStrategy !== null && !internals.inlineStrategy.hasGenerator(workflowId);
|
|
100
|
+
}
|
|
101
|
+
function queuePendingAsyncActivityResolution(internals, workflowId, resolution) {
|
|
102
|
+
internals.pendingAsyncActivityResolutions ??= new Map;
|
|
103
|
+
const queued = internals.pendingAsyncActivityResolutions.get(workflowId) ?? [];
|
|
104
|
+
queued.push(resolution);
|
|
105
|
+
internals.pendingAsyncActivityResolutions.set(workflowId, queued);
|
|
106
|
+
}
|
|
107
|
+
function takePendingAsyncActivityResolution(internals, workflowId, token) {
|
|
108
|
+
internals.pendingAsyncActivityResolutions ??= new Map;
|
|
109
|
+
const queued = internals.pendingAsyncActivityResolutions.get(workflowId);
|
|
110
|
+
if (queued === void 0)
|
|
111
|
+
return;
|
|
112
|
+
const index = queued.findIndex((resolution) => resolution.token === token);
|
|
113
|
+
if (index === -1)
|
|
114
|
+
return;
|
|
115
|
+
const resolution = queued[index];
|
|
116
|
+
if (resolution === void 0)
|
|
117
|
+
return;
|
|
118
|
+
queued.splice(index, 1);
|
|
119
|
+
if (queued.length === 0)
|
|
120
|
+
internals.pendingAsyncActivityResolutions.delete(workflowId);
|
|
121
|
+
return resolution;
|
|
122
|
+
}
|
|
123
|
+
function deliverPendingAsyncActivityResolution(workflowId, resolution, callbacks) {
|
|
124
|
+
callbacks.finalizeTimeline(workflowId, resolution.timelineStatus, resolution.timelineOutput);
|
|
125
|
+
callbacks.feedOperationResult(workflowId, resolution.outcome, resolution.originalReason);
|
|
126
|
+
}
|
|
127
|
+
async function resolvePendingAsyncActivity(internals, token, outcome, callbacks, originalReason) {
|
|
128
|
+
const pending = await consumePendingAsyncActivity(internals, token), timelineOutput = outcome.status === "completed" ? outcome.value : outcome.error, resolution = {
|
|
129
|
+
token,
|
|
130
|
+
outcome,
|
|
131
|
+
timelineStatus: outcome.status,
|
|
132
|
+
timelineOutput,
|
|
133
|
+
...originalReason !== void 0 ? { originalReason } : {}
|
|
134
|
+
};
|
|
135
|
+
if (shouldBufferPendingAsyncActivityResolution(internals, pending.workflowId)) {
|
|
136
|
+
queuePendingAsyncActivityResolution(internals, pending.workflowId, resolution);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
deliverPendingAsyncActivityResolution(pending.workflowId, resolution, callbacks);
|
|
97
140
|
}
|
|
98
|
-
export async function completeAsyncActivity(internals, token, result,
|
|
141
|
+
export async function completeAsyncActivity(internals, token, result, callbacks) {
|
|
99
142
|
assertPayloadWithinLimit(result, internals.options.payloadSizePolicy.maxBytes, "activity result");
|
|
100
|
-
await resolvePendingAsyncActivity(internals, token, { status: "completed", value: result },
|
|
143
|
+
await resolvePendingAsyncActivity(internals, token, { status: "completed", value: result }, callbacks);
|
|
101
144
|
}
|
|
102
145
|
export async function driveWorkflowInterceptorGenerator(generator) {
|
|
103
146
|
let current = generator.next();
|
|
@@ -117,15 +160,13 @@ export async function driveWorkflowInterceptorGenerator(generator) {
|
|
|
117
160
|
}
|
|
118
161
|
return current.value;
|
|
119
162
|
}
|
|
120
|
-
export async function failAsyncActivity(internals, token, error,
|
|
163
|
+
export async function failAsyncActivity(internals, token, error, callbacks) {
|
|
121
164
|
const message = error instanceof Error ? error.message : String(error), errorName = error instanceof Error ? error.name : void 0;
|
|
122
165
|
assertPayloadWithinLimit({ message, name: errorName }, internals.options.payloadSizePolicy.maxBytes, "activity result");
|
|
123
|
-
|
|
124
|
-
finalizeTimeline(pending.workflowId, "failed", message);
|
|
125
|
-
feedOperationResult(pending.workflowId, {
|
|
166
|
+
await resolvePendingAsyncActivity(internals, token, {
|
|
126
167
|
status: "failed",
|
|
127
168
|
error: message,
|
|
128
169
|
...error instanceof Error ? { errorName: error.name } : {},
|
|
129
170
|
failureCategory: "application"
|
|
130
|
-
}, { value: error });
|
|
171
|
+
}, callbacks, { value: error });
|
|
131
172
|
}
|
|
@@ -9,7 +9,10 @@ import {
|
|
|
9
9
|
import { assertWorkflowTagCount, coerceStartWorkflowTags } from "../start-workflow-validation.js";
|
|
10
10
|
import { buildWorkflowTagIndexOperations, normalizeWorkflowTags } from "../workflow-tags.js";
|
|
11
11
|
import { WorkflowNotFoundError } from "./errors.js";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
commitFencedWorkflowStateOperations,
|
|
14
|
+
runSerializedWorkflowStateWrite
|
|
15
|
+
} from "./storage-io.js";
|
|
13
16
|
import {
|
|
14
17
|
decodeWorkflowState,
|
|
15
18
|
isTerminalWorkflowStatus,
|
|
@@ -73,12 +76,14 @@ export async function updateWorkflowState(internals, workflowId, updates, option
|
|
|
73
76
|
...updates,
|
|
74
77
|
updatedAt
|
|
75
78
|
}, additionalOperations = options.buildAdditionalOperations?.(state, updatedAt) ?? [];
|
|
76
|
-
await
|
|
79
|
+
await commitFencedWorkflowStateOperations(internals, state, [
|
|
77
80
|
...buildTerminalWorkflowIndexOperations(state, updated),
|
|
78
81
|
{ type: "put", key: KEYS.workflow(workflowId), value: encode(updated) },
|
|
79
82
|
...buildWorkflowVisibilityIndexTransition(workflowId, state, updated).batchOps,
|
|
80
83
|
...additionalOperations
|
|
81
|
-
]
|
|
84
|
+
], {
|
|
85
|
+
includePendingAtomicSideEffects: isTerminalWorkflowStatus(updated.status)
|
|
86
|
+
});
|
|
82
87
|
return {
|
|
83
88
|
previousState: state,
|
|
84
89
|
updatedAt
|
|
@@ -172,7 +177,7 @@ async function snapshotMatchingWorkflowIds(internals, filter) {
|
|
|
172
177
|
if (remainingLimit !== void 0)
|
|
173
178
|
remainingLimit -= 1;
|
|
174
179
|
if (remainingLimit === 0)
|
|
175
|
-
|
|
180
|
+
return workflowIds;
|
|
176
181
|
}
|
|
177
182
|
return workflowIds;
|
|
178
183
|
}
|