@lostgradient/weft 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -24
- package/dist/cli/conformance.js +7 -1
- package/dist/cli/generated/operation-client.generated.d.ts +28 -13
- package/dist/cli/generated/operation-client.generated.js +1 -0
- package/dist/cli/help-text.d.ts +1 -1
- package/dist/cli/help-text.js +1 -0
- package/dist/cli/operation-catalog-snapshot.d.ts +8 -0
- package/dist/cli/operation-catalog-snapshot.js +11 -0
- package/dist/cli/parse-schedule-arguments.js +3 -1
- package/dist/cli/schedule.js +2 -1
- package/dist/cli/types.d.ts +1 -0
- package/dist/cli-main.js +79 -78
- package/dist/client/handle-delegation.d.ts +3 -2
- package/dist/client/handle-delegation.js +3 -1
- package/dist/client/http-client-requests.d.ts +2 -1
- package/dist/client/http-client-requests.js +7 -0
- package/dist/client/http-client.d.ts +9 -6
- package/dist/client/http-client.js +10 -1
- package/dist/client/http-request.d.ts +11 -1
- package/dist/client/http-request.js +17 -7
- package/dist/client/index.d.ts +1 -1
- package/dist/client/interface.d.ts +46 -5
- package/dist/client/local.d.ts +4 -1
- package/dist/client/local.js +12 -4
- package/dist/client/start-body.d.ts +4 -3
- package/dist/core/byte-arrays.d.ts +5 -0
- package/dist/core/byte-arrays.js +5 -0
- package/dist/core/checkpoint/lifecycle.d.ts +3 -0
- package/dist/core/checkpoint/lifecycle.js +9 -4
- package/dist/core/checkpoint/serialization.js +12 -5
- package/dist/core/codec/extension-codec.d.ts +16 -0
- package/dist/core/codec/extension-codec.js +100 -6
- package/dist/core/context/activity-retry-state.d.ts +38 -0
- package/dist/core/context/activity-retry-state.js +89 -0
- package/dist/core/context/activity-schedule-to-close.d.ts +159 -0
- package/dist/core/context/activity-schedule-to-close.js +69 -0
- package/dist/core/context/child-workflow-pipe.d.ts +5 -5
- package/dist/core/context/child-workflow-pipe.js +15 -2
- package/dist/core/context/context-presence.d.ts +19 -0
- package/dist/core/context/context-presence.js +13 -0
- package/dist/core/context/durable-operations.d.ts +25 -0
- package/dist/core/context/durable-operations.js +64 -0
- package/dist/core/context/index.d.ts +9 -5
- package/dist/core/context/index.js +17 -12
- package/dist/core/context/internals.d.ts +20 -0
- package/dist/core/context/internals.js +3 -1
- package/dist/core/context/operation-request.d.ts +35 -0
- package/dist/core/context/parallel-cache-entry.d.ts +14 -5
- package/dist/core/context/run-operation.d.ts +6 -1
- package/dist/core/context/run-operation.js +41 -87
- package/dist/core/context/session-state.js +7 -8
- package/dist/core/context/speculative-child.js +2 -0
- package/dist/core/context/types.d.ts +15 -0
- package/dist/core/context/version-patching.d.ts +8 -0
- package/dist/core/context/version-patching.js +40 -0
- package/dist/core/context/workflow-logger.d.ts +98 -0
- package/dist/core/context/workflow-logger.js +68 -0
- package/dist/core/engine/activity-heartbeat-tracking.d.ts +64 -0
- package/dist/core/engine/activity-heartbeat-tracking.js +42 -0
- package/dist/core/engine/activity-per-attempt-timeout.d.ts +41 -0
- package/dist/core/engine/activity-per-attempt-timeout.js +36 -0
- package/dist/core/engine/activity-reconciliation.d.ts +1 -0
- package/dist/core/engine/activity-reconciliation.js +12 -1
- package/dist/core/engine/activity-resolution.d.ts +23 -0
- package/dist/core/engine/activity-resolution.js +37 -0
- package/dist/core/engine/aggregate.js +66 -30
- package/dist/core/engine/async-activity-completion.d.ts +23 -6
- package/dist/core/engine/async-activity-completion.js +53 -12
- package/dist/core/engine/attributes-tags.js +9 -4
- package/dist/core/engine/bulk-operations-purge.d.ts +26 -0
- package/dist/core/engine/bulk-operations-purge.js +38 -3
- package/dist/core/engine/bulk-operations-shared.d.ts +2 -0
- package/dist/core/engine/bulk-operations-shared.js +8 -2
- package/dist/core/engine/bulk-operations.d.ts +4 -1
- package/dist/core/engine/bulk-operations.js +235 -24
- package/dist/core/engine/callback-creators-bundles.d.ts +9 -0
- package/dist/core/engine/callback-creators-bundles.js +30 -2
- package/dist/core/engine/callback-creators-core.js +6 -4
- package/dist/core/engine/callback-creators-router.js +10 -0
- package/dist/core/engine/callback-creators-schedule.d.ts +2 -2
- package/dist/core/engine/callback-creators-schedule.js +12 -8
- package/dist/core/engine/candidate-read-batching.d.ts +6 -0
- package/dist/core/engine/candidate-read-batching.js +1 -0
- package/dist/core/engine/checkpoint-io.js +61 -25
- package/dist/core/engine/checkpoint-reads.js +3 -2
- package/dist/core/engine/checkpoint-replay.d.ts +20 -0
- package/dist/core/engine/checkpoint-replay.js +242 -0
- package/dist/core/engine/checkpoint-side-effects.d.ts +23 -0
- package/dist/core/engine/checkpoint-side-effects.js +35 -0
- package/dist/core/engine/child-workflow-cancellation.d.ts +10 -0
- package/dist/core/engine/child-workflow-cancellation.js +40 -0
- package/dist/core/engine/child-workflow.js +27 -4
- package/dist/core/engine/condition-waiters.d.ts +14 -0
- package/dist/core/engine/condition-waiters.js +5 -0
- package/dist/core/engine/construction.d.ts +3 -0
- package/dist/core/engine/construction.js +21 -8
- package/dist/core/engine/coordination-branch-executors.d.ts +70 -0
- package/dist/core/engine/coordination-branch-executors.js +107 -0
- package/dist/core/engine/deferred-consume-envelope.d.ts +59 -0
- package/dist/core/engine/deferred-consume-envelope.js +14 -0
- package/dist/core/engine/disposal.js +13 -0
- package/dist/core/engine/engine-create-types.d.ts +14 -4
- package/dist/core/engine/engine-internal-types.d.ts +26 -3
- package/dist/core/engine/errors.d.ts +47 -0
- package/dist/core/engine/errors.js +20 -0
- package/dist/core/engine/event-log-compaction.d.ts +8 -0
- package/dist/core/engine/event-log-compaction.js +20 -2
- package/dist/core/engine/fenced-write.d.ts +65 -0
- package/dist/core/engine/fenced-write.js +71 -0
- package/dist/core/engine/finalizer-state.d.ts +28 -0
- package/dist/core/engine/finalizer-state.js +16 -0
- package/dist/core/engine/handles.d.ts +8 -0
- package/dist/core/engine/index.d.ts +34 -16
- package/dist/core/engine/index.js +133 -8
- package/dist/core/engine/inline-parking.js +3 -2
- package/dist/core/engine/internals.d.ts +107 -3
- package/dist/core/engine/lease-codec.d.ts +35 -0
- package/dist/core/engine/lease-codec.js +32 -0
- package/dist/core/engine/lease-deposition.d.ts +66 -0
- package/dist/core/engine/lease-deposition.js +10 -0
- package/dist/core/engine/lease-errors.d.ts +99 -0
- package/dist/core/engine/lease-errors.js +30 -0
- package/dist/core/engine/lease-manager.d.ts +114 -0
- package/dist/core/engine/lease-manager.js +135 -0
- package/dist/core/engine/lifecycle/persist.js +10 -32
- package/dist/core/engine/lifecycle/recovered-services.d.ts +8 -6
- package/dist/core/engine/lifecycle/recovered-services.js +18 -3
- package/dist/core/engine/lifecycle/resume.js +16 -9
- package/dist/core/engine/lifecycle/shared.d.ts +8 -1
- package/dist/core/engine/lifecycle/start-batch.d.ts +1 -1
- package/dist/core/engine/lifecycle/start-batch.js +2 -1
- package/dist/core/engine/lifecycle/start-commit.d.ts +9 -0
- package/dist/core/engine/lifecycle/start-commit.js +50 -8
- package/dist/core/engine/lifecycle/start-or-signal-create.d.ts +58 -0
- package/dist/core/engine/lifecycle/start-or-signal-create.js +95 -0
- package/dist/core/engine/lifecycle/start-or-signal.d.ts +3 -2
- package/dist/core/engine/lifecycle/start-or-signal.js +11 -81
- package/dist/core/engine/lifecycle/start-terminal-conflict-purge.d.ts +39 -0
- package/dist/core/engine/lifecycle/start-terminal-conflict-purge.js +28 -0
- package/dist/core/engine/lifecycle/start.d.ts +4 -4
- package/dist/core/engine/lifecycle/start.js +17 -9
- package/dist/core/engine/lifecycle/transition.js +17 -5
- package/dist/core/engine/lifecycle.d.ts +1 -1
- package/dist/core/engine/list-candidate-resolution.js +2 -2
- package/dist/core/engine/listing.js +9 -5
- package/dist/core/engine/operations-activity.d.ts +4 -11
- package/dist/core/engine/operations-activity.js +22 -49
- package/dist/core/engine/operations-coordination.d.ts +10 -0
- package/dist/core/engine/operations-coordination.js +43 -8
- package/dist/core/engine/operations-router.d.ts +6 -0
- package/dist/core/engine/operations-router.js +2 -0
- package/dist/core/engine/operations-speculate.js +6 -2
- package/dist/core/engine/operations-stream.js +12 -2
- package/dist/core/engine/operations-time.d.ts +4 -2
- package/dist/core/engine/operations-time.js +14 -2
- package/dist/core/engine/operations-wait-condition.d.ts +23 -0
- package/dist/core/engine/operations-wait-condition.js +62 -0
- package/dist/core/engine/ownership-options.d.ts +23 -0
- package/dist/core/engine/ownership-options.js +26 -0
- package/dist/core/engine/payload-size-policy.d.ts +3 -0
- package/dist/core/engine/payload-size-policy.js +4 -0
- package/dist/core/engine/pending-updates.d.ts +17 -0
- package/dist/core/engine/pending-updates.js +33 -11
- package/dist/core/engine/queries.js +1 -1
- package/dist/core/engine/registration.d.ts +1 -0
- package/dist/core/engine/registration.js +18 -3
- package/dist/core/engine/schedule-jitter.d.ts +5 -0
- package/dist/core/engine/schedule-jitter.js +10 -0
- package/dist/core/engine/schedule-run.d.ts +17 -0
- package/dist/core/engine/schedule-run.js +38 -0
- package/dist/core/engine/schedule-timer.js +81 -17
- package/dist/core/engine/schedules.d.ts +7 -4
- package/dist/core/engine/schedules.js +37 -16
- package/dist/core/engine/search-attribute-records.d.ts +4 -0
- package/dist/core/engine/search-attribute-records.js +17 -0
- package/dist/core/engine/signals.d.ts +18 -2
- package/dist/core/engine/signals.js +42 -21
- package/dist/core/engine/state-utilities.d.ts +49 -2
- package/dist/core/engine/state-utilities.js +114 -3
- package/dist/core/engine/storage-io.d.ts +16 -2
- package/dist/core/engine/storage-io.js +26 -5
- package/dist/core/engine/stream-chunk-loading.d.ts +2 -0
- package/dist/core/engine/stream-chunk-loading.js +24 -1
- package/dist/core/engine/sub-operation.js +22 -3
- package/dist/core/engine/termination/cleanup.d.ts +3 -1
- package/dist/core/engine/termination/cleanup.js +25 -1
- package/dist/core/engine/termination/complete.js +44 -6
- package/dist/core/engine/termination/finalizer-activity.d.ts +53 -0
- package/dist/core/engine/termination/finalizer-activity.js +30 -0
- package/dist/core/engine/termination/finalizer-claim.d.ts +110 -0
- package/dist/core/engine/termination/finalizer-claim.js +80 -0
- package/dist/core/engine/termination/finalizer.d.ts +48 -0
- package/dist/core/engine/termination/finalizer.js +159 -0
- package/dist/core/engine/termination/suspend.d.ts +3 -1
- package/dist/core/engine/termination.d.ts +1 -0
- package/dist/core/engine/termination.js +4 -0
- package/dist/core/engine/updates.js +5 -25
- package/dist/core/engine/validation/schedule.d.ts +2 -1
- package/dist/core/engine/validation/schedule.js +51 -2
- package/dist/core/engine/validation.js +32 -5
- package/dist/core/engine/waiting-update-response.d.ts +8 -0
- package/dist/core/engine/waiting-update-response.js +22 -0
- package/dist/core/engine/workflow-concurrency.d.ts +10 -0
- package/dist/core/engine/workflow-concurrency.js +136 -0
- package/dist/core/engine/workflow-feed.d.ts +4 -5
- package/dist/core/engine/workflow-feed.js +4 -1
- package/dist/core/engine/workflow-indexes.d.ts +9 -0
- package/dist/core/engine/workflow-indexes.js +10 -0
- package/dist/core/engine/workflow-state-stream.js +33 -13
- package/dist/core/engine/workflow-visibility-queries.d.ts +2 -2
- package/dist/core/engine-helpers.js +1 -0
- package/dist/core/events/activity-events.d.ts +43 -12
- package/dist/core/events/activity-events.js +28 -0
- package/dist/core/events/attribute-events.d.ts +2 -3
- package/dist/core/events/event-map.d.ts +18 -12
- package/dist/core/events/index.d.ts +1 -0
- package/dist/core/events/index.js +1 -0
- package/dist/core/events/schedule-events.d.ts +71 -0
- package/dist/core/events/schedule-events.js +29 -0
- package/dist/core/events/signal-events.d.ts +4 -6
- package/dist/core/events/system-events.d.ts +29 -19
- package/dist/core/events/system-events.js +26 -0
- package/dist/core/events/update-events.d.ts +6 -8
- package/dist/core/events/workflow-events.d.ts +88 -23
- package/dist/core/events/workflow-events.js +26 -0
- package/dist/core/failure-categories.js +5 -17
- package/dist/core/fault-code.d.ts +9 -3
- package/dist/core/fault-code.js +1 -0
- package/dist/core/inline-execution-strategy.context-options.d.ts +69 -0
- package/dist/core/inline-execution-strategy.context-options.js +56 -0
- package/dist/core/inline-execution-strategy.d.ts +31 -36
- package/dist/core/inline-execution-strategy.js +16 -27
- package/dist/core/list-filter-validation.d.ts +1 -1
- package/dist/core/payload-size.d.ts +1 -1
- package/dist/core/persisted-data-incompatible-error.d.ts +9 -7
- package/dist/core/review/events.d.ts +6 -8
- package/dist/core/scheduler/scheduler-class.d.ts +10 -1
- package/dist/core/scheduler/scheduler-class.js +38 -11
- package/dist/core/scheduler/timer-batch.js +9 -1
- package/dist/core/scheduler/timer-sources.d.ts +1 -0
- package/dist/core/scheduler/timer-sources.js +11 -5
- package/dist/core/session-state.d.ts +0 -1
- package/dist/core/session-state.js +2 -2
- package/dist/core/start-workflow-validation.d.ts +34 -0
- package/dist/core/start-workflow-validation.js +19 -0
- package/dist/core/types/activity-verification.d.ts +67 -0
- package/dist/core/types/activity-verification.js +0 -0
- package/dist/core/types/activity.d.ts +80 -61
- package/dist/core/types/bulk.d.ts +50 -9
- package/dist/core/types/checkpoint.d.ts +44 -8
- package/dist/core/types/list-options.d.ts +146 -0
- package/dist/core/types/list-options.js +0 -0
- package/dist/core/types/options.d.ts +121 -165
- package/dist/core/types/schedules.d.ts +39 -3
- package/dist/core/types/services-resolution.d.ts +2 -2
- package/dist/core/types/workflow-builder-runtime.d.ts +12 -3
- package/dist/core/types/workflow-builder-runtime.js +11 -2
- package/dist/core/types/workflow-builder.d.ts +42 -11
- package/dist/core/types/workflow-concurrency.d.ts +39 -0
- package/dist/core/types/workflow-concurrency.js +0 -0
- package/dist/core/types/workflow-context.d.ts +157 -14
- package/dist/core/types/workflow-definition.d.ts +53 -10
- package/dist/core/types/workflow-function.d.ts +84 -9
- package/dist/core/types/workflow-log.d.ts +98 -0
- package/dist/core/types/workflow-log.js +0 -0
- package/dist/core/types/workflow-registries.d.ts +14 -3
- package/dist/core/types/workflow-registry.d.ts +3 -0
- package/dist/core/types.d.ts +4 -0
- package/dist/core/types.js +4 -0
- package/dist/core/versioning.d.ts +9 -39
- package/dist/core/versioning.js +2 -12
- package/dist/core/weft-error.d.ts +44 -1
- package/dist/core/weft-error.js +16 -0
- package/dist/core/worker-execution-strategy-options.d.ts +26 -0
- package/dist/core/worker-execution-strategy.js +40 -36
- package/dist/core/worker-inbound-message.d.ts +38 -0
- package/dist/core/worker-inbound-message.js +37 -0
- package/dist/core/worker-log-abuse-counter.d.ts +175 -0
- package/dist/core/worker-log-abuse-counter.js +107 -0
- package/dist/core/worker-message-helpers.d.ts +47 -0
- package/dist/core/worker-message-helpers.js +26 -0
- package/dist/core/worker-protocol-guard.js +1 -1
- package/dist/core/worker-protocol-log.d.ts +56 -0
- package/dist/core/worker-protocol-log.js +18 -0
- package/dist/core/worker-protocol.d.ts +23 -0
- package/dist/core/worker-protocol.js +12 -2
- package/dist/core/workflow-version-tuple.d.ts +3 -9
- package/dist/core/workflow-version-tuple.js +2 -3
- package/dist/diagnostics/format.js +1 -6
- package/dist/diagnostics/types.d.ts +4 -5
- package/dist/diagnostics/validate.d.ts +0 -1
- package/dist/diagnostics/version-check.d.ts +1 -1
- package/dist/diagnostics/version-check.js +4 -9
- package/dist/index.d.ts +12 -10
- package/dist/index.js +29 -3
- package/dist/json-schema.js +3 -3
- package/dist/mcp/cli.js +27 -27
- package/dist/mcp/dispatcher.js +1 -1
- package/dist/mcp/http.js +16 -6
- package/dist/mcp/protocol.d.ts +2 -0
- package/dist/mcp/protocol.js +1 -1
- package/dist/mcp/session.d.ts +16 -0
- package/dist/mcp/session.js +59 -6
- package/dist/mcp/tools.js +73 -6
- package/dist/observability/index.js +2 -2
- package/dist/server/asyncapi-channels.js +5 -2
- package/dist/server/attribute-filters.d.ts +8 -3
- package/dist/server/attribute-filters.js +6 -1
- package/dist/server/authentication/api-key.d.ts +2 -1
- package/dist/server/authentication/api-key.js +5 -2
- package/dist/server/authentication/constant-time-api-key.d.ts +15 -0
- package/dist/server/authentication/constant-time-api-key.js +24 -0
- package/dist/server/authentication/index.d.ts +1 -1
- package/dist/server/authentication/index.js +7 -4
- package/dist/server/authentication/rotating-api-key-store.d.ts +5 -3
- package/dist/server/authentication/rotating-api-key-store.js +19 -11
- package/dist/server/engine-event-feed-backend.d.ts +4 -5
- package/dist/server/fault-to-http.js +8 -1
- package/dist/server/fault-to-json-rpc.js +1 -0
- package/dist/server/fleet-event-feed.d.ts +31 -0
- package/dist/server/fleet-event-feed.js +157 -0
- package/dist/server/handler/index.js +1 -1
- package/dist/server/handler/response-helpers.js +2 -1
- package/dist/server/handler/route-dispatch.d.ts +6 -3
- package/dist/server/handler/route-dispatch.js +2 -2
- package/dist/server/handler.js +23 -23
- package/dist/server/index.d.ts +32 -2
- package/dist/server/index.js +26 -26
- package/dist/server/json-rpc-transport-helpers.d.ts +1 -0
- package/dist/server/json-rpc-transport-helpers.js +2 -1
- package/dist/server/json-rpc-websocket-runtime.d.ts +11 -2
- package/dist/server/json-rpc-websocket-runtime.js +1 -0
- package/dist/server/json-rpc-websocket-subscriptions.d.ts +10 -0
- package/dist/server/json-rpc-websocket-subscriptions.js +29 -0
- package/dist/server/json-rpc-websocket-types.d.ts +22 -0
- package/dist/server/json-rpc-websocket-types.js +0 -0
- package/dist/server/json-rpc-websocket-validation.js +20 -4
- package/dist/server/json-rpc-websocket.d.ts +2 -43
- package/dist/server/json-rpc-websocket.js +57 -74
- package/dist/server/openapi.d.ts +2 -1
- package/dist/server/openapi.js +1 -3
- package/dist/server/openrpc-document-schema.d.ts +78 -0
- package/dist/server/openrpc-document-schema.js +27 -1
- package/dist/server/openrpc-errors.d.ts +3 -0
- package/dist/server/openrpc-errors.js +2 -1
- package/dist/server/openrpc.js +32 -0
- package/dist/server/operation-catalog/index.d.ts +1 -1
- package/dist/server/operation-catalog/pipeline-helpers.js +1 -0
- package/dist/server/operation-catalog/pipeline-stages.js +26 -12
- package/dist/server/operation-catalog/pipeline.js +8 -1
- package/dist/server/operation-catalog/registry.js +13 -0
- package/dist/server/operation-catalog/types.d.ts +20 -9
- package/dist/server/operation-fault.d.ts +10 -0
- package/dist/server/operation-fault.js +2 -0
- package/dist/server/operation-registry.d.ts +12 -11
- package/dist/server/operation-registry.js +12 -3
- package/dist/server/operations/aggregate-workflows.d.ts +15 -15
- package/dist/server/operations/async-activity.d.ts +2 -2
- package/dist/server/operations/async-activity.js +12 -7
- package/dist/server/operations/bulk-cancel-workflows.d.ts +1 -1
- package/dist/server/operations/bulk-cancel-workflows.js +2 -2
- package/dist/server/operations/bulk-delete-workflows.d.ts +1 -1
- package/dist/server/operations/bulk-delete-workflows.js +2 -2
- package/dist/server/operations/bulk-filter-helpers.d.ts +8 -6
- package/dist/server/operations/bulk-filter-helpers.js +54 -24
- package/dist/server/operations/bulk-mutate-workflow-tags.d.ts +11 -9
- package/dist/server/operations/bulk-mutate-workflow-tags.js +2 -2
- package/dist/server/operations/bulk-operation-helpers.d.ts +2 -2
- package/dist/server/operations/bulk-retry-failed-workflows.d.ts +7 -0
- package/dist/server/operations/bulk-retry-failed-workflows.js +64 -0
- package/dist/server/operations/bulk-signal-workflows.d.ts +11 -9
- package/dist/server/operations/bulk-signal-workflows.js +2 -2
- package/dist/server/operations/cancel-schedule.d.ts +1 -1
- package/dist/server/operations/create-schedule.d.ts +3 -1
- package/dist/server/operations/create-schedule.js +29 -11
- package/dist/server/operations/fleet-events-subscription.d.ts +54 -0
- package/dist/server/operations/fleet-events-subscription.js +99 -0
- package/dist/server/operations/fork-workflow.d.ts +1 -1
- package/dist/server/operations/fork-workflow.js +3 -2
- package/dist/server/operations/get-checkpoint-at.d.ts +1 -1
- package/dist/server/operations/get-registry.d.ts +1 -1
- package/dist/server/operations/get-retention-overview.d.ts +1 -1
- package/dist/server/operations/get-review.d.ts +1 -1
- package/dist/server/operations/get-schedule.d.ts +1 -1
- package/dist/server/operations/get-stream-chunks.d.ts +1 -1
- package/dist/server/operations/get-system-metrics.d.ts +2 -2
- package/dist/server/operations/get-task-diagnostics.d.ts +45 -6
- package/dist/server/operations/get-task-diagnostics.js +101 -7
- package/dist/server/operations/get-update-result.d.ts +1 -1
- package/dist/server/operations/get-workflow-attributes.d.ts +1 -1
- package/dist/server/operations/get-workflow-events.d.ts +1 -1
- package/dist/server/operations/get-workflow-result.d.ts +1 -1
- package/dist/server/operations/get-workflow-timeline.d.ts +1 -1
- package/dist/server/operations/get-workflow.d.ts +1 -1
- package/dist/server/operations/list-checkpoints.d.ts +1 -1
- package/dist/server/operations/list-reviews.d.ts +1 -1
- package/dist/server/operations/list-schedules.d.ts +1 -1
- package/dist/server/operations/list-task-queues.d.ts +2 -2
- package/dist/server/operations/list-workers.d.ts +2 -2
- package/dist/server/operations/list-workflows.d.ts +1 -1
- package/dist/server/operations/operation-helpers.d.ts +16 -1
- package/dist/server/operations/operation-helpers.js +15 -3
- package/dist/server/operations/pause-schedule.d.ts +1 -1
- package/dist/server/operations/purge-workflows.d.ts +5 -5
- package/dist/server/operations/purge-workflows.js +2 -2
- package/dist/server/operations/query-workflow.d.ts +1 -1
- package/dist/server/operations/query-workflow.js +3 -2
- package/dist/server/operations/recover-all.d.ts +1 -1
- package/dist/server/operations/replay-workflow.d.ts +1 -1
- package/dist/server/operations/resume-schedule.d.ts +1 -1
- package/dist/server/operations/set-workflow-attributes.d.ts +1 -1
- package/dist/server/operations/set-workflow-attributes.js +6 -3
- package/dist/server/operations/signal-workflow.js +8 -3
- package/dist/server/operations/single-workflow-tag-mutation.js +13 -3
- package/dist/server/operations/start-or-signal-workflow.d.ts +6 -1
- package/dist/server/operations/start-or-signal-workflow.js +14 -24
- package/dist/server/operations/start-workflow-options.d.ts +6 -0
- package/dist/server/operations/start-workflow-rest-input.d.ts +14 -0
- package/dist/server/operations/start-workflow-rest-input.js +31 -0
- package/dist/server/operations/start-workflow.d.ts +1 -1
- package/dist/server/operations/start-workflow.js +8 -23
- package/dist/server/operations/storage.d.ts +6 -6
- package/dist/server/operations/storage.js +24 -14
- package/dist/server/operations/stream-workflow-sse.d.ts +1 -1
- package/dist/server/operations/submit-review-decision.d.ts +1 -1
- package/dist/server/operations/submit-review-decision.js +6 -3
- package/dist/server/operations/update-schedule.d.ts +1 -1
- package/dist/server/operations/update-schedule.js +7 -4
- package/dist/server/operations/update-workflow.d.ts +1 -1
- package/dist/server/operations/update-workflow.js +7 -3
- package/dist/server/operations/worker-drain.d.ts +8 -8
- package/dist/server/operations/worker-drain.js +11 -8
- package/dist/server/operations/workflow-events-subscription.d.ts +7 -8
- package/dist/server/operations/workflow-events-subscription.js +43 -8
- package/dist/server/rest-binding.d.ts +3 -1
- package/dist/server/rest-bindings.js +12 -0
- package/dist/server/rest-body.d.ts +10 -0
- package/dist/server/rest-body.js +80 -0
- package/dist/server/runtime/authentication-bridge.d.ts +1 -0
- package/dist/server/runtime/authentication-bridge.js +33 -6
- package/dist/server/runtime/client-visible-events.d.ts +3 -0
- package/dist/server/runtime/client-visible-events.js +65 -0
- package/dist/server/runtime/context.d.ts +7 -0
- package/dist/server/runtime/event-broadcasting.d.ts +6 -0
- package/dist/server/runtime/event-broadcasting.js +72 -38
- package/dist/server/runtime/retry.d.ts +1 -0
- package/dist/server/runtime/retry.js +14 -0
- package/dist/server/runtime/shutdown.d.ts +7 -6
- package/dist/server/runtime/shutdown.js +6 -1
- package/dist/server/runtime/task-polling.js +61 -20
- package/dist/server/runtime/task-reconciliation.js +9 -1
- package/dist/server/runtime/task-result-resolution.d.ts +15 -0
- package/dist/server/runtime/task-result-resolution.js +81 -0
- package/dist/server/runtime/websocket-stream.d.ts +20 -1
- package/dist/server/runtime/websocket-stream.js +173 -7
- package/dist/server/runtime/websocket-upgrade.js +22 -3
- package/dist/server/runtime/websocket-worker.d.ts +1 -1
- package/dist/server/runtime/websocket-worker.js +38 -30
- package/dist/server/serve-internals.d.ts +3 -1
- package/dist/server/serve-internals.js +18 -2
- package/dist/server/task-state.d.ts +30 -0
- package/dist/server/task-state.js +28 -0
- package/dist/server/workflow-event-feed.d.ts +36 -115
- package/dist/server/workflow-event-feed.js +92 -27
- package/dist/service-worker/index.js +30 -30
- package/dist/storage/auto.js +1 -1
- package/dist/storage/bun-sql.js +24 -0
- package/dist/storage/compressed-storage.js +1 -1
- package/dist/storage/default-scope.d.ts +7 -4
- package/dist/storage/http.js +2 -2
- package/dist/storage/index.d.ts +76 -4
- package/dist/storage/indexeddb.js +1 -1
- package/dist/storage/interface.d.ts +163 -0
- package/dist/storage/interface.js +1 -1
- package/dist/storage/key-prefixes.d.ts +1 -1
- package/dist/storage/key-prefixes.js +10 -0
- package/dist/storage/lmdb.d.ts +4 -3
- package/dist/storage/lmdb.js +1 -1
- package/dist/storage/memory.js +1 -1
- package/dist/storage/neon-batch.d.ts +30 -0
- package/dist/storage/neon-batch.js +30 -0
- package/dist/storage/neon-value-mapping.d.ts +30 -3
- package/dist/storage/neon-value-mapping.js +12 -0
- package/dist/storage/neon.d.ts +16 -0
- package/dist/storage/neon.js +9 -4
- package/dist/storage/node-sqlite.js +23 -0
- package/dist/storage/postgres-key-value-queries.d.ts +69 -44
- package/dist/storage/postgres-key-value-queries.js +62 -24
- package/dist/storage/resolve.js +1 -1
- package/dist/storage/scoped-storage.js +1 -1
- package/dist/storage/testing.d.ts +168 -0
- package/dist/storage/testing.js +2 -0
- package/dist/storage/turso.d.ts +8 -0
- package/dist/storage/turso.js +2 -2
- package/dist/storage/typed-storage.js +1 -1
- package/dist/storage/web-extension.js +1 -1
- package/dist/testing/index.js +28 -28
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker/protocol.js +1 -1
- package/dist/workers/worker-replay-state.d.ts +32 -0
- package/dist/workers/worker-replay-state.js +35 -0
- package/dist/workers/worker-state-namespace.d.ts +21 -0
- package/dist/workers/worker-state-namespace.js +13 -0
- package/dist/workers/workflow-runner.d.ts +19 -15
- package/dist/workers/workflow-runner.js +72 -60
- package/dist/workers/workflow-worker-entry.js +5 -2
- package/package.json +5 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Engine } from '../../core/engine.ts';
|
|
2
|
+
import type { FleetEventFeed } from '../fleet-event-feed.ts';
|
|
2
3
|
import type { ServerContext } from './context.ts';
|
|
3
4
|
/**
|
|
4
5
|
* Result of wiring up engine-to-WebSocket event broadcasting.
|
|
@@ -46,6 +47,9 @@ export declare function registerWorkflowEventLifecycle(engine: Engine, context:
|
|
|
46
47
|
* token messages, enabling per-workflow stream sockets to be used in
|
|
47
48
|
* place of the default pub/sub channel. Leave unset unless you manage stream
|
|
48
49
|
* sockets separately (as `serve()` does internally).
|
|
50
|
+
* @param options.publishWatchMessage - Optional override for watch-event delivery.
|
|
51
|
+
* When provided, this callback is called instead of `server.publish()` for
|
|
52
|
+
* watch messages, enabling per-socket replay buffering during catch-up.
|
|
49
53
|
*
|
|
50
54
|
* @example
|
|
51
55
|
* ```ts
|
|
@@ -68,4 +72,6 @@ export declare function registerWorkflowEventLifecycle(engine: Engine, context:
|
|
|
68
72
|
*/
|
|
69
73
|
export declare function wireEventBroadcasting(engine: Engine, server: ReturnType<typeof Bun.serve>, options?: {
|
|
70
74
|
publishTokenMessage?: (workflowId: string, sequence: number, message: string) => void;
|
|
75
|
+
publishWatchMessage?: (workflowId: string, sequence: number, message: string) => void;
|
|
76
|
+
fleetEventFeed?: FleetEventFeed;
|
|
71
77
|
}): EventBroadcastingHandle;
|
|
@@ -1,24 +1,19 @@
|
|
|
1
1
|
import { encode } from "../../core/codec.js";
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
SignalDeliveredEvent,
|
|
8
|
-
SignalReceivedEvent,
|
|
9
|
-
UpdateCompletedEvent,
|
|
10
|
-
UpdateReceivedEvent,
|
|
3
|
+
encodeStoredStreamTailSequence,
|
|
4
|
+
loadStoredStreamTailSequence
|
|
5
|
+
} from "../../core/engine/stream-chunk-loading.js";
|
|
6
|
+
import {
|
|
11
7
|
WorkflowCancelledEvent,
|
|
12
8
|
WorkflowCompletedEvent,
|
|
13
9
|
WorkflowFailedEvent,
|
|
14
|
-
WorkflowStartedEvent,
|
|
15
10
|
WorkflowTimedOutEvent
|
|
16
11
|
} from "../../core/events.js";
|
|
17
12
|
import { KEYS } from "../../storage/interface.js";
|
|
18
13
|
import { claimNextSequence } from "../runtime-helpers.js";
|
|
14
|
+
import { CLIENT_VISIBLE_EVENT_TYPES, TOKEN_EVENT_TYPE } from "./client-visible-events.js";
|
|
19
15
|
import { cancelTask } from "./task-dispatch.js";
|
|
20
16
|
import { withRetry } from "./websocket-worker.js";
|
|
21
|
-
const TOKEN_EVENT_TYPE = "stream:token";
|
|
22
17
|
function workflowChannelPath(workflowId, connectionType) {
|
|
23
18
|
return `/v1/workflows/${encodeURIComponent(workflowId)}/${connectionType}`;
|
|
24
19
|
}
|
|
@@ -106,6 +101,11 @@ export function wireEventBroadcasting(engine, server, options) {
|
|
|
106
101
|
if (existing)
|
|
107
102
|
return existing;
|
|
108
103
|
const promise = (async () => {
|
|
104
|
+
const storedTailSequence = await loadStoredStreamTailSequence(engine.storage, workflowId, "tokens");
|
|
105
|
+
if (storedTailSequence !== null) {
|
|
106
|
+
tokenSequenceCounters.set(workflowId, storedTailSequence + 1);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
109
|
const prefix = KEYS.streamChunkPrefix(workflowId, "tokens");
|
|
110
110
|
let highestSequence = -1;
|
|
111
111
|
for await (const [key] of engine.storage.scan(prefix, { reverse: !0, limit: 1 })) {
|
|
@@ -122,11 +122,7 @@ export function wireEventBroadcasting(engine, server, options) {
|
|
|
122
122
|
return promise;
|
|
123
123
|
}
|
|
124
124
|
async function persistAndPublishEvent(workflowId, eventType, message) {
|
|
125
|
-
|
|
126
|
-
const parsed = JSON.parse(message), sequence = claimNextSequence(sequenceCounters, workflowId), storageKey = KEYS.event(workflowId, sequence), encoded = encode(parsed);
|
|
127
|
-
await withRetry(async () => engine.storage.put(storageKey, encoded), `persist event "${eventType}" for workflow "${workflowId}"`);
|
|
128
|
-
const watchChannel = workflowChannelPath(workflowId, "watch");
|
|
129
|
-
server.publish(watchChannel, message);
|
|
125
|
+
const parsed = JSON.parse(message);
|
|
130
126
|
if (eventType === TOKEN_EVENT_TYPE) {
|
|
131
127
|
const tokenPayload = {
|
|
132
128
|
workflowId: typeof parsed.data.workflowId === "string" ? parsed.data.workflowId : workflowId,
|
|
@@ -135,10 +131,23 @@ export function wireEventBroadcasting(engine, server, options) {
|
|
|
135
131
|
};
|
|
136
132
|
await ensureTokenSequenceInitialized(workflowId);
|
|
137
133
|
const tokenSequence = claimNextSequence(tokenSequenceCounters, workflowId);
|
|
138
|
-
await withRetry(async () => engine.storage.
|
|
134
|
+
await withRetry(async () => engine.storage.batch([
|
|
135
|
+
{
|
|
136
|
+
type: "put",
|
|
137
|
+
key: KEYS.streamChunk(workflowId, "tokens", tokenSequence),
|
|
138
|
+
value: encode(tokenPayload)
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
type: "put",
|
|
142
|
+
key: KEYS.streamTail(workflowId, "tokens"),
|
|
143
|
+
value: encodeStoredStreamTailSequence(tokenSequence)
|
|
144
|
+
}
|
|
145
|
+
]), `persist token stream chunk for workflow "${workflowId}"`);
|
|
139
146
|
const streamMessage = JSON.stringify({
|
|
140
|
-
|
|
147
|
+
type: parsed.type,
|
|
148
|
+
timestamp: parsed.timestamp,
|
|
141
149
|
sequence: tokenSequence,
|
|
150
|
+
cursor: String(tokenSequence),
|
|
142
151
|
data: tokenPayload
|
|
143
152
|
});
|
|
144
153
|
if (options?.publishTokenMessage)
|
|
@@ -147,32 +156,34 @@ export function wireEventBroadcasting(engine, server, options) {
|
|
|
147
156
|
const streamChannel = workflowChannelPath(workflowId, "stream");
|
|
148
157
|
server.publish(streamChannel, streamMessage);
|
|
149
158
|
}
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
await ensureSequenceInitialized(workflowId);
|
|
162
|
+
const sequence = claimNextSequence(sequenceCounters, workflowId), watchMessage = JSON.stringify({
|
|
163
|
+
type: parsed.type,
|
|
164
|
+
timestamp: parsed.timestamp,
|
|
165
|
+
data: parsed.data,
|
|
166
|
+
sequence,
|
|
167
|
+
cursor: String(sequence)
|
|
168
|
+
}), storageKey = KEYS.event(workflowId, sequence), encoded = encode(JSON.parse(watchMessage));
|
|
169
|
+
await withRetry(async () => engine.storage.put(storageKey, encoded), `persist event "${eventType}" for workflow "${workflowId}"`);
|
|
170
|
+
await appendFleetEvent(options?.fleetEventFeed, eventType, workflowId, message);
|
|
171
|
+
if (options?.publishWatchMessage)
|
|
172
|
+
options.publishWatchMessage(workflowId, sequence, watchMessage);
|
|
173
|
+
else {
|
|
174
|
+
const watchChannel = workflowChannelPath(workflowId, "watch");
|
|
175
|
+
server.publish(watchChannel, watchMessage);
|
|
150
176
|
}
|
|
151
177
|
}
|
|
152
|
-
const
|
|
153
|
-
WorkflowStartedEvent.type,
|
|
154
|
-
WorkflowCompletedEvent.type,
|
|
155
|
-
WorkflowFailedEvent.type,
|
|
156
|
-
WorkflowCancelledEvent.type,
|
|
157
|
-
WorkflowTimedOutEvent.type,
|
|
158
|
-
ActivityStartedEvent.type,
|
|
159
|
-
ActivityCompletedEvent.type,
|
|
160
|
-
ActivityFailedEvent.type,
|
|
161
|
-
TOKEN_EVENT_TYPE,
|
|
162
|
-
SignalReceivedEvent.type,
|
|
163
|
-
SignalDeliveredEvent.type,
|
|
164
|
-
AttributesChangedEvent.type,
|
|
165
|
-
UpdateReceivedEvent.type,
|
|
166
|
-
UpdateCompletedEvent.type
|
|
167
|
-
];
|
|
168
|
-
for (const eventType of eventTypes)
|
|
178
|
+
for (const eventType of CLIENT_VISIBLE_EVENT_TYPES)
|
|
169
179
|
engine.addEventListener(eventType, (event) => {
|
|
170
|
-
const workflowId = getWorkflowIdFromEvent(event);
|
|
171
|
-
if (workflowId === void 0)
|
|
172
|
-
return;
|
|
173
|
-
const message = serializeEvent(event);
|
|
180
|
+
const workflowId = getWorkflowIdFromEvent(event), message = serializeEvent(event);
|
|
174
181
|
if (message === null)
|
|
175
182
|
return;
|
|
183
|
+
if (workflowId === void 0) {
|
|
184
|
+
appendFleetEvent(options?.fleetEventFeed, eventType, void 0, message);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
176
187
|
const nextChain = (sequenceChains.get(workflowId) ?? Promise.resolve()).then(() => persistAndPublishEvent(workflowId, eventType, message)).catch((error) => {
|
|
177
188
|
console.error(`[weft] Failed to persist event "${eventType}" for workflow "${workflowId}":`, error);
|
|
178
189
|
});
|
|
@@ -203,3 +214,26 @@ export function wireEventBroadcasting(engine, server, options) {
|
|
|
203
214
|
cleanupWorkflow
|
|
204
215
|
};
|
|
205
216
|
}
|
|
217
|
+
async function appendFleetEvent(fleetEventFeed, eventType, workflowId, message) {
|
|
218
|
+
if (eventType === TOKEN_EVENT_TYPE)
|
|
219
|
+
return;
|
|
220
|
+
if (fleetEventFeed === void 0)
|
|
221
|
+
return;
|
|
222
|
+
try {
|
|
223
|
+
const parsed = JSON.parse(message), event = {
|
|
224
|
+
kind: eventType,
|
|
225
|
+
emittedAtMs: parsed.timestamp,
|
|
226
|
+
payload: parsed.data
|
|
227
|
+
};
|
|
228
|
+
if (workflowId === void 0) {
|
|
229
|
+
await fleetEventFeed.append(event);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
await fleetEventFeed.appendWorkflowEventIfPresent({
|
|
233
|
+
...event,
|
|
234
|
+
workflowId
|
|
235
|
+
});
|
|
236
|
+
} catch (error) {
|
|
237
|
+
console.error(`[weft] Failed to append fleet event "${eventType}":`, error);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function withRetry<T>(operation: () => Promise<T>, label: string, maxAttempts?: number): Promise<T>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export async function withRetry(operation, label, maxAttempts = 2) {
|
|
2
|
+
let lastError;
|
|
3
|
+
for (let attempt = 1;attempt <= maxAttempts; attempt++)
|
|
4
|
+
try {
|
|
5
|
+
return await operation();
|
|
6
|
+
} catch (error) {
|
|
7
|
+
lastError = error;
|
|
8
|
+
if (attempt < maxAttempts) {
|
|
9
|
+
console.warn(`[weft] Retrying "${label}" (attempt ${attempt + 1}/${maxAttempts})`);
|
|
10
|
+
await Bun.sleep(100 * attempt);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
throw lastError;
|
|
14
|
+
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { ServerContext } from './context.ts';
|
|
2
2
|
export declare const DEFAULT_SHUTDOWN_TIMEOUT_MS = 30000;
|
|
3
|
+
type WorkerShutdownOptions = {
|
|
4
|
+
timeoutMs?: number | undefined;
|
|
5
|
+
stopWaitingWhenIdle?: boolean | undefined;
|
|
6
|
+
};
|
|
3
7
|
/** Send a shutdown message to a specific worker and wait for it to disconnect. */
|
|
4
|
-
export declare function shutdownWorker(context: ServerContext, workerId: string, shutdownOptions?:
|
|
5
|
-
timeoutMs?: number;
|
|
6
|
-
}): Promise<boolean>;
|
|
8
|
+
export declare function shutdownWorker(context: ServerContext, workerId: string, shutdownOptions?: WorkerShutdownOptions): Promise<boolean>;
|
|
7
9
|
/** Send a shutdown message to all connected workers and wait for them to disconnect. */
|
|
8
|
-
export declare function shutdownAllWorkers(context: ServerContext, shutdownOptions?:
|
|
9
|
-
|
|
10
|
-
}): Promise<void>;
|
|
10
|
+
export declare function shutdownAllWorkers(context: ServerContext, shutdownOptions?: WorkerShutdownOptions): Promise<void>;
|
|
11
|
+
export {};
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
export const DEFAULT_SHUTDOWN_TIMEOUT_MS = 30000;
|
|
2
|
+
function workerShutdownFinished(context, workerId, options) {
|
|
3
|
+
if (!context.workerSockets.has(workerId))
|
|
4
|
+
return !0;
|
|
5
|
+
return options?.stopWaitingWhenIdle === !0 && context.registry.getWorkerTasks(workerId).length === 0;
|
|
6
|
+
}
|
|
2
7
|
export async function shutdownWorker(context, workerId, shutdownOptions) {
|
|
3
8
|
const ws = context.workerSockets.get(workerId);
|
|
4
9
|
if (!ws)
|
|
5
10
|
return !1;
|
|
6
11
|
ws.send(JSON.stringify({ type: "shutdown" }));
|
|
7
12
|
const timeout = shutdownOptions?.timeoutMs ?? DEFAULT_SHUTDOWN_TIMEOUT_MS, deadline = Date.now() + timeout;
|
|
8
|
-
while (context
|
|
13
|
+
while (!workerShutdownFinished(context, workerId, shutdownOptions)) {
|
|
9
14
|
if (Date.now() >= deadline)
|
|
10
15
|
return !0;
|
|
11
16
|
await Bun.sleep(50);
|
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
import { isAuthenticated } from "../principal.js";
|
|
2
|
+
import { readRestJsonBody } from "../rest-body.js";
|
|
3
|
+
import { readInflightRecord, transitionQueuedToInflight } from "../task-state.js";
|
|
4
|
+
import { recordTaskBacklogMetric, recordTaskQueueLatencyMetric } from "./task-metrics.js";
|
|
2
5
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from "../task-state.js";
|
|
7
|
-
import {
|
|
8
|
-
recordTaskBacklogMetric,
|
|
9
|
-
recordTaskExecutionLatencyMetric,
|
|
10
|
-
recordTaskQueueLatencyMetric
|
|
11
|
-
} from "./task-metrics.js";
|
|
6
|
+
taskResultPayloadSizeError,
|
|
7
|
+
transitionTaskResultToResolvedWithRetry
|
|
8
|
+
} from "./task-result-resolution.js";
|
|
12
9
|
const TASK_POLL_RE = /^\/v1\/tasks\/([\w-]+)$/, TASK_RESULT_RE = /^\/v1\/tasks\/([\w-]+)\/result$/, TASK_DIAGNOSTICS_PATH = "/v1/tasks/diagnostics", MAX_POLL_TIMEOUT = 60000, DEFAULT_POLL_TIMEOUT = 30000, DEFAULT_VISIBILITY_TIMEOUT = 30000;
|
|
13
|
-
async function parseTaskResultBody(request) {
|
|
10
|
+
async function parseTaskResultBody(request, options) {
|
|
14
11
|
try {
|
|
15
|
-
return await request
|
|
16
|
-
} catch {
|
|
12
|
+
return await readRestJsonBody(request, options);
|
|
13
|
+
} catch (error) {
|
|
14
|
+
if (isPayloadTooLargeFault(error))
|
|
15
|
+
return Response.json({ error: error.message }, { status: 413 });
|
|
17
16
|
return null;
|
|
18
17
|
}
|
|
19
18
|
}
|
|
19
|
+
function isPayloadTooLargeFault(value) {
|
|
20
|
+
return typeof value === "object" && value !== null && value.code === "PayloadTooLarge" && typeof value.message === "string";
|
|
21
|
+
}
|
|
20
22
|
function authorizeWorkerPrincipal(principal) {
|
|
21
23
|
if (principal === void 0)
|
|
22
24
|
return null;
|
|
@@ -47,19 +49,42 @@ async function applyTaskResult(context, options, result, inflightRecord) {
|
|
|
47
49
|
try {
|
|
48
50
|
context.taskQueue.complete({ operationId, status, value, error });
|
|
49
51
|
context.deadlineTracker.remove(operationId);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
resolvedAt,
|
|
52
|
+
await transitionTaskResultToResolvedWithRetry(context, options, {
|
|
53
|
+
operationId,
|
|
54
|
+
status: resolvedStatus,
|
|
54
55
|
resolutionReason: resolvedStatus,
|
|
56
|
+
inflightRecord,
|
|
55
57
|
...status === "completed" ? { value } : { error }
|
|
56
58
|
});
|
|
57
|
-
if (inflightRecord !== null)
|
|
58
|
-
recordTaskExecutionLatencyMetric(context.metricsCollector, inflightRecord, resolvedAt);
|
|
59
59
|
} catch (storageError) {
|
|
60
60
|
console.error(`[weft] Failed to transition task "${operationId}" to resolved \u2014 inflight record may leak:`, storageError);
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
|
+
async function applyPayloadRejectedTaskResult(context, options, result, inflightRecord, error) {
|
|
64
|
+
context.taskQueue.complete({
|
|
65
|
+
operationId: result.operationId,
|
|
66
|
+
status: "failed",
|
|
67
|
+
error: error.message
|
|
68
|
+
});
|
|
69
|
+
context.deadlineTracker.remove(result.operationId);
|
|
70
|
+
await transitionTaskResultToResolvedWithRetry(context, options, {
|
|
71
|
+
operationId: result.operationId,
|
|
72
|
+
status: "failed",
|
|
73
|
+
resolutionReason: "failed",
|
|
74
|
+
inflightRecord,
|
|
75
|
+
error: error.message,
|
|
76
|
+
skipPayloadSizeCheck: !0
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
function payloadSizeExceededResponse(error) {
|
|
80
|
+
return Response.json({
|
|
81
|
+
error: error.message,
|
|
82
|
+
code: error.code,
|
|
83
|
+
maxBytes: error.maxBytes,
|
|
84
|
+
serializedBytes: error.serializedBytes,
|
|
85
|
+
payloadKind: error.payloadKind
|
|
86
|
+
}, { status: 413 });
|
|
87
|
+
}
|
|
63
88
|
export function createLongPollInflightRecord(queue, task) {
|
|
64
89
|
const now = Date.now(), visibilityTimeout = task.visibilityTimeout ?? DEFAULT_VISIBILITY_TIMEOUT, deadline = now + visibilityTimeout;
|
|
65
90
|
return {
|
|
@@ -126,7 +151,9 @@ export async function handleTaskResultRequest(context, options, request, url, pr
|
|
|
126
151
|
const authorizationResponse = authorizeWorkerPrincipal(principal);
|
|
127
152
|
if (authorizationResponse !== null)
|
|
128
153
|
return authorizationResponse;
|
|
129
|
-
const body = await parseTaskResultBody(request);
|
|
154
|
+
const body = await parseTaskResultBody(request, options.maxRequestBodyBytes !== void 0 ? { maxBodyBytes: options.maxRequestBodyBytes } : {});
|
|
155
|
+
if (body instanceof Response)
|
|
156
|
+
return body;
|
|
130
157
|
if (body === null)
|
|
131
158
|
return Response.json({ error: "Invalid JSON body" }, { status: 400 });
|
|
132
159
|
const validated = validateTaskResultBody(body);
|
|
@@ -135,13 +162,27 @@ export async function handleTaskResultRequest(context, options, request, url, pr
|
|
|
135
162
|
const inflightRecord = await readInflightRecord(options.engine.storage, validated.operationId);
|
|
136
163
|
if (inflightRecord !== null && !isLongPollCompletionAuthorized(inflightRecord, validated))
|
|
137
164
|
return Response.json({ error: "Forbidden" }, { status: 403 });
|
|
165
|
+
const payloadError = taskResultPayloadSizeError({
|
|
166
|
+
operationId: validated.operationId,
|
|
167
|
+
status: validated.status,
|
|
168
|
+
resolutionReason: validated.status,
|
|
169
|
+
...validated.status === "completed" ? { value: validated.value } : { error: validated.error }
|
|
170
|
+
}, context.payloadSizeMaxBytes);
|
|
171
|
+
if (payloadError !== null) {
|
|
172
|
+
try {
|
|
173
|
+
await applyPayloadRejectedTaskResult(context, options, validated, inflightRecord, payloadError);
|
|
174
|
+
} catch (error) {
|
|
175
|
+
console.error(`[weft] Failed to persist oversized task result rejection for task "${validated.operationId}":`, error);
|
|
176
|
+
}
|
|
177
|
+
return payloadSizeExceededResponse(payloadError);
|
|
178
|
+
}
|
|
138
179
|
await applyTaskResult(context, options, validated, inflightRecord);
|
|
139
180
|
return Response.json({ ok: !0 });
|
|
140
181
|
}
|
|
141
182
|
function isLongPollCompletionAuthorized(inflightRecord, validated) {
|
|
142
183
|
if (validated.workerId === void 0 || inflightRecord.workerId !== validated.workerId)
|
|
143
184
|
return !1;
|
|
144
|
-
if (inflightRecord.attemptToken !== void 0 && validated.attemptToken !==
|
|
185
|
+
if (inflightRecord.attemptToken !== void 0 && validated.attemptToken !== inflightRecord.attemptToken)
|
|
145
186
|
return !1;
|
|
146
187
|
return !0;
|
|
147
188
|
}
|
|
@@ -3,7 +3,11 @@ import { ActivityFailedEvent } from "../../core/events.js";
|
|
|
3
3
|
import { calculateBackoff } from "../../core/scheduler.js";
|
|
4
4
|
import { KEYS } from "../../storage/interface.js";
|
|
5
5
|
import { restoreExtendedDeadlineIfStillActive } from "../runtime-helpers.js";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
isTaskDeadLettered,
|
|
8
|
+
transitionInflightToQueued,
|
|
9
|
+
transitionInflightToResolved
|
|
10
|
+
} from "../task-state.js";
|
|
7
11
|
import { dispatchTaskImpl, scheduleDelayedDispatch } from "./task-dispatch.js";
|
|
8
12
|
import {
|
|
9
13
|
isTaskHeartbeatStaleForMetrics,
|
|
@@ -98,6 +102,8 @@ export async function scanExpiredTasks(context, options, cleanupWorkflowIndex) {
|
|
|
98
102
|
console.error(`[weft] Corrupt inflight record for task "${operationId}" \u2014 skipping`);
|
|
99
103
|
continue;
|
|
100
104
|
}
|
|
105
|
+
if (await isTaskDeadLettered(options.engine.storage, operationId))
|
|
106
|
+
continue;
|
|
101
107
|
if (restoreExtendedDeadlineIfStillActive(context.deadlineTracker, operationId, decoded.deadline, now))
|
|
102
108
|
continue;
|
|
103
109
|
context.registry.completeTask(decoded.operationId);
|
|
@@ -130,6 +136,8 @@ export async function reconcileOrphanedRecords(context, options, cleanupWorkflow
|
|
|
130
136
|
continue;
|
|
131
137
|
if (isTaskHeartbeatStaleForMetrics(decoded, now))
|
|
132
138
|
staleHeartbeatCount += 1;
|
|
139
|
+
if (await isTaskDeadLettered(options.engine.storage, decoded.operationId))
|
|
140
|
+
continue;
|
|
133
141
|
if (decoded.deadline > now) {
|
|
134
142
|
if (context.processingOperations.has(decoded.operationId))
|
|
135
143
|
continue;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PayloadSizeExceededError } from '../../core/payload-size.ts';
|
|
2
|
+
import type { ServeOptions } from '../index.ts';
|
|
3
|
+
import { type InflightRecord, type TaskResolutionReason } from '../task-state.ts';
|
|
4
|
+
import type { ServerContext } from './context.ts';
|
|
5
|
+
export type TaskResultResolutionInput = {
|
|
6
|
+
readonly operationId: string;
|
|
7
|
+
readonly status: 'completed' | 'failed';
|
|
8
|
+
readonly resolutionReason: TaskResolutionReason;
|
|
9
|
+
readonly value?: unknown;
|
|
10
|
+
readonly error?: string | undefined;
|
|
11
|
+
readonly inflightRecord?: InflightRecord | null | undefined;
|
|
12
|
+
readonly skipPayloadSizeCheck?: boolean | undefined;
|
|
13
|
+
};
|
|
14
|
+
export declare function taskResultPayloadSizeError(input: TaskResultResolutionInput, maxBytes: number | null): PayloadSizeExceededError | null;
|
|
15
|
+
export declare function transitionTaskResultToResolvedWithRetry(context: ServerContext, options: ServeOptions, input: TaskResultResolutionInput): Promise<void>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { TaskResultDeadLetteredEvent } from "../../core/events.js";
|
|
2
|
+
import { PayloadSizeExceededError, assertPayloadWithinLimit } from "../../core/payload-size.js";
|
|
3
|
+
import {
|
|
4
|
+
readInflightRecord,
|
|
5
|
+
transitionInflightToResolved,
|
|
6
|
+
writeDeadLetteredTaskRecord
|
|
7
|
+
} from "../task-state.js";
|
|
8
|
+
import { withRetry } from "./retry.js";
|
|
9
|
+
import { recordTaskExecutionLatencyMetric } from "./task-metrics.js";
|
|
10
|
+
const TASK_RESULT_RESOLUTION_RETRY_ATTEMPTS = 2;
|
|
11
|
+
function taskResultPayloadForSizeCheck(input) {
|
|
12
|
+
return input.status === "completed" ? input.value : input.error ?? "";
|
|
13
|
+
}
|
|
14
|
+
export function taskResultPayloadSizeError(input, maxBytes) {
|
|
15
|
+
try {
|
|
16
|
+
assertPayloadWithinLimit(taskResultPayloadForSizeCheck(input), maxBytes, "activity result");
|
|
17
|
+
return null;
|
|
18
|
+
} catch (error) {
|
|
19
|
+
if (error instanceof PayloadSizeExceededError)
|
|
20
|
+
return error;
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export async function transitionTaskResultToResolvedWithRetry(context, options, input) {
|
|
25
|
+
if (input.skipPayloadSizeCheck !== !0) {
|
|
26
|
+
const payloadError = taskResultPayloadSizeError(input, context.payloadSizeMaxBytes);
|
|
27
|
+
if (payloadError !== null)
|
|
28
|
+
throw payloadError;
|
|
29
|
+
}
|
|
30
|
+
const storage = options.engine.storage, resolvedAt = Date.now();
|
|
31
|
+
let latestInflightRecord = input.inflightRecord;
|
|
32
|
+
try {
|
|
33
|
+
await withRetry(async () => {
|
|
34
|
+
if (latestInflightRecord === void 0)
|
|
35
|
+
latestInflightRecord = await readInflightRecord(storage, input.operationId);
|
|
36
|
+
await transitionInflightToResolved(storage, input.operationId, input.status, {
|
|
37
|
+
...latestInflightRecord === null ? {} : { record: latestInflightRecord },
|
|
38
|
+
resolvedAt,
|
|
39
|
+
resolutionReason: input.resolutionReason,
|
|
40
|
+
...input.status === "completed" ? { value: input.value } : { error: input.error }
|
|
41
|
+
});
|
|
42
|
+
}, `transition task "${input.operationId}" to resolved`, TASK_RESULT_RESOLUTION_RETRY_ATTEMPTS);
|
|
43
|
+
} catch (error) {
|
|
44
|
+
const fallbackInflightRecord = latestInflightRecord ?? await readInflightRecord(storage, input.operationId).catch(() => null);
|
|
45
|
+
await withRetry(async () => {
|
|
46
|
+
await writeTaskResultDeadLetter(options, input, fallbackInflightRecord);
|
|
47
|
+
}, `dead-letter task "${input.operationId}" after result-resolution retries`, TASK_RESULT_RESOLUTION_RETRY_ATTEMPTS);
|
|
48
|
+
console.error(`[weft] Failed to transition task "${input.operationId}" to resolved after retries \u2014 dead-lettered:`, error);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (latestInflightRecord !== null && latestInflightRecord !== void 0)
|
|
52
|
+
recordTaskExecutionLatencyMetric(context.metricsCollector, latestInflightRecord, resolvedAt);
|
|
53
|
+
}
|
|
54
|
+
async function writeTaskResultDeadLetter(options, input, inflightRecord) {
|
|
55
|
+
const storageErrorCode = "result-resolution-storage-exhausted", record = {
|
|
56
|
+
operationId: input.operationId,
|
|
57
|
+
reason: storageErrorCode,
|
|
58
|
+
deadLetteredAt: Date.now(),
|
|
59
|
+
errorMessage: storageErrorCode,
|
|
60
|
+
retryAttempts: TASK_RESULT_RESOLUTION_RETRY_ATTEMPTS,
|
|
61
|
+
status: input.status,
|
|
62
|
+
...inflightRecord?.activityName === void 0 ? {} : { activityName: inflightRecord.activityName },
|
|
63
|
+
...inflightRecord?.queue === void 0 ? {} : { queue: inflightRecord.queue },
|
|
64
|
+
...inflightRecord?.workerId === void 0 ? {} : { workerId: inflightRecord.workerId },
|
|
65
|
+
...inflightRecord?.attempt === void 0 ? {} : { attempt: inflightRecord.attempt },
|
|
66
|
+
...inflightRecord?.visibilityTimeout === void 0 ? {} : { visibilityTimeout: inflightRecord.visibilityTimeout },
|
|
67
|
+
...inflightRecord?.workflowId === void 0 ? {} : { workflowId: inflightRecord.workflowId },
|
|
68
|
+
...inflightRecord?.retryCount === void 0 ? {} : { retryCount: inflightRecord.retryCount },
|
|
69
|
+
...inflightRecord?.requeueCount === void 0 ? {} : { requeueCount: inflightRecord.requeueCount },
|
|
70
|
+
...inflightRecord?.lastRequeueReason === void 0 ? {} : { lastRequeueReason: inflightRecord.lastRequeueReason }
|
|
71
|
+
};
|
|
72
|
+
await writeDeadLetteredTaskRecord(options.engine.storage, record);
|
|
73
|
+
options.engine.dispatchEvent(new TaskResultDeadLetteredEvent({
|
|
74
|
+
operationId: record.operationId,
|
|
75
|
+
workflowId: record.workflowId,
|
|
76
|
+
activityName: record.activityName,
|
|
77
|
+
queue: record.queue,
|
|
78
|
+
workerId: record.workerId,
|
|
79
|
+
errorMessage: record.errorMessage
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
@@ -2,14 +2,33 @@ import type { ServerWebSocket } from 'bun';
|
|
|
2
2
|
import type { Engine } from '../../core/engine.ts';
|
|
3
3
|
import type { WebSocketData } from '../json-rpc-websocket-runtime.ts';
|
|
4
4
|
import type { ServerContext } from './context.ts';
|
|
5
|
+
/**
|
|
6
|
+
* Default per-workflow cap for one-way workflow WebSocket connections
|
|
7
|
+
* (`/stream` and `/watch`). Mirrors the JSON-RPC subscription default so one
|
|
8
|
+
* workflow cannot consume unbounded server sockets.
|
|
9
|
+
*/
|
|
10
|
+
export declare const DEFAULT_MAX_STREAM_CONNECTIONS_PER_WORKFLOW = 100;
|
|
5
11
|
export declare function sendStreamMessage(ws: ServerWebSocket<WebSocketData>, sequence: number, message: string): void;
|
|
12
|
+
export declare function sendWatchMessage(ws: ServerWebSocket<WebSocketData>, sequence: number, message: string): void;
|
|
6
13
|
export declare function getHighestStoredStreamSequence(engine: Engine, workflowId: string, key: string): Promise<number>;
|
|
7
|
-
export declare function
|
|
14
|
+
export declare function getHighestStoredWatchSequence(engine: Engine, workflowId: string): Promise<number>;
|
|
15
|
+
export declare function addStreamSocket(context: ServerContext, workflowId: string, ws: ServerWebSocket<WebSocketData>): boolean;
|
|
16
|
+
export declare function addWatchSocket(context: ServerContext, workflowId: string, ws: ServerWebSocket<WebSocketData>): boolean;
|
|
8
17
|
export declare function removeStreamSocket(context: ServerContext, ws: ServerWebSocket<WebSocketData>): void;
|
|
18
|
+
export declare function removeWatchSocket(context: ServerContext, ws: ServerWebSocket<WebSocketData>): void;
|
|
19
|
+
export declare function removeWorkflowStreamConnection(context: ServerContext, ws: ServerWebSocket<WebSocketData>): void;
|
|
9
20
|
export declare function flushPendingStreamMessages(_context: ServerContext, ws: ServerWebSocket<WebSocketData>): void;
|
|
21
|
+
export declare function flushPendingWatchMessages(_context: ServerContext, ws: ServerWebSocket<WebSocketData>): void;
|
|
10
22
|
export declare function publishTokenMessage(context: ServerContext, workflowId: string, sequence: number, message: string): void;
|
|
23
|
+
export declare function publishWatchMessage(context: ServerContext, workflowId: string, sequence: number, message: string): void;
|
|
11
24
|
/**
|
|
12
25
|
* Send existing token chunks from storage to a newly connected stream client,
|
|
13
26
|
* so it can catch up on tokens emitted before the connection was established.
|
|
14
27
|
*/
|
|
15
28
|
export declare function replayTokenStream(context: ServerContext, engine: Engine, ws: ServerWebSocket<WebSocketData>, workflowId: string): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Send stored raw watch events to a newly connected watch client. The raw
|
|
31
|
+
* watch transport keeps its historical frame shape but now honors the same
|
|
32
|
+
* `resumeFrom` cursor query parameter used by token streams.
|
|
33
|
+
*/
|
|
34
|
+
export declare function replayWatchEvents(context: ServerContext, engine: Engine, ws: ServerWebSocket<WebSocketData>, workflowId: string): Promise<void>;
|