@lostgradient/weft 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -24
- package/dist/cli/conformance.js +7 -1
- package/dist/cli/generated/operation-client.generated.d.ts +28 -13
- package/dist/cli/generated/operation-client.generated.js +1 -0
- package/dist/cli/help-text.d.ts +1 -1
- package/dist/cli/help-text.js +1 -0
- package/dist/cli/operation-catalog-snapshot.d.ts +8 -0
- package/dist/cli/operation-catalog-snapshot.js +11 -0
- package/dist/cli/parse-schedule-arguments.js +3 -1
- package/dist/cli/schedule.js +2 -1
- package/dist/cli/types.d.ts +1 -0
- package/dist/cli-main.js +79 -78
- package/dist/client/handle-delegation.d.ts +3 -2
- package/dist/client/handle-delegation.js +3 -1
- package/dist/client/http-client-requests.d.ts +2 -1
- package/dist/client/http-client-requests.js +7 -0
- package/dist/client/http-client.d.ts +9 -6
- package/dist/client/http-client.js +10 -1
- package/dist/client/http-request.d.ts +11 -1
- package/dist/client/http-request.js +17 -7
- package/dist/client/index.d.ts +1 -1
- package/dist/client/interface.d.ts +61 -5
- package/dist/client/local-handles.d.ts +22 -0
- package/dist/client/local-handles.js +23 -0
- package/dist/client/local.d.ts +6 -3
- package/dist/client/local.js +12 -26
- package/dist/client/start-body.d.ts +4 -3
- package/dist/core/byte-arrays.d.ts +5 -0
- package/dist/core/byte-arrays.js +5 -0
- package/dist/core/checkpoint/lifecycle.d.ts +3 -0
- package/dist/core/checkpoint/lifecycle.js +9 -4
- package/dist/core/checkpoint/serialization.js +12 -5
- package/dist/core/codec/extension-codec.d.ts +16 -0
- package/dist/core/codec/extension-codec.js +100 -6
- package/dist/core/context/activity-retry-state.d.ts +38 -0
- package/dist/core/context/activity-retry-state.js +89 -0
- package/dist/core/context/activity-schedule-to-close.d.ts +159 -0
- package/dist/core/context/activity-schedule-to-close.js +69 -0
- package/dist/core/context/child-workflow-pipe.d.ts +5 -5
- package/dist/core/context/child-workflow-pipe.js +15 -2
- package/dist/core/context/context-presence.d.ts +19 -0
- package/dist/core/context/context-presence.js +13 -0
- package/dist/core/context/durable-operations.d.ts +25 -0
- package/dist/core/context/durable-operations.js +64 -0
- package/dist/core/context/index.d.ts +9 -5
- package/dist/core/context/index.js +17 -12
- package/dist/core/context/internals.d.ts +20 -0
- package/dist/core/context/internals.js +3 -1
- package/dist/core/context/operation-request.d.ts +35 -0
- package/dist/core/context/parallel-cache-entry.d.ts +14 -5
- package/dist/core/context/run-operation.d.ts +6 -1
- package/dist/core/context/run-operation.js +41 -87
- package/dist/core/context/session-state.js +7 -8
- package/dist/core/context/speculative-child.js +2 -0
- package/dist/core/context/types.d.ts +15 -0
- package/dist/core/context/version-patching.d.ts +8 -0
- package/dist/core/context/version-patching.js +40 -0
- package/dist/core/context/workflow-logger.d.ts +98 -0
- package/dist/core/context/workflow-logger.js +68 -0
- package/dist/core/engine/activity-heartbeat-tracking.d.ts +64 -0
- package/dist/core/engine/activity-heartbeat-tracking.js +42 -0
- package/dist/core/engine/activity-per-attempt-timeout.d.ts +46 -0
- package/dist/core/engine/activity-per-attempt-timeout.js +36 -0
- package/dist/core/engine/activity-reconciliation.d.ts +1 -0
- package/dist/core/engine/activity-reconciliation.js +12 -1
- package/dist/core/engine/activity-resolution.d.ts +23 -0
- package/dist/core/engine/activity-resolution.js +37 -0
- package/dist/core/engine/aggregate.js +66 -30
- package/dist/core/engine/async-activity-completion.d.ts +23 -6
- package/dist/core/engine/async-activity-completion.js +53 -12
- package/dist/core/engine/attributes-tags.js +9 -4
- package/dist/core/engine/bulk-operations-purge.d.ts +26 -0
- package/dist/core/engine/bulk-operations-purge.js +38 -3
- package/dist/core/engine/bulk-operations-shared.d.ts +2 -0
- package/dist/core/engine/bulk-operations-shared.js +8 -2
- package/dist/core/engine/bulk-operations.d.ts +4 -1
- package/dist/core/engine/bulk-operations.js +235 -24
- package/dist/core/engine/callback-creators-bundles.d.ts +9 -0
- package/dist/core/engine/callback-creators-bundles.js +30 -2
- package/dist/core/engine/callback-creators-core.js +6 -4
- package/dist/core/engine/callback-creators-router.js +10 -0
- package/dist/core/engine/callback-creators-schedule.d.ts +2 -2
- package/dist/core/engine/callback-creators-schedule.js +12 -8
- package/dist/core/engine/candidate-read-batching.d.ts +6 -0
- package/dist/core/engine/candidate-read-batching.js +1 -0
- package/dist/core/engine/checkpoint-io.js +61 -25
- package/dist/core/engine/checkpoint-reads.js +3 -2
- package/dist/core/engine/checkpoint-replay.d.ts +20 -0
- package/dist/core/engine/checkpoint-replay.js +242 -0
- package/dist/core/engine/checkpoint-side-effects.d.ts +23 -0
- package/dist/core/engine/checkpoint-side-effects.js +35 -0
- package/dist/core/engine/child-workflow-cancellation.d.ts +10 -0
- package/dist/core/engine/child-workflow-cancellation.js +40 -0
- package/dist/core/engine/child-workflow.js +27 -4
- package/dist/core/engine/condition-waiters.d.ts +14 -0
- package/dist/core/engine/condition-waiters.js +5 -0
- package/dist/core/engine/construction.d.ts +3 -0
- package/dist/core/engine/construction.js +21 -8
- package/dist/core/engine/coordination-branch-executors.d.ts +70 -0
- package/dist/core/engine/coordination-branch-executors.js +107 -0
- package/dist/core/engine/deferred-consume-envelope.d.ts +59 -0
- package/dist/core/engine/deferred-consume-envelope.js +14 -0
- package/dist/core/engine/disposal.js +13 -0
- package/dist/core/engine/engine-create-types.d.ts +14 -4
- package/dist/core/engine/engine-internal-types.d.ts +26 -3
- package/dist/core/engine/errors.d.ts +47 -0
- package/dist/core/engine/errors.js +20 -0
- package/dist/core/engine/event-log-compaction.d.ts +8 -0
- package/dist/core/engine/event-log-compaction.js +20 -2
- package/dist/core/engine/fenced-write.d.ts +65 -0
- package/dist/core/engine/fenced-write.js +71 -0
- package/dist/core/engine/finalizer-state.d.ts +28 -0
- package/dist/core/engine/finalizer-state.js +16 -0
- package/dist/core/engine/handles.d.ts +8 -0
- package/dist/core/engine/index.d.ts +34 -16
- package/dist/core/engine/index.js +136 -9
- package/dist/core/engine/inline-parking.js +3 -2
- package/dist/core/engine/internals.d.ts +107 -3
- package/dist/core/engine/lease-codec.d.ts +35 -0
- package/dist/core/engine/lease-codec.js +32 -0
- package/dist/core/engine/lease-deposition.d.ts +66 -0
- package/dist/core/engine/lease-deposition.js +10 -0
- package/dist/core/engine/lease-errors.d.ts +99 -0
- package/dist/core/engine/lease-errors.js +30 -0
- package/dist/core/engine/lease-manager.d.ts +114 -0
- package/dist/core/engine/lease-manager.js +135 -0
- package/dist/core/engine/lifecycle/persist.js +10 -32
- package/dist/core/engine/lifecycle/recovered-services.d.ts +8 -6
- package/dist/core/engine/lifecycle/recovered-services.js +18 -3
- package/dist/core/engine/lifecycle/resume.js +16 -9
- package/dist/core/engine/lifecycle/shared.d.ts +8 -1
- package/dist/core/engine/lifecycle/start-batch.d.ts +1 -1
- package/dist/core/engine/lifecycle/start-batch.js +2 -1
- package/dist/core/engine/lifecycle/start-commit.d.ts +9 -0
- package/dist/core/engine/lifecycle/start-commit.js +50 -8
- package/dist/core/engine/lifecycle/start-or-signal-create.d.ts +58 -0
- package/dist/core/engine/lifecycle/start-or-signal-create.js +95 -0
- package/dist/core/engine/lifecycle/start-or-signal.d.ts +3 -2
- package/dist/core/engine/lifecycle/start-or-signal.js +11 -81
- package/dist/core/engine/lifecycle/start-terminal-conflict-purge.d.ts +39 -0
- package/dist/core/engine/lifecycle/start-terminal-conflict-purge.js +28 -0
- package/dist/core/engine/lifecycle/start.d.ts +4 -4
- package/dist/core/engine/lifecycle/start.js +17 -9
- package/dist/core/engine/lifecycle/transition.js +17 -5
- package/dist/core/engine/lifecycle.d.ts +1 -1
- package/dist/core/engine/list-candidate-resolution.js +2 -2
- package/dist/core/engine/listing.js +9 -5
- package/dist/core/engine/operations-activity.d.ts +6 -13
- package/dist/core/engine/operations-activity.js +26 -53
- package/dist/core/engine/operations-coordination.d.ts +10 -0
- package/dist/core/engine/operations-coordination.js +44 -9
- package/dist/core/engine/operations-router.d.ts +6 -0
- package/dist/core/engine/operations-router.js +2 -0
- package/dist/core/engine/operations-speculate.js +6 -2
- package/dist/core/engine/operations-stream.js +12 -2
- package/dist/core/engine/operations-time.d.ts +4 -2
- package/dist/core/engine/operations-time.js +14 -2
- package/dist/core/engine/operations-wait-condition.d.ts +23 -0
- package/dist/core/engine/operations-wait-condition.js +62 -0
- package/dist/core/engine/ownership-options.d.ts +23 -0
- package/dist/core/engine/ownership-options.js +26 -0
- package/dist/core/engine/payload-size-policy.d.ts +3 -0
- package/dist/core/engine/payload-size-policy.js +4 -0
- package/dist/core/engine/pending-updates.d.ts +17 -0
- package/dist/core/engine/pending-updates.js +33 -11
- package/dist/core/engine/queries.js +1 -1
- package/dist/core/engine/registration.d.ts +1 -0
- package/dist/core/engine/registration.js +18 -3
- package/dist/core/engine/schedule-jitter.d.ts +5 -0
- package/dist/core/engine/schedule-jitter.js +10 -0
- package/dist/core/engine/schedule-run.d.ts +17 -0
- package/dist/core/engine/schedule-run.js +38 -0
- package/dist/core/engine/schedule-timer.js +81 -17
- package/dist/core/engine/schedules.d.ts +7 -4
- package/dist/core/engine/schedules.js +37 -16
- package/dist/core/engine/search-attribute-records.d.ts +4 -0
- package/dist/core/engine/search-attribute-records.js +17 -0
- package/dist/core/engine/signals.d.ts +18 -2
- package/dist/core/engine/signals.js +42 -21
- package/dist/core/engine/state-utilities.d.ts +49 -2
- package/dist/core/engine/state-utilities.js +114 -3
- package/dist/core/engine/storage-io.d.ts +16 -2
- package/dist/core/engine/storage-io.js +26 -5
- package/dist/core/engine/stream-chunk-loading.d.ts +2 -0
- package/dist/core/engine/stream-chunk-loading.js +24 -1
- package/dist/core/engine/sub-operation.js +25 -6
- package/dist/core/engine/termination/cleanup.d.ts +3 -1
- package/dist/core/engine/termination/cleanup.js +25 -1
- package/dist/core/engine/termination/complete.js +44 -6
- package/dist/core/engine/termination/finalizer-activity.d.ts +53 -0
- package/dist/core/engine/termination/finalizer-activity.js +30 -0
- package/dist/core/engine/termination/finalizer-claim.d.ts +110 -0
- package/dist/core/engine/termination/finalizer-claim.js +80 -0
- package/dist/core/engine/termination/finalizer.d.ts +48 -0
- package/dist/core/engine/termination/finalizer.js +159 -0
- package/dist/core/engine/termination/suspend.d.ts +3 -1
- package/dist/core/engine/termination.d.ts +1 -0
- package/dist/core/engine/termination.js +4 -0
- package/dist/core/engine/updates.js +5 -25
- package/dist/core/engine/validation/schedule.d.ts +2 -1
- package/dist/core/engine/validation/schedule.js +51 -2
- package/dist/core/engine/validation.js +32 -5
- package/dist/core/engine/waiting-update-response.d.ts +8 -0
- package/dist/core/engine/waiting-update-response.js +22 -0
- package/dist/core/engine/workflow-concurrency.d.ts +10 -0
- package/dist/core/engine/workflow-concurrency.js +136 -0
- package/dist/core/engine/workflow-feed.d.ts +4 -5
- package/dist/core/engine/workflow-feed.js +4 -1
- package/dist/core/engine/workflow-indexes.d.ts +9 -0
- package/dist/core/engine/workflow-indexes.js +10 -0
- package/dist/core/engine/workflow-state-stream.js +33 -13
- package/dist/core/engine/workflow-visibility-queries.d.ts +2 -2
- package/dist/core/engine-helpers.js +1 -0
- package/dist/core/events/activity-events.d.ts +43 -12
- package/dist/core/events/activity-events.js +28 -0
- package/dist/core/events/attribute-events.d.ts +2 -3
- package/dist/core/events/event-map.d.ts +18 -12
- package/dist/core/events/index.d.ts +1 -0
- package/dist/core/events/index.js +1 -0
- package/dist/core/events/schedule-events.d.ts +71 -0
- package/dist/core/events/schedule-events.js +29 -0
- package/dist/core/events/signal-events.d.ts +4 -6
- package/dist/core/events/system-events.d.ts +29 -19
- package/dist/core/events/system-events.js +26 -0
- package/dist/core/events/update-events.d.ts +6 -8
- package/dist/core/events/workflow-events.d.ts +88 -23
- package/dist/core/events/workflow-events.js +26 -0
- package/dist/core/failure-categories.js +5 -17
- package/dist/core/fault-code.d.ts +9 -3
- package/dist/core/fault-code.js +1 -0
- package/dist/core/inline-execution-strategy.context-options.d.ts +69 -0
- package/dist/core/inline-execution-strategy.context-options.js +56 -0
- package/dist/core/inline-execution-strategy.d.ts +31 -36
- package/dist/core/inline-execution-strategy.js +16 -27
- package/dist/core/list-filter-validation.d.ts +1 -1
- package/dist/core/payload-size.d.ts +1 -1
- package/dist/core/persisted-data-incompatible-error.d.ts +9 -7
- package/dist/core/review/events.d.ts +6 -8
- package/dist/core/scheduler/scheduler-class.d.ts +10 -1
- package/dist/core/scheduler/scheduler-class.js +38 -11
- package/dist/core/scheduler/timer-batch.js +9 -1
- package/dist/core/scheduler/timer-sources.d.ts +1 -0
- package/dist/core/scheduler/timer-sources.js +11 -5
- package/dist/core/session-state.d.ts +0 -1
- package/dist/core/session-state.js +2 -2
- package/dist/core/start-workflow-validation.d.ts +34 -0
- package/dist/core/start-workflow-validation.js +19 -0
- package/dist/core/types/activity-verification.d.ts +67 -0
- package/dist/core/types/activity-verification.js +0 -0
- package/dist/core/types/activity.d.ts +80 -61
- package/dist/core/types/bulk.d.ts +50 -9
- package/dist/core/types/checkpoint.d.ts +44 -8
- package/dist/core/types/list-options.d.ts +146 -0
- package/dist/core/types/list-options.js +0 -0
- package/dist/core/types/options.d.ts +121 -165
- package/dist/core/types/schedules.d.ts +39 -3
- package/dist/core/types/services-resolution.d.ts +2 -2
- package/dist/core/types/workflow-builder-runtime.d.ts +12 -3
- package/dist/core/types/workflow-builder-runtime.js +11 -2
- package/dist/core/types/workflow-builder.d.ts +42 -11
- package/dist/core/types/workflow-concurrency.d.ts +39 -0
- package/dist/core/types/workflow-concurrency.js +0 -0
- package/dist/core/types/workflow-context.d.ts +157 -14
- package/dist/core/types/workflow-definition.d.ts +53 -10
- package/dist/core/types/workflow-function.d.ts +84 -9
- package/dist/core/types/workflow-log.d.ts +98 -0
- package/dist/core/types/workflow-log.js +0 -0
- package/dist/core/types/workflow-registries.d.ts +14 -3
- package/dist/core/types/workflow-registry.d.ts +3 -0
- package/dist/core/types.d.ts +4 -0
- package/dist/core/types.js +4 -0
- package/dist/core/versioning.d.ts +9 -39
- package/dist/core/versioning.js +2 -12
- package/dist/core/weft-error.d.ts +44 -1
- package/dist/core/weft-error.js +16 -0
- package/dist/core/worker-execution-strategy-options.d.ts +26 -0
- package/dist/core/worker-execution-strategy.js +40 -36
- package/dist/core/worker-inbound-message.d.ts +38 -0
- package/dist/core/worker-inbound-message.js +37 -0
- package/dist/core/worker-log-abuse-counter.d.ts +175 -0
- package/dist/core/worker-log-abuse-counter.js +107 -0
- package/dist/core/worker-message-helpers.d.ts +47 -0
- package/dist/core/worker-message-helpers.js +26 -0
- package/dist/core/worker-protocol-guard.js +1 -1
- package/dist/core/worker-protocol-log.d.ts +56 -0
- package/dist/core/worker-protocol-log.js +18 -0
- package/dist/core/worker-protocol.d.ts +23 -0
- package/dist/core/worker-protocol.js +12 -2
- package/dist/core/workflow-version-tuple.d.ts +3 -9
- package/dist/core/workflow-version-tuple.js +2 -3
- package/dist/diagnostics/format.js +1 -6
- package/dist/diagnostics/types.d.ts +4 -5
- package/dist/diagnostics/validate.d.ts +0 -1
- package/dist/diagnostics/version-check.d.ts +1 -1
- package/dist/diagnostics/version-check.js +4 -9
- package/dist/index.d.ts +12 -10
- package/dist/index.js +29 -3
- package/dist/json-schema.js +3 -3
- package/dist/mcp/cli.js +19 -19
- package/dist/mcp/dispatcher.js +1 -1
- package/dist/mcp/http.js +16 -6
- package/dist/mcp/protocol.d.ts +2 -0
- package/dist/mcp/protocol.js +1 -1
- package/dist/mcp/session.d.ts +16 -0
- package/dist/mcp/session.js +59 -6
- package/dist/mcp/tools.js +73 -6
- package/dist/observability/index.js +2 -2
- package/dist/server/asyncapi-channels.js +5 -2
- package/dist/server/attribute-filters.d.ts +8 -3
- package/dist/server/attribute-filters.js +6 -1
- package/dist/server/authentication/api-key.d.ts +2 -1
- package/dist/server/authentication/api-key.js +5 -2
- package/dist/server/authentication/constant-time-api-key.d.ts +15 -0
- package/dist/server/authentication/constant-time-api-key.js +24 -0
- package/dist/server/authentication/index.d.ts +1 -1
- package/dist/server/authentication/index.js +7 -4
- package/dist/server/authentication/rotating-api-key-store.d.ts +5 -3
- package/dist/server/authentication/rotating-api-key-store.js +19 -11
- package/dist/server/engine-event-feed-backend.d.ts +4 -5
- package/dist/server/fault-to-http.js +8 -1
- package/dist/server/fault-to-json-rpc.js +1 -0
- package/dist/server/fleet-event-feed.d.ts +31 -0
- package/dist/server/fleet-event-feed.js +157 -0
- package/dist/server/handler/index.js +1 -1
- package/dist/server/handler/response-helpers.js +2 -1
- package/dist/server/handler/route-dispatch.d.ts +6 -3
- package/dist/server/handler/route-dispatch.js +2 -2
- package/dist/server/handler.js +23 -23
- package/dist/server/index.d.ts +32 -2
- package/dist/server/index.js +32 -32
- package/dist/server/json-rpc-transport-helpers.d.ts +1 -0
- package/dist/server/json-rpc-transport-helpers.js +2 -1
- package/dist/server/json-rpc-websocket-runtime.d.ts +11 -2
- package/dist/server/json-rpc-websocket-runtime.js +1 -0
- package/dist/server/json-rpc-websocket-subscriptions.d.ts +10 -0
- package/dist/server/json-rpc-websocket-subscriptions.js +29 -0
- package/dist/server/json-rpc-websocket-types.d.ts +22 -0
- package/dist/server/json-rpc-websocket-types.js +0 -0
- package/dist/server/json-rpc-websocket-validation.js +20 -4
- package/dist/server/json-rpc-websocket.d.ts +2 -43
- package/dist/server/json-rpc-websocket.js +57 -74
- package/dist/server/openapi.d.ts +2 -1
- package/dist/server/openapi.js +1 -3
- package/dist/server/openrpc-document-schema.d.ts +78 -0
- package/dist/server/openrpc-document-schema.js +27 -1
- package/dist/server/openrpc-errors.d.ts +3 -0
- package/dist/server/openrpc-errors.js +2 -1
- package/dist/server/openrpc.js +32 -0
- package/dist/server/operation-catalog/index.d.ts +1 -1
- package/dist/server/operation-catalog/pipeline-helpers.js +1 -0
- package/dist/server/operation-catalog/pipeline-stages.js +26 -12
- package/dist/server/operation-catalog/pipeline.js +8 -1
- package/dist/server/operation-catalog/registry.js +13 -0
- package/dist/server/operation-catalog/types.d.ts +20 -9
- package/dist/server/operation-fault.d.ts +10 -0
- package/dist/server/operation-fault.js +2 -0
- package/dist/server/operation-registry.d.ts +12 -11
- package/dist/server/operation-registry.js +12 -3
- package/dist/server/operations/aggregate-workflows.d.ts +15 -15
- package/dist/server/operations/async-activity.d.ts +2 -2
- package/dist/server/operations/async-activity.js +12 -7
- package/dist/server/operations/bulk-cancel-workflows.d.ts +1 -1
- package/dist/server/operations/bulk-cancel-workflows.js +2 -2
- package/dist/server/operations/bulk-delete-workflows.d.ts +1 -1
- package/dist/server/operations/bulk-delete-workflows.js +2 -2
- package/dist/server/operations/bulk-filter-helpers.d.ts +8 -6
- package/dist/server/operations/bulk-filter-helpers.js +54 -24
- package/dist/server/operations/bulk-mutate-workflow-tags.d.ts +11 -9
- package/dist/server/operations/bulk-mutate-workflow-tags.js +2 -2
- package/dist/server/operations/bulk-operation-helpers.d.ts +2 -2
- package/dist/server/operations/bulk-retry-failed-workflows.d.ts +7 -0
- package/dist/server/operations/bulk-retry-failed-workflows.js +64 -0
- package/dist/server/operations/bulk-signal-workflows.d.ts +11 -9
- package/dist/server/operations/bulk-signal-workflows.js +2 -2
- package/dist/server/operations/cancel-schedule.d.ts +1 -1
- package/dist/server/operations/create-schedule.d.ts +3 -1
- package/dist/server/operations/create-schedule.js +29 -11
- package/dist/server/operations/fleet-events-subscription.d.ts +54 -0
- package/dist/server/operations/fleet-events-subscription.js +99 -0
- package/dist/server/operations/fork-workflow.d.ts +1 -1
- package/dist/server/operations/fork-workflow.js +3 -2
- package/dist/server/operations/get-checkpoint-at.d.ts +1 -1
- package/dist/server/operations/get-registry.d.ts +1 -1
- package/dist/server/operations/get-retention-overview.d.ts +1 -1
- package/dist/server/operations/get-review.d.ts +1 -1
- package/dist/server/operations/get-schedule.d.ts +1 -1
- package/dist/server/operations/get-stream-chunks.d.ts +1 -1
- package/dist/server/operations/get-system-metrics.d.ts +2 -2
- package/dist/server/operations/get-task-diagnostics.d.ts +45 -6
- package/dist/server/operations/get-task-diagnostics.js +101 -7
- package/dist/server/operations/get-update-result.d.ts +1 -1
- package/dist/server/operations/get-workflow-attributes.d.ts +1 -1
- package/dist/server/operations/get-workflow-events.d.ts +1 -1
- package/dist/server/operations/get-workflow-result.d.ts +1 -1
- package/dist/server/operations/get-workflow-timeline.d.ts +1 -1
- package/dist/server/operations/get-workflow.d.ts +1 -1
- package/dist/server/operations/list-checkpoints.d.ts +1 -1
- package/dist/server/operations/list-reviews.d.ts +1 -1
- package/dist/server/operations/list-schedules.d.ts +1 -1
- package/dist/server/operations/list-task-queues.d.ts +2 -2
- package/dist/server/operations/list-workers.d.ts +2 -2
- package/dist/server/operations/list-workflows.d.ts +1 -1
- package/dist/server/operations/operation-helpers.d.ts +16 -1
- package/dist/server/operations/operation-helpers.js +15 -3
- package/dist/server/operations/pause-schedule.d.ts +1 -1
- package/dist/server/operations/purge-workflows.d.ts +5 -5
- package/dist/server/operations/purge-workflows.js +2 -2
- package/dist/server/operations/query-workflow.d.ts +1 -1
- package/dist/server/operations/query-workflow.js +3 -2
- package/dist/server/operations/recover-all.d.ts +1 -1
- package/dist/server/operations/replay-workflow.d.ts +1 -1
- package/dist/server/operations/resume-schedule.d.ts +1 -1
- package/dist/server/operations/set-workflow-attributes.d.ts +1 -1
- package/dist/server/operations/set-workflow-attributes.js +6 -3
- package/dist/server/operations/signal-workflow.js +8 -3
- package/dist/server/operations/single-workflow-tag-mutation.js +13 -3
- package/dist/server/operations/start-or-signal-workflow.d.ts +6 -1
- package/dist/server/operations/start-or-signal-workflow.js +14 -24
- package/dist/server/operations/start-workflow-options.d.ts +6 -0
- package/dist/server/operations/start-workflow-rest-input.d.ts +14 -0
- package/dist/server/operations/start-workflow-rest-input.js +31 -0
- package/dist/server/operations/start-workflow.d.ts +1 -1
- package/dist/server/operations/start-workflow.js +8 -23
- package/dist/server/operations/storage.d.ts +6 -6
- package/dist/server/operations/storage.js +24 -14
- package/dist/server/operations/stream-workflow-sse.d.ts +1 -1
- package/dist/server/operations/submit-review-decision.d.ts +1 -1
- package/dist/server/operations/submit-review-decision.js +6 -3
- package/dist/server/operations/update-schedule.d.ts +1 -1
- package/dist/server/operations/update-schedule.js +7 -4
- package/dist/server/operations/update-workflow.d.ts +1 -1
- package/dist/server/operations/update-workflow.js +7 -3
- package/dist/server/operations/worker-drain.d.ts +8 -8
- package/dist/server/operations/worker-drain.js +11 -8
- package/dist/server/operations/workflow-events-subscription.d.ts +7 -8
- package/dist/server/operations/workflow-events-subscription.js +43 -8
- package/dist/server/rest-binding.d.ts +3 -1
- package/dist/server/rest-bindings.js +12 -0
- package/dist/server/rest-body.d.ts +10 -0
- package/dist/server/rest-body.js +80 -0
- package/dist/server/runtime/authentication-bridge.d.ts +1 -0
- package/dist/server/runtime/authentication-bridge.js +33 -6
- package/dist/server/runtime/client-visible-events.d.ts +3 -0
- package/dist/server/runtime/client-visible-events.js +65 -0
- package/dist/server/runtime/context.d.ts +7 -0
- package/dist/server/runtime/event-broadcasting.d.ts +6 -0
- package/dist/server/runtime/event-broadcasting.js +72 -38
- package/dist/server/runtime/retry.d.ts +1 -0
- package/dist/server/runtime/retry.js +14 -0
- package/dist/server/runtime/shutdown.d.ts +7 -6
- package/dist/server/runtime/shutdown.js +6 -1
- package/dist/server/runtime/task-polling.js +61 -20
- package/dist/server/runtime/task-reconciliation.js +9 -1
- package/dist/server/runtime/task-result-resolution.d.ts +15 -0
- package/dist/server/runtime/task-result-resolution.js +81 -0
- package/dist/server/runtime/websocket-stream.d.ts +20 -1
- package/dist/server/runtime/websocket-stream.js +173 -7
- package/dist/server/runtime/websocket-upgrade.js +22 -3
- package/dist/server/runtime/websocket-worker.d.ts +1 -1
- package/dist/server/runtime/websocket-worker.js +38 -30
- package/dist/server/serve-internals.d.ts +3 -1
- package/dist/server/serve-internals.js +18 -2
- package/dist/server/task-state.d.ts +30 -0
- package/dist/server/task-state.js +28 -0
- package/dist/server/workflow-event-feed.d.ts +36 -115
- package/dist/server/workflow-event-feed.js +92 -27
- package/dist/service-worker/index.js +30 -30
- package/dist/storage/auto.js +1 -1
- package/dist/storage/bun-sql.js +24 -0
- package/dist/storage/compressed-storage.js +1 -1
- package/dist/storage/default-scope.d.ts +7 -4
- package/dist/storage/http.js +2 -2
- package/dist/storage/index.d.ts +76 -4
- package/dist/storage/indexeddb.js +1 -1
- package/dist/storage/interface.d.ts +163 -0
- package/dist/storage/interface.js +1 -1
- package/dist/storage/key-prefixes.d.ts +1 -1
- package/dist/storage/key-prefixes.js +10 -0
- package/dist/storage/lmdb.d.ts +4 -3
- package/dist/storage/lmdb.js +1 -1
- package/dist/storage/memory.js +1 -1
- package/dist/storage/neon-batch.d.ts +30 -0
- package/dist/storage/neon-batch.js +30 -0
- package/dist/storage/neon-value-mapping.d.ts +30 -3
- package/dist/storage/neon-value-mapping.js +12 -0
- package/dist/storage/neon.d.ts +16 -0
- package/dist/storage/neon.js +9 -4
- package/dist/storage/node-sqlite.js +23 -0
- package/dist/storage/postgres-key-value-queries.d.ts +69 -44
- package/dist/storage/postgres-key-value-queries.js +62 -24
- package/dist/storage/resolve.js +1 -1
- package/dist/storage/scoped-storage.js +1 -1
- package/dist/storage/testing.d.ts +168 -0
- package/dist/storage/testing.js +2 -0
- package/dist/storage/turso.d.ts +8 -0
- package/dist/storage/turso.js +2 -2
- package/dist/storage/typed-storage.js +1 -1
- package/dist/storage/web-extension.js +1 -1
- package/dist/testing/index.js +20 -20
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker/protocol.js +1 -1
- package/dist/workers/worker-replay-state.d.ts +32 -0
- package/dist/workers/worker-replay-state.js +35 -0
- package/dist/workers/worker-state-namespace.d.ts +21 -0
- package/dist/workers/worker-state-namespace.js +13 -0
- package/dist/workers/workflow-runner.d.ts +19 -15
- package/dist/workers/workflow-runner.js +72 -60
- package/dist/workers/workflow-worker-entry.js +5 -2
- package/package.json +5 -1
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { WeftError } from './weft-error.ts';
|
|
2
2
|
/**
|
|
3
3
|
* Thrown by {@link Engine.create} (and other storage-opening entry points) when
|
|
4
|
-
* a persisted Weft database
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* a persisted Weft database's schema version does not match what the engine
|
|
5
|
+
* requires — an older version, a newer one, an unparseable sentinel, or user
|
|
6
|
+
* data present with no sentinel at all. Weft loads persisted data only at the
|
|
7
|
+
* exact current schema version; it never reshapes a non-matching database in
|
|
8
|
+
* place. Bumping {@link CURRENT_PERSISTED_DATA_SCHEMA_VERSION} intentionally
|
|
9
|
+
* invalidates databases stamped with any other version so the failure surfaces
|
|
10
|
+
* deterministically at boot, before any workflow attempts replay.
|
|
9
11
|
*
|
|
10
12
|
* Inspect `foundVersion` to see what the storage advertised and `expectedVersion`
|
|
11
|
-
* to see what this engine requires. Resolve by deleting the database
|
|
12
|
-
*
|
|
13
|
+
* to see what this engine requires. Resolve by deleting the database or by
|
|
14
|
+
* starting from fresh storage.
|
|
13
15
|
*
|
|
14
16
|
* @example
|
|
15
17
|
* ```ts
|
|
@@ -6,12 +6,11 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @example Route review notifications to a webhook
|
|
8
8
|
* ```ts
|
|
9
|
-
* import { ReviewRequestedEvent } from '@lostgradient/weft';
|
|
9
|
+
* import { ReviewRequestedEvent, type TypedEventTarget, type WeftReviewEventMap } from '@lostgradient/weft';
|
|
10
10
|
*
|
|
11
|
-
* const target
|
|
11
|
+
* declare const target: TypedEventTarget<WeftReviewEventMap>;
|
|
12
12
|
*
|
|
13
|
-
* target.addEventListener(ReviewRequestedEvent.type, (
|
|
14
|
-
* const event = e as ReviewRequestedEvent;
|
|
13
|
+
* target.addEventListener(ReviewRequestedEvent.type, (event) => {
|
|
15
14
|
* console.log(`Review ${event.reviewId} requested for workflow ${event.workflowId}`);
|
|
16
15
|
* console.log('Reviewers:', event.reviewers);
|
|
17
16
|
* });
|
|
@@ -33,12 +32,11 @@ export declare class ReviewRequestedEvent extends Event {
|
|
|
33
32
|
*
|
|
34
33
|
* @example Record review decisions in an audit log
|
|
35
34
|
* ```ts
|
|
36
|
-
* import { ReviewCompletedEvent } from '@lostgradient/weft';
|
|
35
|
+
* import { ReviewCompletedEvent, type TypedEventTarget, type WeftReviewEventMap } from '@lostgradient/weft';
|
|
37
36
|
*
|
|
38
|
-
* const target
|
|
37
|
+
* declare const target: TypedEventTarget<WeftReviewEventMap>;
|
|
39
38
|
*
|
|
40
|
-
* target.addEventListener(ReviewCompletedEvent.type, (
|
|
41
|
-
* const event = e as ReviewCompletedEvent;
|
|
39
|
+
* target.addEventListener(ReviewCompletedEvent.type, (event) => {
|
|
42
40
|
* console.log(`Review ${event.reviewId}: '${event.decision}' by ${event.reviewer} in ${event.duration}ms`);
|
|
43
41
|
* });
|
|
44
42
|
* ```
|
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
import type { Storage } from '../../storage/interface.ts';
|
|
1
|
+
import type { BatchOperation, Storage } from '../../storage/interface.ts';
|
|
2
2
|
import type { TimerEntry } from '../types.ts';
|
|
3
3
|
export interface SchedulerOptions {
|
|
4
4
|
storage: Storage;
|
|
5
5
|
onTimerFired: (entry: TimerEntry) => void | Promise<void>;
|
|
6
6
|
pollIntervalMs?: number;
|
|
7
7
|
getNow?: () => number;
|
|
8
|
+
/**
|
|
9
|
+
* Commit the batch that deletes a fired timer's keys after its callback
|
|
10
|
+
* returns. Defaults to an unfenced `storage.batch`. The engine supplies a
|
|
11
|
+
* lease-fenced commit (#563) so the fired-timer delete and the callback's own
|
|
12
|
+
* follow-up writes share the same ownership fence — under deposition both are
|
|
13
|
+
* rejected and the timer survives for the successor to re-drive. With no lease
|
|
14
|
+
* held this commits exactly as the unfenced default would.
|
|
15
|
+
*/
|
|
16
|
+
commitTimerCleanup?: (operations: BatchOperation[]) => Promise<void>;
|
|
8
17
|
}
|
|
9
18
|
/**
|
|
10
19
|
* Scheduler manages durable timers and polls for expired deadlines.
|
|
@@ -4,16 +4,19 @@ import { buildTimerBatchOperations } from "./timer-batch.js";
|
|
|
4
4
|
import {
|
|
5
5
|
advanceTimerSource,
|
|
6
6
|
readNextScannedTimerEntry,
|
|
7
|
+
readNextTeardownTimerEntry,
|
|
7
8
|
readNextTerminalCleanupTimerEntry,
|
|
8
9
|
selectNextTimerSource,
|
|
9
10
|
shouldDeleteTimerIndexWithoutLookup
|
|
10
11
|
} from "./timer-sources.js";
|
|
12
|
+
const EXPIRED_TIMER_SCAN_LIMIT_PER_SOURCE = 1000;
|
|
11
13
|
|
|
12
14
|
export class Scheduler {
|
|
13
15
|
#storage;
|
|
14
16
|
#onTimerFired;
|
|
15
17
|
#pollIntervalMs;
|
|
16
18
|
#getNow;
|
|
19
|
+
#commitTimerCleanup;
|
|
17
20
|
#intervalHandle = null;
|
|
18
21
|
#stopped = !1;
|
|
19
22
|
constructor(options) {
|
|
@@ -21,6 +24,7 @@ export class Scheduler {
|
|
|
21
24
|
this.#onTimerFired = options.onTimerFired;
|
|
22
25
|
this.#pollIntervalMs = options.pollIntervalMs ?? 1000;
|
|
23
26
|
this.#getNow = options.getNow ?? Date.now;
|
|
27
|
+
this.#commitTimerCleanup = options.commitTimerCleanup ?? ((operations) => this.#storage.batch(operations));
|
|
24
28
|
}
|
|
25
29
|
start() {
|
|
26
30
|
if (this.#intervalHandle !== null)
|
|
@@ -66,7 +70,7 @@ export class Scheduler {
|
|
|
66
70
|
this.stop();
|
|
67
71
|
}
|
|
68
72
|
async#processExpiredTimers(now, { respectStopped }) {
|
|
69
|
-
const currentTime = now ?? this.#getNow(), timerSources = this.#createTimerSources(this.#scanExpiredTimers(currentTime));
|
|
73
|
+
const currentTime = now ?? this.#getNow(), timerSources = this.#createTimerSources(this.#scanExpiredTimers(currentTime)), cleanupOperations = [];
|
|
70
74
|
for (const timerSource of timerSources)
|
|
71
75
|
await advanceTimerSource(timerSource, this.#storage);
|
|
72
76
|
while (this.#hasPendingTimer(timerSources)) {
|
|
@@ -74,27 +78,36 @@ export class Scheduler {
|
|
|
74
78
|
if (!nextEntry || !selectedSource)
|
|
75
79
|
break;
|
|
76
80
|
if (respectStopped && this.#stopped)
|
|
77
|
-
|
|
78
|
-
if (await this.#processSelectedTimer(nextEntry) === "retry") {
|
|
81
|
+
break;
|
|
82
|
+
if (await this.#processSelectedTimer(nextEntry, cleanupOperations) === "retry") {
|
|
79
83
|
await advanceTimerSource(selectedSource, this.#storage);
|
|
80
84
|
continue;
|
|
81
85
|
}
|
|
82
86
|
await advanceTimerSource(selectedSource, this.#storage);
|
|
83
87
|
}
|
|
88
|
+
await this.#deleteProcessedTimerKeys(cleanupOperations);
|
|
84
89
|
}
|
|
85
90
|
#scanExpiredTimers(currentTime) {
|
|
86
91
|
return {
|
|
87
92
|
deadline: this.#storage.scan("wf-deadline:", {
|
|
88
|
-
lt: resolvePrefixRangeEnd(KEYS.deadline(currentTime, ""))
|
|
93
|
+
lt: resolvePrefixRangeEnd(KEYS.deadline(currentTime, "")),
|
|
94
|
+
limit: EXPIRED_TIMER_SCAN_LIMIT_PER_SOURCE
|
|
89
95
|
}),
|
|
90
96
|
delayedStart: this.#storage.scan("wf-delayed:", {
|
|
91
|
-
lt: resolvePrefixRangeEnd(KEYS.delayedStart(currentTime, ""))
|
|
97
|
+
lt: resolvePrefixRangeEnd(KEYS.delayedStart(currentTime, "")),
|
|
98
|
+
limit: EXPIRED_TIMER_SCAN_LIMIT_PER_SOURCE
|
|
92
99
|
}),
|
|
93
100
|
schedule: this.#storage.scan("schedule-due:", {
|
|
94
|
-
lt: resolvePrefixRangeEnd(KEYS.scheduleTick(currentTime, ""))
|
|
101
|
+
lt: resolvePrefixRangeEnd(KEYS.scheduleTick(currentTime, "")),
|
|
102
|
+
limit: EXPIRED_TIMER_SCAN_LIMIT_PER_SOURCE
|
|
95
103
|
}),
|
|
96
104
|
terminalCleanup: this.#storage.scan("wf-cleanup:", {
|
|
97
|
-
lt: resolvePrefixRangeEnd(KEYS.terminalCleanup(currentTime, ""))
|
|
105
|
+
lt: resolvePrefixRangeEnd(KEYS.terminalCleanup(currentTime, "")),
|
|
106
|
+
limit: EXPIRED_TIMER_SCAN_LIMIT_PER_SOURCE
|
|
107
|
+
}),
|
|
108
|
+
teardown: this.#storage.scan("wf-teardown:", {
|
|
109
|
+
lt: resolvePrefixRangeEnd(KEYS.teardownTimer(currentTime, "")),
|
|
110
|
+
limit: EXPIRED_TIMER_SCAN_LIMIT_PER_SOURCE
|
|
98
111
|
})
|
|
99
112
|
};
|
|
100
113
|
}
|
|
@@ -119,29 +132,43 @@ export class Scheduler {
|
|
|
119
132
|
iterator: iterators.terminalCleanup[Symbol.asyncIterator](),
|
|
120
133
|
next: null,
|
|
121
134
|
readNext: readNextTerminalCleanupTimerEntry
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
iterator: iterators.teardown[Symbol.asyncIterator](),
|
|
138
|
+
next: null,
|
|
139
|
+
readNext: readNextTeardownTimerEntry
|
|
122
140
|
}
|
|
123
141
|
];
|
|
124
142
|
}
|
|
125
143
|
#hasPendingTimer(timerSources) {
|
|
126
144
|
return timerSources.some((timerSource) => timerSource.next !== null);
|
|
127
145
|
}
|
|
128
|
-
async#processSelectedTimer(nextEntry) {
|
|
146
|
+
async#processSelectedTimer(nextEntry, cleanupOperations) {
|
|
129
147
|
try {
|
|
130
148
|
await this.#onTimerFired(nextEntry.entry);
|
|
131
149
|
} catch (error) {
|
|
132
150
|
console.error(`Timer callback failed for timer ${nextEntry.entry.id}:`, error);
|
|
133
151
|
return "retry";
|
|
134
152
|
}
|
|
135
|
-
await this.#
|
|
153
|
+
await this.#appendTimerCleanupOperationsAfterCallback(nextEntry, cleanupOperations);
|
|
136
154
|
return "processed";
|
|
137
155
|
}
|
|
138
|
-
async#
|
|
156
|
+
async#appendTimerCleanupOperationsAfterCallback(nextEntry, cleanupOperations) {
|
|
139
157
|
try {
|
|
140
|
-
|
|
158
|
+
cleanupOperations.push(...await this.#buildTimerCleanupOperations(nextEntry));
|
|
141
159
|
} catch (deleteError) {
|
|
142
160
|
console.error(`Failed to delete timer keys for ${nextEntry.entry.id}:`, deleteError);
|
|
143
161
|
}
|
|
144
162
|
}
|
|
163
|
+
async#deleteProcessedTimerKeys(cleanupOperations) {
|
|
164
|
+
if (cleanupOperations.length === 0)
|
|
165
|
+
return;
|
|
166
|
+
try {
|
|
167
|
+
await this.#commitTimerCleanup(cleanupOperations);
|
|
168
|
+
} catch (deleteError) {
|
|
169
|
+
console.error("Failed to delete timer keys for processed scheduler tick:", deleteError);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
145
172
|
async#buildTimerCleanupOperations(nextEntry) {
|
|
146
173
|
const cleanupOperations = [{ type: "delete", key: nextEntry.key }], indexDeleteOperation = await this.#buildTimerIndexDeleteOperation(nextEntry);
|
|
147
174
|
if (indexDeleteOperation)
|
|
@@ -2,7 +2,7 @@ import { KEYS } from "../../storage/interface.js";
|
|
|
2
2
|
import { encode } from "../codec.js";
|
|
3
3
|
import { normalizeStorageTimestamp } from "./duration.js";
|
|
4
4
|
function isTimerEntryKind(value) {
|
|
5
|
-
return value === "sleep" || value === "visibility-timeout" || value === "execution-deadline" || value === "delayed-start" || value === "schedule" || value === "terminal-cleanup";
|
|
5
|
+
return value === "sleep" || value === "visibility-timeout" || value === "execution-deadline" || value === "delayed-start" || value === "schedule" || value === "terminal-cleanup" || value === "teardown" || value === "wait-condition";
|
|
6
6
|
}
|
|
7
7
|
function isRecord(value) {
|
|
8
8
|
return typeof value === "object" && value !== null;
|
|
@@ -30,6 +30,14 @@ export function buildTimerBatchOperations(entry) {
|
|
|
30
30
|
value: encode(normalizedEntry.workflowId)
|
|
31
31
|
}
|
|
32
32
|
];
|
|
33
|
+
if (normalizedEntry.kind === "teardown")
|
|
34
|
+
return [
|
|
35
|
+
{
|
|
36
|
+
type: "put",
|
|
37
|
+
key: KEYS.teardownTimer(normalizedEntry.fireAt, normalizedEntry.id),
|
|
38
|
+
value: encode(normalizedEntry.workflowId)
|
|
39
|
+
}
|
|
40
|
+
];
|
|
33
41
|
const deadlineKey = normalizedEntry.kind === "delayed-start" ? KEYS.delayedStart(normalizedEntry.fireAt, normalizedEntry.workflowId) : normalizedEntry.kind === "schedule" ? KEYS.scheduleTick(normalizedEntry.fireAt, normalizedEntry.workflowId) : KEYS.deadline(normalizedEntry.fireAt, normalizedEntry.id), operations = [
|
|
34
42
|
{ type: "put", key: deadlineKey, value: encode(normalizedEntry) }
|
|
35
43
|
];
|
|
@@ -12,6 +12,7 @@ export type TimerSource = {
|
|
|
12
12
|
export declare function compareScannedTimerEntries(left: ScannedTimerEntry, right: ScannedTimerEntry): number;
|
|
13
13
|
export declare function readNextScannedTimerEntry(iterator: AsyncIterator<[string, Uint8Array]>, storage: Storage): Promise<ScannedTimerEntry | null>;
|
|
14
14
|
export declare function readNextTerminalCleanupTimerEntry(iterator: AsyncIterator<[string, Uint8Array]>, storage: Storage): Promise<ScannedTimerEntry | null>;
|
|
15
|
+
export declare function readNextTeardownTimerEntry(iterator: AsyncIterator<[string, Uint8Array]>, storage: Storage): Promise<ScannedTimerEntry | null>;
|
|
15
16
|
export declare function advanceTimerSource(timerSource: TimerSource, storage: Storage): Promise<void>;
|
|
16
17
|
export declare function selectNextTimerSource(timerSources: TimerSource[]): TimerSource | undefined;
|
|
17
18
|
export declare function shouldDeleteTimerIndexWithoutLookup(entry: TimerEntry): boolean;
|
|
@@ -20,15 +20,15 @@ export async function readNextScannedTimerEntry(iterator, storage) {
|
|
|
20
20
|
return { key, entry: decoded };
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
-
|
|
24
|
-
const prefix = "wf-cleanup:";
|
|
23
|
+
async function readNextWorkflowTimerEntry(iterator, storage, kind) {
|
|
24
|
+
const { diagnosticName, prefix } = kind === "terminal-cleanup" ? { diagnosticName: "terminal cleanup", prefix: "wf-cleanup:" } : { diagnosticName: "teardown timer", prefix: "wf-teardown:" };
|
|
25
25
|
while (!0) {
|
|
26
26
|
const next = await iterator.next();
|
|
27
27
|
if (next.done)
|
|
28
28
|
return null;
|
|
29
29
|
const [key, value] = next.value, separatorIndex = key.indexOf(":", prefix.length), fireAtValue = separatorIndex === -1 ? Number.NaN : Number(key.slice(prefix.length, separatorIndex)), timerId = separatorIndex === -1 ? null : tryDecodeStorageKeyComponent(key.slice(separatorIndex + 1)), decodedWorkflowId = decode(value);
|
|
30
30
|
if (!Number.isSafeInteger(fireAtValue) || fireAtValue < 0 || timerId === null || typeof decodedWorkflowId !== "string") {
|
|
31
|
-
console.error(`Corrupted
|
|
31
|
+
console.error(`Corrupted ${diagnosticName} entry at ${key}: removing`);
|
|
32
32
|
await storage.delete(key);
|
|
33
33
|
continue;
|
|
34
34
|
}
|
|
@@ -38,11 +38,17 @@ export async function readNextTerminalCleanupTimerEntry(iterator, storage) {
|
|
|
38
38
|
id: timerId,
|
|
39
39
|
workflowId: decodedWorkflowId,
|
|
40
40
|
fireAt: fireAtValue,
|
|
41
|
-
kind
|
|
41
|
+
kind
|
|
42
42
|
}
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
+
export async function readNextTerminalCleanupTimerEntry(iterator, storage) {
|
|
47
|
+
return readNextWorkflowTimerEntry(iterator, storage, "terminal-cleanup");
|
|
48
|
+
}
|
|
49
|
+
export async function readNextTeardownTimerEntry(iterator, storage) {
|
|
50
|
+
return readNextWorkflowTimerEntry(iterator, storage, "teardown");
|
|
51
|
+
}
|
|
46
52
|
export async function advanceTimerSource(timerSource, storage) {
|
|
47
53
|
timerSource.next = await timerSource.readNext(timerSource.iterator, storage);
|
|
48
54
|
}
|
|
@@ -57,5 +63,5 @@ export function selectNextTimerSource(timerSources) {
|
|
|
57
63
|
return selectedSource;
|
|
58
64
|
}
|
|
59
65
|
export function shouldDeleteTimerIndexWithoutLookup(entry) {
|
|
60
|
-
return entry.kind !== "schedule" && entry.kind !== "terminal-cleanup";
|
|
66
|
+
return entry.kind !== "schedule" && entry.kind !== "terminal-cleanup" && entry.kind !== "teardown";
|
|
61
67
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { WeftError } from './weft-error.ts';
|
|
2
2
|
export declare const SESSION_STATE_LOCAL_KEY = "stateSession";
|
|
3
|
-
export declare const LEGACY_SESSION_STATE_LOCAL_KEY = "sessionState";
|
|
4
3
|
export declare const MAX_SESSION_STATE_ENTRY_COUNT = 256;
|
|
5
4
|
export declare const MAX_SESSION_STATE_KEY_LENGTH = 256;
|
|
6
5
|
export declare const MAX_SESSION_STATE_SERIALIZED_BYTES: number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { encode } from "./codec.js";
|
|
2
2
|
import { WeftError } from "./weft-error.js";
|
|
3
|
-
export const SESSION_STATE_LOCAL_KEY = "stateSession",
|
|
3
|
+
export const SESSION_STATE_LOCAL_KEY = "stateSession", MAX_SESSION_STATE_ENTRY_COUNT = 256, MAX_SESSION_STATE_KEY_LENGTH = 256, MAX_SESSION_STATE_SERIALIZED_BYTES = 32768;
|
|
4
4
|
const RESERVED_SESSION_STATE_KEYS = new Set(["__proto__", "constructor", "prototype"]);
|
|
5
5
|
|
|
6
6
|
export class SessionStateValidationError extends WeftError {
|
|
@@ -55,7 +55,7 @@ export function normalizeSessionStateRecord(value) {
|
|
|
55
55
|
export function normalizeSessionStateLocals(locals) {
|
|
56
56
|
if (!locals)
|
|
57
57
|
return;
|
|
58
|
-
return normalizeSessionStateRecord(locals[SESSION_STATE_LOCAL_KEY]
|
|
58
|
+
return normalizeSessionStateRecord(locals[SESSION_STATE_LOCAL_KEY]);
|
|
59
59
|
}
|
|
60
60
|
export function validateSessionStateStore(store) {
|
|
61
61
|
const keys = Object.keys(store);
|
|
@@ -29,6 +29,40 @@ export declare const coerceStartWorkflowIdempotencyKey: (value: unknown, fieldNa
|
|
|
29
29
|
* caller gets the same guarantees as an HTTP caller.
|
|
30
30
|
*/
|
|
31
31
|
export declare const assertValidIdempotencyKey: (value: string, fieldName: string) => string;
|
|
32
|
+
/**
|
|
33
|
+
* Validate the `onTerminalConflict` start policy against the rest of the start
|
|
34
|
+
* options. `'error'` (the default) and `'start-new'` are the only accepted
|
|
35
|
+
* values. `'start-new'` (Temporal's `ALLOW_DUPLICATE` for terminal runs) requires
|
|
36
|
+
* an explicit, caller-chosen `id` and is mutually exclusive with `idempotencyKey`:
|
|
37
|
+
* idempotency is a permanent at-most-once mapping that survives terminal state, so
|
|
38
|
+
* restarting under it would contradict that contract. A generated UUID is never a
|
|
39
|
+
* meaningful restart target, hence the explicit-`id` requirement.
|
|
40
|
+
*/
|
|
41
|
+
export declare function assertValidOnTerminalConflict(options: {
|
|
42
|
+
onTerminalConflict?: unknown;
|
|
43
|
+
id?: unknown;
|
|
44
|
+
idempotencyKey?: unknown;
|
|
45
|
+
} | undefined): void;
|
|
46
|
+
/**
|
|
47
|
+
* `options.id` and `options.idempotencyKey` are mutually exclusive: idempotency
|
|
48
|
+
* assigns its own generated workflow id and dedups through the key, so pinning a
|
|
49
|
+
* caller id alongside it conflates "id already taken" with "lost the idempotency
|
|
50
|
+
* race". Reject the combination so each concern stays separable. Shared by the
|
|
51
|
+
* plain idempotent-start path and `startOrSignal` convergence validation.
|
|
52
|
+
*/
|
|
53
|
+
export declare function assertIdAndIdempotencyKeyExclusive(options: {
|
|
54
|
+
id?: unknown;
|
|
55
|
+
idempotencyKey?: unknown;
|
|
56
|
+
}): void;
|
|
57
|
+
/**
|
|
58
|
+
* Reject `onTerminalConflict` on a start surface that does not support it
|
|
59
|
+
* (`engine.startOrSignal`). The option is type-absent from those surfaces, but a
|
|
60
|
+
* transport or untyped JS caller could still smuggle the field into the options
|
|
61
|
+
* object — this is the runtime backstop. `engine.startOrSignal`'s identity is the
|
|
62
|
+
* permanent at-most-once idempotency mapping, which `'start-new'` would violate,
|
|
63
|
+
* so the policy is `engine.start`-only (see follow-up issue #489).
|
|
64
|
+
*/
|
|
65
|
+
export declare function assertOnTerminalConflictUnsupported(options: object | undefined, surface: string): void;
|
|
32
66
|
export declare function coerceStartWorkflowTimestamp(value: unknown, fieldName: string): number;
|
|
33
67
|
export declare function parseStartWorkflowDuration(duration: Duration, fieldName: string): number;
|
|
34
68
|
export declare function coerceStartWorkflowDuration(value: unknown, fieldName: string): Duration;
|
|
@@ -33,6 +33,25 @@ export const assertExclusiveStartWorkflowOptions = (startAt, startAfter) => {
|
|
|
33
33
|
throw new StartWorkflowValidationError(`${fieldName} must be at most ${MAX_IDEMPOTENCY_KEY_BYTES} UTF-8 bytes`);
|
|
34
34
|
return value;
|
|
35
35
|
};
|
|
36
|
+
export function assertValidOnTerminalConflict(options) {
|
|
37
|
+
const onTerminalConflict = options?.onTerminalConflict;
|
|
38
|
+
if (onTerminalConflict === void 0 || onTerminalConflict === "error")
|
|
39
|
+
return;
|
|
40
|
+
if (onTerminalConflict !== "start-new")
|
|
41
|
+
throw new StartWorkflowValidationError("options.onTerminalConflict must be 'error' or 'start-new'");
|
|
42
|
+
if (options?.idempotencyKey !== void 0)
|
|
43
|
+
throw new StartWorkflowValidationError("options.onTerminalConflict: 'start-new' is mutually exclusive with options.idempotencyKey: idempotency is a permanent at-most-once mapping and cannot restart a terminal run");
|
|
44
|
+
if (options?.id === void 0)
|
|
45
|
+
throw new StartWorkflowValidationError("options.onTerminalConflict: 'start-new' requires an explicit options.id; a generated id is never a meaningful restart target");
|
|
46
|
+
}
|
|
47
|
+
export function assertIdAndIdempotencyKeyExclusive(options) {
|
|
48
|
+
if (options.id !== void 0 && options.idempotencyKey !== void 0)
|
|
49
|
+
throw new StartWorkflowValidationError("options.id and options.idempotencyKey are mutually exclusive: idempotency assigns its own workflow id and dedups through the idempotency key. Provide one or the other.");
|
|
50
|
+
}
|
|
51
|
+
export function assertOnTerminalConflictUnsupported(options, surface) {
|
|
52
|
+
if (options !== void 0 && "onTerminalConflict" in options && options.onTerminalConflict !== void 0)
|
|
53
|
+
throw new StartWorkflowValidationError(`${surface} does not support options.onTerminalConflict; it is available on engine.start only`);
|
|
54
|
+
}
|
|
36
55
|
export function coerceStartWorkflowTimestamp(value, fieldName) {
|
|
37
56
|
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0)
|
|
38
57
|
throw new StartWorkflowValidationError(`${fieldName} must be a non-negative integer millisecond timestamp`);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Activity verification types: the two-phase verifier contract an activity can
|
|
3
|
+
* declare via {@link ActivityDefinition.verify}. Split out of `activity.ts` to
|
|
4
|
+
* keep that module under the per-file line ceiling; these types are re-exported
|
|
5
|
+
* through `../types.ts` so the public surface is unchanged.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Identifies whether an activity verifier is checking a fresh result or
|
|
9
|
+
* reconciling a prior keyed dispatch before redispatch.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import type { ActivityVerificationPhase } from '@lostgradient/weft';
|
|
14
|
+
*
|
|
15
|
+
* const phase: ActivityVerificationPhase = 'pre-dispatch-reconciliation';
|
|
16
|
+
* console.log(phase);
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export type ActivityVerificationPhase = 'post-execution-validation' | 'pre-dispatch-reconciliation';
|
|
20
|
+
/**
|
|
21
|
+
* Metadata passed to a Tier-0 activity verifier.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* import type { ActivityVerificationContext } from '@lostgradient/weft';
|
|
26
|
+
*
|
|
27
|
+
* function shouldQueryExternalSystem(context: ActivityVerificationContext): boolean {
|
|
28
|
+
* return context.phase === 'pre-dispatch-reconciliation';
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export interface ActivityVerificationContext<TInput = unknown> {
|
|
33
|
+
phase: ActivityVerificationPhase;
|
|
34
|
+
workflowId: string;
|
|
35
|
+
activityName: string;
|
|
36
|
+
operationId: string;
|
|
37
|
+
input: TInput;
|
|
38
|
+
idempotencyKey?: string;
|
|
39
|
+
attempt: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Return value for activity verification. Post-execution validation uses a
|
|
43
|
+
* boolean; pre-dispatch reconciliation can report whether a prior keyed side
|
|
44
|
+
* effect completed, did not complete, or is indeterminate.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* import type { ActivityVerificationResult } from '@lostgradient/weft';
|
|
49
|
+
*
|
|
50
|
+
* const result: ActivityVerificationResult<string> = {
|
|
51
|
+
* status: 'completed-with-result',
|
|
52
|
+
* result: 'already-finished',
|
|
53
|
+
* };
|
|
54
|
+
* console.log(result.status);
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export type ActivityVerificationResult<TOutput = unknown> = boolean | 'not-completed' | 'completed-result-unavailable' | 'indeterminate' | {
|
|
58
|
+
status: 'completed-with-result';
|
|
59
|
+
result: TOutput;
|
|
60
|
+
};
|
|
61
|
+
export type ActivityPostExecutionVerifier<TOutput = unknown> = {
|
|
62
|
+
bivarianceHack(result: TOutput): Promise<boolean> | boolean;
|
|
63
|
+
}['bivarianceHack'];
|
|
64
|
+
export type ActivityTier0Verifier<TInput = unknown, TOutput = unknown> = {
|
|
65
|
+
bivarianceHack(result: TOutput | undefined, context: ActivityVerificationContext<TInput>): Promise<ActivityVerificationResult<TOutput>> | ActivityVerificationResult<TOutput>;
|
|
66
|
+
}['bivarianceHack'];
|
|
67
|
+
export type ActivityVerifier<TInput = unknown, TOutput = unknown> = ActivityPostExecutionVerifier<TOutput> | ActivityTier0Verifier<TInput, TOutput>;
|
|
File without changes
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ActivityVerifier } from './activity-verification.ts';
|
|
1
2
|
import type { DefinitionSchema, InferSchemaOutput } from './definition-schema.ts';
|
|
2
3
|
import type { Duration, RetryPolicy } from './retry-retention.ts';
|
|
3
4
|
/**
|
|
@@ -47,6 +48,53 @@ export type ActivityFunction<TInput = unknown, TOutput = unknown> = (input: TInp
|
|
|
47
48
|
export interface ActivityContext {
|
|
48
49
|
signal: AbortSignal;
|
|
49
50
|
heartbeat(details?: unknown): void;
|
|
51
|
+
/**
|
|
52
|
+
* The heartbeat payload recorded by the PREVIOUS attempt of this activity, or
|
|
53
|
+
* `undefined` if there is none. This is the resumable-batch pattern: a
|
|
54
|
+
* long-running activity that calls `ctx.heartbeat({ done: n })` to record its
|
|
55
|
+
* progress can read `ctx.lastHeartbeatDetails` on a retry and skip the work it
|
|
56
|
+
* already finished, instead of re-running from the start and producing
|
|
57
|
+
* duplicate side effects.
|
|
58
|
+
*
|
|
59
|
+
* It is `undefined` on the first attempt, after an engine restart (the value is
|
|
60
|
+
* held in engine memory, never checkpointed), and for worker-executed
|
|
61
|
+
* activities (which run their function out of process and never observe this).
|
|
62
|
+
* Because it is non-durable, treat it as a best-effort optimization: a correct
|
|
63
|
+
* activity must still produce the right result when `lastHeartbeatDetails` is
|
|
64
|
+
* `undefined`. For a durability guarantee, persist progress in workflow state
|
|
65
|
+
* (e.g. one `ctx.run` per batch with an `idempotencyKey`) instead.
|
|
66
|
+
*
|
|
67
|
+
* Only top-level `ctx.run` activities retry, so this is only ever populated
|
|
68
|
+
* there. An activity called inside `ctx.all` / `ctx.race` does not retry, so its
|
|
69
|
+
* `lastHeartbeatDetails` is always `undefined`.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* import { activity, type ActivityContext } from '@lostgradient/weft';
|
|
74
|
+
*
|
|
75
|
+
* function resumeFrom(details: unknown): number {
|
|
76
|
+
* return typeof details === 'object' && details !== null && 'done' in details &&
|
|
77
|
+
* typeof (details as { done: unknown }).done === 'number'
|
|
78
|
+
* ? (details as { done: number }).done
|
|
79
|
+
* : 0;
|
|
80
|
+
* }
|
|
81
|
+
*
|
|
82
|
+
* const postBatches = activity({
|
|
83
|
+
* name: 'postBatches',
|
|
84
|
+
* execute: async (batches: string[][], ctx?: ActivityContext) => {
|
|
85
|
+
* let done = resumeFrom(ctx?.lastHeartbeatDetails);
|
|
86
|
+
* for (; done < batches.length; done += 1) {
|
|
87
|
+
* await postBatch(batches[done]!);
|
|
88
|
+
* ctx?.heartbeat({ done: done + 1 });
|
|
89
|
+
* }
|
|
90
|
+
* return { posted: done };
|
|
91
|
+
* },
|
|
92
|
+
* });
|
|
93
|
+
* declare function postBatch(batch: string[]): Promise<void>;
|
|
94
|
+
* void postBatches;
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
lastHeartbeatDetails?: unknown;
|
|
50
98
|
/**
|
|
51
99
|
* Defer this activity to out-of-band completion. Calling `completeAsync()`
|
|
52
100
|
* hands the work off to an external system — a webhook, a human callback, a
|
|
@@ -120,68 +168,30 @@ export interface ActivityCallOptions {
|
|
|
120
168
|
sticky?: boolean;
|
|
121
169
|
/** Override the default visibility timeout for this invocation. */
|
|
122
170
|
visibilityTimeout?: Duration;
|
|
171
|
+
/**
|
|
172
|
+
* Total wall-clock budget for this activity across ALL retry attempts and the
|
|
173
|
+
* backoff waits between them — close to Temporal's `scheduleToCloseTimeout`.
|
|
174
|
+
* Unlike `timeout` (a per-attempt cap, reset on every attempt), this budget is
|
|
175
|
+
* measured from the first dispatch and is not reset between attempts. When the
|
|
176
|
+
* budget bars the next attempt, the activity fails with an
|
|
177
|
+
* {@link ActivityScheduleToCloseTimeoutError} (a `timeout` failure category).
|
|
178
|
+
*
|
|
179
|
+
* Enforcement is at the **retry decision point**, not by waiting out the clock:
|
|
180
|
+
* the activity fails when the next retry's backoff would start it at or after the
|
|
181
|
+
* deadline (or when an attempt has already overrun the budget), rather than
|
|
182
|
+
* parking for a backoff that is already doomed. So a retry whose backoff would
|
|
183
|
+
* overshoot the budget is skipped immediately even though the actual elapsed time
|
|
184
|
+
* is still under the budget — the error reports the actual elapsed time and the
|
|
185
|
+
* projected next-dispatch that triggered the decision.
|
|
186
|
+
*
|
|
187
|
+
* It has **no effect unless a retry policy is configured** — a non-retried
|
|
188
|
+
* activity fails on its first error before the budget is ever consulted. Use
|
|
189
|
+
* `timeout` to bound a single attempt. It also applies to top-level `ctx.run`
|
|
190
|
+
* activities only; an activity inside `ctx.all` / `ctx.race` does not retry, so
|
|
191
|
+
* this budget never engages there.
|
|
192
|
+
*/
|
|
193
|
+
scheduleToCloseTimeout?: Duration;
|
|
123
194
|
}
|
|
124
|
-
/**
|
|
125
|
-
* Identifies whether an activity verifier is checking a fresh result or
|
|
126
|
-
* reconciling a prior keyed dispatch before redispatch.
|
|
127
|
-
*
|
|
128
|
-
* @example
|
|
129
|
-
* ```ts
|
|
130
|
-
* import type { ActivityVerificationPhase } from '@lostgradient/weft';
|
|
131
|
-
*
|
|
132
|
-
* const phase: ActivityVerificationPhase = 'pre-dispatch-reconciliation';
|
|
133
|
-
* console.log(phase);
|
|
134
|
-
* ```
|
|
135
|
-
*/
|
|
136
|
-
export type ActivityVerificationPhase = 'post-execution-validation' | 'pre-dispatch-reconciliation';
|
|
137
|
-
/**
|
|
138
|
-
* Metadata passed to a Tier-0 activity verifier.
|
|
139
|
-
*
|
|
140
|
-
* @example
|
|
141
|
-
* ```ts
|
|
142
|
-
* import type { ActivityVerificationContext } from '@lostgradient/weft';
|
|
143
|
-
*
|
|
144
|
-
* function shouldQueryExternalSystem(context: ActivityVerificationContext): boolean {
|
|
145
|
-
* return context.phase === 'pre-dispatch-reconciliation';
|
|
146
|
-
* }
|
|
147
|
-
* ```
|
|
148
|
-
*/
|
|
149
|
-
export interface ActivityVerificationContext<TInput = unknown> {
|
|
150
|
-
phase: ActivityVerificationPhase;
|
|
151
|
-
workflowId: string;
|
|
152
|
-
activityName: string;
|
|
153
|
-
operationId: string;
|
|
154
|
-
input: TInput;
|
|
155
|
-
idempotencyKey?: string;
|
|
156
|
-
attempt: number;
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Return value for activity verification. Post-execution validation uses a
|
|
160
|
-
* boolean; pre-dispatch reconciliation can report whether a prior keyed side
|
|
161
|
-
* effect completed, did not complete, or is indeterminate.
|
|
162
|
-
*
|
|
163
|
-
* @example
|
|
164
|
-
* ```ts
|
|
165
|
-
* import type { ActivityVerificationResult } from '@lostgradient/weft';
|
|
166
|
-
*
|
|
167
|
-
* const result: ActivityVerificationResult<string> = {
|
|
168
|
-
* status: 'completed-with-result',
|
|
169
|
-
* result: 'already-finished',
|
|
170
|
-
* };
|
|
171
|
-
* console.log(result.status);
|
|
172
|
-
* ```
|
|
173
|
-
*/
|
|
174
|
-
export type ActivityVerificationResult<TOutput = unknown> = boolean | 'not-completed' | 'completed-result-unavailable' | 'indeterminate' | {
|
|
175
|
-
status: 'completed-with-result';
|
|
176
|
-
result: TOutput;
|
|
177
|
-
};
|
|
178
|
-
export type ActivityPostExecutionVerifier<TOutput = unknown> = {
|
|
179
|
-
bivarianceHack(result: TOutput): Promise<boolean> | boolean;
|
|
180
|
-
}['bivarianceHack'];
|
|
181
|
-
export type ActivityTier0Verifier<TInput = unknown, TOutput = unknown> = {
|
|
182
|
-
bivarianceHack(result: TOutput | undefined, context: ActivityVerificationContext<TInput>): Promise<ActivityVerificationResult<TOutput>> | ActivityVerificationResult<TOutput>;
|
|
183
|
-
}['bivarianceHack'];
|
|
184
|
-
export type ActivityVerifier<TInput = unknown, TOutput = unknown> = ActivityPostExecutionVerifier<TOutput> | ActivityTier0Verifier<TInput, TOutput>;
|
|
185
195
|
/**
|
|
186
196
|
* Full metadata for an activity, combining the execute function with optional
|
|
187
197
|
* retry policy, timeout, queue routing, compensation, and idempotency. Built
|
|
@@ -235,6 +245,15 @@ export interface ActivityDefinition<TInput = unknown, TOutput = unknown, TName e
|
|
|
235
245
|
idempotent?: boolean;
|
|
236
246
|
/** Visibility timeout for this activity. Defaults to 30 seconds. */
|
|
237
247
|
visibilityTimeout?: Duration;
|
|
248
|
+
/**
|
|
249
|
+
* Total wall-clock budget across all retry attempts and their backoff waits,
|
|
250
|
+
* measured from the first dispatch. The per-call {@link ActivityCallOptions.scheduleToCloseTimeout}
|
|
251
|
+
* overrides this default. Enforced at the retry decision point (the activity
|
|
252
|
+
* fails when the next retry would start at or after the deadline, not by waiting
|
|
253
|
+
* out the clock), so it only engages for a retried, top-level `ctx.run` activity.
|
|
254
|
+
* See the per-call option for the full contract.
|
|
255
|
+
*/
|
|
256
|
+
scheduleToCloseTimeout?: Duration;
|
|
238
257
|
/**
|
|
239
258
|
* Optional compensation function. When defined and a saga step that ran this
|
|
240
259
|
* activity needs to be rolled back, the engine calls `compensate(input, output)`
|