@lostgradient/weft 0.23.1 → 0.24.1
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 +72 -4
- package/dist/cli/codegen-emit-dedup.d.ts +81 -0
- package/dist/cli/codegen-emit-dedup.js +45 -0
- package/dist/cli/codegen-emit-registry.d.ts +90 -0
- package/dist/cli/codegen-emit-registry.js +50 -0
- package/dist/cli/codegen-emit.d.ts +26 -39
- package/dist/cli/codegen-emit.js +4 -27
- package/dist/cli/codegen-validate.d.ts +49 -0
- package/dist/cli/codegen-validate.js +186 -0
- package/dist/cli/codegen.js +6 -87
- package/dist/cli/conformance.js +5 -2
- package/dist/cli/generated/operation-catalog.snapshot.json +381 -3
- package/dist/cli/generated/operation-client.generated.d.ts +350 -10
- package/dist/cli/generated/operation-client.generated.js +14 -0
- package/dist/cli/output.js +1 -1
- package/dist/cli/parse-schedule-arguments.js +15 -3
- package/dist/cli/schedule.js +2 -1
- package/dist/cli/storage-factory.js +2 -0
- package/dist/cli/types.d.ts +2 -1
- package/dist/cli/workflow-commands.js +2 -0
- package/dist/cli-main.js +1 -1
- package/dist/client/http-client-requests.js +6 -9
- package/dist/client/start-body.js +1 -0
- package/dist/core/application-payload-digest.d.ts +42 -0
- package/dist/core/application-payload-digest.js +76 -0
- package/dist/core/application-primitive-abort.d.ts +50 -0
- package/dist/core/application-primitive-abort.js +40 -0
- package/dist/core/application-primitive-attempt-registry.d.ts +74 -0
- package/dist/core/application-primitive-attempt-registry.js +73 -0
- package/dist/core/application-primitive-codec.d.ts +36 -0
- package/dist/core/application-primitive-codec.js +56 -0
- package/dist/core/application-primitive-commit.d.ts +67 -0
- package/dist/core/application-primitive-commit.js +66 -0
- package/dist/core/application-primitive-guards.d.ts +62 -0
- package/dist/core/application-primitive-guards.js +89 -0
- package/dist/core/application-primitive-payload.d.ts +29 -0
- package/dist/core/application-primitive-payload.js +65 -0
- package/dist/core/application-primitive-timing.d.ts +18 -0
- package/dist/core/application-primitive-timing.js +22 -0
- package/dist/core/atomic-state.js +2 -0
- package/dist/core/catalog/codec.d.ts +40 -0
- package/dist/core/catalog/codec.js +45 -0
- package/dist/core/catalog/errors.d.ts +104 -0
- package/dist/core/catalog/errors.js +41 -0
- package/dist/core/catalog/index.d.ts +25 -0
- package/dist/core/catalog/index.js +22 -0
- package/dist/core/catalog/reference-counts.d.ts +120 -0
- package/dist/core/catalog/reference-counts.js +28 -0
- package/dist/core/catalog/removal.d.ts +105 -0
- package/dist/core/catalog/removal.js +30 -0
- package/dist/core/catalog/storage-io.d.ts +101 -0
- package/dist/core/catalog/storage-io.js +106 -0
- package/dist/core/catalog/types.d.ts +108 -0
- package/dist/core/catalog/types.js +0 -0
- package/dist/core/catalog/workflow-catalog.d.ts +165 -0
- package/dist/core/catalog/workflow-catalog.js +198 -0
- package/dist/core/compare-codepoint.d.ts +13 -0
- package/dist/core/compare-codepoint.js +7 -0
- package/dist/core/compression.js +2 -0
- package/dist/core/context/attributes.d.ts +1 -1
- package/dist/core/context/durable-operations.d.ts +2 -2
- package/dist/core/context/index.js +5 -3
- package/dist/core/context/state-namespace.d.ts +1 -1
- package/dist/core/contract/build.d.ts +64 -0
- package/dist/core/contract/build.js +99 -0
- package/dist/core/contract/compatibility.d.ts +187 -0
- package/dist/core/contract/compatibility.js +37 -0
- package/dist/core/contract/failure.d.ts +64 -0
- package/dist/core/contract/failure.js +4 -0
- package/dist/core/contract/hash.d.ts +92 -0
- package/dist/core/contract/hash.js +34 -0
- package/dist/core/contract/index.d.ts +21 -0
- package/dist/core/contract/index.js +22 -0
- package/dist/core/contract/limits.d.ts +74 -0
- package/dist/core/contract/limits.js +1 -0
- package/dist/core/contract/manifest-parse-schema.d.ts +37 -0
- package/dist/core/contract/manifest-parse-schema.js +106 -0
- package/dist/core/contract/manifest-parse.d.ts +76 -0
- package/dist/core/contract/manifest-parse.js +189 -0
- package/dist/core/contract/manifest.d.ts +56 -0
- package/dist/core/contract/manifest.js +31 -0
- package/dist/core/contract/normalize.d.ts +97 -0
- package/dist/core/contract/normalize.js +127 -0
- package/dist/core/contract/revision.d.ts +29 -0
- package/dist/core/contract/revision.js +5 -0
- package/dist/core/contract/types.d.ts +274 -0
- package/dist/core/contract/types.js +1 -0
- package/dist/core/engine/activity-resolution.js +17 -17
- package/dist/core/engine/bulk-operations-purge.js +14 -20
- package/dist/core/engine/bulk-operations-retry.d.ts +9 -0
- package/dist/core/engine/bulk-operations-retry.js +177 -0
- package/dist/core/engine/bulk-operations-shared.d.ts +18 -0
- package/dist/core/engine/bulk-operations-shared.js +14 -0
- package/dist/core/engine/bulk-operations.js +8 -167
- package/dist/core/engine/callback-creators-bundles.js +4 -2
- package/dist/core/engine/callback-creators-core.js +9 -1
- package/dist/core/engine/callback-creators-schedule.js +2 -2
- package/dist/core/engine/catalog-activation.d.ts +40 -0
- package/dist/core/engine/catalog-activation.js +17 -0
- package/dist/core/engine/catalog-events.d.ts +36 -0
- package/dist/core/engine/catalog-events.js +15 -0
- package/dist/core/engine/catalog-readiness.d.ts +49 -0
- package/dist/core/engine/catalog-readiness.js +61 -0
- package/dist/core/engine/catalog-removal.d.ts +236 -0
- package/dist/core/engine/catalog-removal.js +123 -0
- package/dist/core/engine/catalog-tombstone-recovery.d.ts +56 -0
- package/dist/core/engine/catalog-tombstone-recovery.js +39 -0
- package/dist/core/engine/constraints.js +5 -1
- package/dist/core/engine/construction.d.ts +2 -2
- package/dist/core/engine/construction.js +4 -2
- package/dist/core/engine/decode-revision.d.ts +32 -0
- package/dist/core/engine/decode-revision.js +9 -0
- package/dist/core/engine/disposal.d.ts +6 -2
- package/dist/core/engine/disposal.js +26 -3
- package/dist/core/engine/dynamic-source-errors.d.ts +81 -0
- package/dist/core/engine/dynamic-source-errors.js +25 -0
- package/dist/core/engine/dynamic-source-execution.d.ts +173 -0
- package/dist/core/engine/dynamic-source-execution.js +108 -0
- package/dist/core/engine/engine-internal-types.d.ts +16 -0
- package/dist/core/engine/engine-workflows-namespace.d.ts +140 -0
- package/dist/core/engine/engine-workflows-namespace.js +51 -0
- package/dist/core/engine/finalizer-metadata.d.ts +22 -0
- package/dist/core/engine/finalizer-metadata.js +12 -0
- package/dist/core/engine/handle-result.js +2 -0
- package/dist/core/engine/index.d.ts +91 -0
- package/dist/core/engine/index.js +78 -6
- package/dist/core/engine/inline-launch-queue.js +1 -1
- package/dist/core/engine/internals.d.ts +54 -15
- package/dist/core/engine/internals.js +6 -0
- package/dist/core/engine/lifecycle/checkpoint-launch.d.ts +29 -0
- package/dist/core/engine/lifecycle/checkpoint-launch.js +75 -0
- package/dist/core/engine/lifecycle/delayed-start-registration.d.ts +30 -0
- package/dist/core/engine/lifecycle/delayed-start-registration.js +11 -0
- package/dist/core/engine/lifecycle/fork-helpers.d.ts +33 -1
- package/dist/core/engine/lifecycle/fork-helpers.js +3 -1
- package/dist/core/engine/lifecycle/recovery-revision-groups.d.ts +75 -0
- package/dist/core/engine/lifecycle/recovery-revision-groups.js +64 -0
- package/dist/core/engine/lifecycle/resume-generation-guard.d.ts +58 -0
- package/dist/core/engine/lifecycle/resume-generation-guard.js +11 -0
- package/dist/core/engine/lifecycle/resume.js +18 -9
- package/dist/core/engine/lifecycle/shared.d.ts +43 -0
- package/dist/core/engine/lifecycle/standalone-claim-acquire.d.ts +12 -0
- package/dist/core/engine/lifecycle/standalone-claim-acquire.js +6 -0
- package/dist/core/engine/lifecycle/start-commit-errors.d.ts +12 -0
- package/dist/core/engine/lifecycle/start-commit-errors.js +6 -0
- package/dist/core/engine/lifecycle/start-commit.d.ts +22 -7
- package/dist/core/engine/lifecycle/start-commit.js +49 -15
- package/dist/core/engine/lifecycle/start-exec.d.ts +18 -2
- package/dist/core/engine/lifecycle/start-exec.js +7 -5
- package/dist/core/engine/lifecycle/start-or-signal-create.js +1 -3
- package/dist/core/engine/lifecycle/start-or-signal.js +1 -1
- package/dist/core/engine/lifecycle/start-precondition-attribution.d.ts +49 -0
- package/dist/core/engine/lifecycle/start-precondition-attribution.js +13 -0
- package/dist/core/engine/lifecycle/start-revision-resolution.d.ts +34 -0
- package/dist/core/engine/lifecycle/start-revision-resolution.js +11 -0
- package/dist/core/engine/lifecycle/start-state.d.ts +16 -0
- package/dist/core/engine/lifecycle/start-state.js +60 -0
- package/dist/core/engine/lifecycle/start-terminal-conflict-purge.d.ts +66 -3
- package/dist/core/engine/lifecycle/start-terminal-conflict-purge.js +13 -3
- package/dist/core/engine/lifecycle/start.d.ts +16 -6
- package/dist/core/engine/lifecycle/start.js +39 -66
- package/dist/core/engine/lifecycle/transition.d.ts +3 -4
- package/dist/core/engine/lifecycle/transition.js +30 -80
- package/dist/core/engine/lifecycle.d.ts +4 -2
- package/dist/core/engine/lifecycle.js +6 -6
- package/dist/core/engine/listing.js +15 -1
- package/dist/core/engine/memo-durable-activity.js +4 -1
- package/dist/core/engine/nonterminal-revision-count.d.ts +25 -0
- package/dist/core/engine/nonterminal-revision-count.js +16 -0
- package/dist/core/engine/operations-time.d.ts +5 -23
- package/dist/core/engine/operations-time.js +13 -11
- package/dist/core/engine/ownership-bootstrap.d.ts +1 -1
- package/dist/core/engine/pinned-schedule-revision-count.d.ts +26 -0
- package/dist/core/engine/pinned-schedule-revision-count.js +19 -0
- package/dist/core/engine/pinned-schedule-revision.d.ts +76 -0
- package/dist/core/engine/pinned-schedule-revision.js +53 -0
- package/dist/core/engine/registration.d.ts +106 -0
- package/dist/core/engine/registration.js +28 -7
- package/dist/core/engine/retention.js +9 -2
- package/dist/core/engine/revision-errors.d.ts +71 -0
- package/dist/core/engine/revision-errors.js +13 -0
- package/dist/core/engine/schedule-revision-fire.d.ts +17 -0
- package/dist/core/engine/schedule-revision-fire.js +3 -0
- package/dist/core/engine/schedule-run.js +2 -1
- package/dist/core/engine/schedules.d.ts +2 -1
- package/dist/core/engine/schedules.js +28 -9
- package/dist/core/engine/source-diagnostics.d.ts +76 -0
- package/dist/core/engine/source-diagnostics.js +105 -0
- package/dist/core/engine/source-registration.d.ts +42 -0
- package/dist/core/engine/source-registration.js +38 -0
- package/dist/core/engine/source-resolution.d.ts +101 -0
- package/dist/core/engine/source-resolution.js +154 -0
- package/dist/core/engine/source-runtime-state.d.ts +92 -0
- package/dist/core/engine/source-runtime-state.js +36 -0
- package/dist/core/engine/storage-io.d.ts +19 -2
- package/dist/core/engine/storage-io.js +21 -2
- package/dist/core/engine/termination/finalizer-registration.d.ts +18 -0
- package/dist/core/engine/termination/finalizer-registration.js +21 -0
- package/dist/core/engine/termination/finalizer.d.ts +16 -19
- package/dist/core/engine/termination/finalizer.js +3 -3
- package/dist/core/engine/time-operation-callbacks.d.ts +32 -0
- package/dist/core/engine/time-operation-callbacks.js +0 -0
- package/dist/core/engine/validation/schedule-cadence.d.ts +16 -0
- package/dist/core/engine/validation/schedule-cadence.js +20 -0
- package/dist/core/engine/validation/schedule-options.d.ts +4 -1
- package/dist/core/engine/validation/schedule-options.js +14 -0
- package/dist/core/engine/validation/schedule-revision.d.ts +24 -0
- package/dist/core/engine/validation/schedule-revision.js +21 -0
- package/dist/core/engine/validation/schedule-warnings.d.ts +11 -0
- package/dist/core/engine/validation/schedule-warnings.js +5 -0
- package/dist/core/engine/validation/schedule.d.ts +4 -3
- package/dist/core/engine/validation/schedule.js +15 -26
- package/dist/core/engine/validation.js +5 -2
- package/dist/core/engine/workflow-claim-reclaim-target.d.ts +1 -1
- package/dist/core/engine/workflow-claim-reclaim-target.js +16 -2
- package/dist/core/engine/workflow-retention-deadline.d.ts +16 -0
- package/dist/core/engine/workflow-retention-deadline.js +33 -0
- package/dist/core/events/catalog-events.d.ts +117 -0
- package/dist/core/events/catalog-events.js +62 -0
- package/dist/core/events/event-map.d.ts +11 -0
- package/dist/core/events/index.d.ts +2 -0
- package/dist/core/events/index.js +2 -0
- package/dist/core/events/workflow-source-events.d.ts +102 -0
- package/dist/core/events/workflow-source-events.js +57 -0
- package/dist/core/execution-strategy.d.ts +7 -0
- package/dist/core/inline-execution-strategy.context-options.d.ts +1 -1
- package/dist/core/inline-execution-strategy.js +1 -1
- package/dist/core/mailbox-admission.d.ts +26 -0
- package/dist/core/mailbox-admission.js +130 -0
- package/dist/core/mailbox-claims.d.ts +251 -0
- package/dist/core/mailbox-claims.js +0 -0
- package/dist/core/mailbox-codec.d.ts +32 -0
- package/dist/core/mailbox-codec.js +221 -0
- package/dist/core/mailbox-contract.d.ts +290 -0
- package/dist/core/mailbox-contract.js +0 -0
- package/dist/core/mailbox-delivery.d.ts +37 -0
- package/dist/core/mailbox-delivery.js +193 -0
- package/dist/core/mailbox-guards.d.ts +78 -0
- package/dist/core/mailbox-guards.js +58 -0
- package/dist/core/mailbox-index-codec.d.ts +41 -0
- package/dist/core/mailbox-index-codec.js +71 -0
- package/dist/core/mailbox-internals.d.ts +156 -0
- package/dist/core/mailbox-internals.js +154 -0
- package/dist/core/mailbox-maintenance.d.ts +29 -0
- package/dist/core/mailbox-maintenance.js +196 -0
- package/dist/core/mailbox-settlement.d.ts +69 -0
- package/dist/core/mailbox-settlement.js +206 -0
- package/dist/core/mailbox-storage.d.ts +117 -0
- package/dist/core/mailbox-storage.js +115 -0
- package/dist/core/mailbox-transition-helpers.d.ts +70 -0
- package/dist/core/mailbox-transition-helpers.js +43 -0
- package/dist/core/mailbox-transitions-recovery.d.ts +28 -0
- package/dist/core/mailbox-transitions-recovery.js +64 -0
- package/dist/core/mailbox-transitions.d.ts +138 -0
- package/dist/core/mailbox-transitions.js +180 -0
- package/dist/core/mailbox-types.d.ts +406 -0
- package/dist/core/mailbox-types.js +16 -0
- package/dist/core/mailbox-validation.d.ts +65 -0
- package/dist/core/mailbox-validation.js +73 -0
- package/dist/core/mailbox-waits.d.ts +50 -0
- package/dist/core/mailbox-waits.js +97 -0
- package/dist/core/mailbox.d.ts +163 -0
- package/dist/core/mailbox.js +211 -0
- package/dist/core/outbox-claims.d.ts +307 -0
- package/dist/core/outbox-claims.js +0 -0
- package/dist/core/outbox-codec.d.ts +24 -0
- package/dist/core/outbox-codec.js +257 -0
- package/dist/core/outbox-contract.d.ts +346 -0
- package/dist/core/outbox-contract.js +0 -0
- package/dist/core/outbox-delivery.d.ts +34 -0
- package/dist/core/outbox-delivery.js +149 -0
- package/dist/core/outbox-drain.d.ts +29 -0
- package/dist/core/outbox-drain.js +158 -0
- package/dist/core/outbox-enqueue.d.ts +24 -0
- package/dist/core/outbox-enqueue.js +115 -0
- package/dist/core/outbox-guards.d.ts +76 -0
- package/dist/core/outbox-guards.js +60 -0
- package/dist/core/outbox-index-codec.d.ts +33 -0
- package/dist/core/outbox-index-codec.js +71 -0
- package/dist/core/outbox-internals.d.ts +99 -0
- package/dist/core/outbox-internals.js +159 -0
- package/dist/core/outbox-listing.d.ts +12 -0
- package/dist/core/outbox-listing.js +38 -0
- package/dist/core/outbox-maintenance.d.ts +28 -0
- package/dist/core/outbox-maintenance.js +191 -0
- package/dist/core/outbox-operations.d.ts +18 -0
- package/dist/core/outbox-operations.js +46 -0
- package/dist/core/outbox-runner.d.ts +30 -0
- package/dist/core/outbox-runner.js +217 -0
- package/dist/core/outbox-settlement.d.ts +57 -0
- package/dist/core/outbox-settlement.js +183 -0
- package/dist/core/outbox-storage.d.ts +107 -0
- package/dist/core/outbox-storage.js +127 -0
- package/dist/core/outbox-transition-helpers.d.ts +83 -0
- package/dist/core/outbox-transition-helpers.js +63 -0
- package/dist/core/outbox-transitions-recovery.d.ts +30 -0
- package/dist/core/outbox-transitions-recovery.js +42 -0
- package/dist/core/outbox-transitions.d.ts +145 -0
- package/dist/core/outbox-transitions.js +236 -0
- package/dist/core/outbox-types.d.ts +400 -0
- package/dist/core/outbox-types.js +20 -0
- package/dist/core/outbox-validation.d.ts +101 -0
- package/dist/core/outbox-validation.js +127 -0
- package/dist/core/outbox-waits.d.ts +39 -0
- package/dist/core/outbox-waits.js +88 -0
- package/dist/core/outbox.d.ts +156 -0
- package/dist/core/outbox.js +234 -0
- package/dist/core/registry-limits.d.ts +49 -0
- package/dist/core/registry-limits.js +10 -0
- package/dist/core/registry-schema-conversion.d.ts +20 -0
- package/dist/core/registry-schema-conversion.js +22 -0
- package/dist/core/registry-snapshot.d.ts +91 -42
- package/dist/core/registry-snapshot.js +39 -77
- package/dist/core/registry-workflow-contract-draft.d.ts +32 -0
- package/dist/core/registry-workflow-contract-draft.js +28 -0
- package/dist/core/registry-workflow-manifest.d.ts +122 -0
- package/dist/core/registry-workflow-manifest.js +92 -0
- package/dist/core/source/errors.d.ts +55 -0
- package/dist/core/source/errors.js +13 -0
- package/dist/core/source/index.d.ts +19 -0
- package/dist/core/source/index.js +4 -0
- package/dist/core/source/resolvers.d.ts +45 -0
- package/dist/core/source/resolvers.js +9 -0
- package/dist/core/source/types.d.ts +211 -0
- package/dist/core/source/types.js +0 -0
- package/dist/core/source/validate.d.ts +91 -0
- package/dist/core/source/validate.js +62 -0
- package/dist/core/source/workflow-source.d.ts +43 -0
- package/dist/core/source/workflow-source.js +16 -0
- package/dist/core/types/checkpoint.d.ts +14 -0
- package/dist/core/types/schedules.d.ts +52 -1
- package/dist/core/types/state.d.ts +16 -0
- package/dist/core/types/workflow-registries.d.ts +7 -0
- package/dist/core/types/workflow-registry.d.ts +12 -0
- package/dist/core/versioning.js +2 -0
- package/dist/core/weft-error.d.ts +1 -1
- package/dist/core/weft-error.js +12 -1
- package/dist/core/worker-execution-strategy.d.ts +1 -0
- package/dist/core/worker-execution-strategy.js +13 -1
- package/dist/core/worker-fault-handling.d.ts +10 -0
- package/dist/core/worker-fault-handling.js +1 -0
- package/dist/core/worker-inbound-message.d.ts +1 -0
- package/dist/core/worker-inbound-message.js +1 -0
- package/dist/core/worker-protocol-guard.js +4 -0
- package/dist/core/worker-protocol.d.ts +7 -0
- package/dist/core/worker-protocol.js +2 -1
- package/dist/core/worker-turn-watchdog.d.ts +8 -1
- package/dist/core/worker-turn-watchdog.js +3 -2
- package/dist/diagnostics/format.js +5 -0
- package/dist/diagnostics/types.d.ts +24 -0
- package/dist/diagnostics/version-check.js +8 -2
- package/dist/http.js +2 -2
- package/dist/index.d.ts +25 -4
- package/dist/index.js +57 -0
- package/dist/indexeddb.js +1 -1
- package/dist/json-schema.js +3 -3
- package/dist/mcp/resources.js +2 -0
- package/dist/runtime/portable.d.ts +9 -1
- package/dist/server/fault-to-json-rpc.js +4 -1
- package/dist/server/handler/auth-context-principal.js +4 -0
- package/dist/server/index.d.ts +11 -0
- package/dist/server/json-rpc-http.js +2 -0
- package/dist/server/json-rpc-websocket.js +6 -4
- package/dist/server/operation-catalog/index.d.ts +1 -1
- package/dist/server/operation-catalog/pipeline-helpers.js +2 -0
- package/dist/server/operation-catalog/types.d.ts +17 -0
- package/dist/server/operation-fault.d.ts +5 -0
- package/dist/server/operation-fault.js +4 -1
- package/dist/server/operations/activate-workflow-revision.d.ts +30 -0
- package/dist/server/operations/activate-workflow-revision.js +69 -0
- package/dist/server/operations/create-schedule.d.ts +2 -0
- package/dist/server/operations/create-schedule.js +10 -6
- package/dist/server/operations/fleet-events-subscription.js +1 -1
- package/dist/server/operations/fork-workflow.js +1 -1
- package/dist/server/operations/get-active-workflow-revision.d.ts +32 -0
- package/dist/server/operations/get-active-workflow-revision.js +46 -0
- package/dist/server/operations/get-catalog-diagnostics.d.ts +113 -0
- package/dist/server/operations/get-catalog-diagnostics.js +65 -0
- package/dist/server/operations/get-registry.js +17 -4
- package/dist/server/operations/get-task-detail-schema.d.ts +8 -0
- package/dist/server/operations/get-task-detail-schema.js +1 -0
- package/dist/server/operations/get-task-detail.d.ts +8 -0
- package/dist/server/operations/get-task-detail.js +1 -0
- package/dist/server/operations/get-task-diagnostics.d.ts +4 -4
- package/dist/server/operations/get-workflow-revision.d.ts +25 -0
- package/dist/server/operations/get-workflow-revision.js +50 -0
- package/dist/server/operations/install-workflow-revision.d.ts +27 -0
- package/dist/server/operations/install-workflow-revision.js +46 -0
- package/dist/server/operations/list-workflow-revisions.d.ts +20 -0
- package/dist/server/operations/list-workflow-revisions.js +40 -0
- package/dist/server/operations/preload-workflow-revision.d.ts +28 -0
- package/dist/server/operations/preload-workflow-revision.js +60 -0
- package/dist/server/operations/schedule-faults.d.ts +1 -0
- package/dist/server/operations/schedule-faults.js +32 -4
- package/dist/server/operations/schedule-rest-body.d.ts +1 -0
- package/dist/server/operations/schedule-rest-body.js +2 -1
- package/dist/server/operations/start-or-signal-workflow.js +1 -1
- package/dist/server/operations/start-workflow.js +1 -1
- package/dist/server/operations/static-registrations.js +42 -0
- package/dist/server/operations/storage.js +2 -2
- package/dist/server/operations/submit-review-decision.js +1 -1
- package/dist/server/operations/update-schedule.d.ts +2 -0
- package/dist/server/operations/update-schedule.js +4 -2
- package/dist/server/operations/workflow-catalog-operation-helpers.d.ts +59 -0
- package/dist/server/operations/workflow-catalog-operation-helpers.js +162 -0
- package/dist/server/runtime/task-dispatch-envelope.d.ts +14 -0
- package/dist/server/runtime/task-dispatch-envelope.js +32 -0
- package/dist/server/runtime/task-dispatch-revision.d.ts +29 -0
- package/dist/server/runtime/task-dispatch-revision.js +13 -0
- package/dist/server/runtime/task-dispatch.js +12 -37
- package/dist/server/runtime/task-ledger-recovery.js +1 -1
- package/dist/server/runtime/task-ledger-runtime.d.ts +14 -2
- package/dist/server/runtime/task-ledger-runtime.js +5 -3
- package/dist/server/runtime/task-polling.js +9 -3
- package/dist/server/runtime/task-reconciliation.js +2 -1
- package/dist/server/runtime/websocket-upgrade.js +2 -0
- package/dist/server/runtime/websocket-worker.js +9 -0
- package/dist/server/task-ledger-codec.d.ts +9 -0
- package/dist/server/task-ledger-codec.js +4 -1
- package/dist/server/task-ledger-transition-helpers.js +1 -0
- package/dist/server/task-ledger-types.d.ts +9 -0
- package/dist/server/task-ledger.d.ts +1 -1
- package/dist/server/task-ledger.js +2 -1
- package/dist/server/task-queue-types.d.ts +2 -0
- package/dist/storage/bun-sql.js +51 -6
- package/dist/storage/catalog-keys.d.ts +64 -0
- package/dist/storage/catalog-keys.js +8 -0
- package/dist/storage/compressed-storage.js +1 -1
- package/dist/storage/derived-operations.js +1 -1
- package/dist/storage/index.d.ts +28 -1
- package/dist/storage/interface.d.ts +28 -1
- package/dist/storage/interface.js +1 -1
- package/dist/storage/key-encoding.d.ts +15 -0
- package/dist/storage/key-encoding.js +3 -0
- package/dist/storage/key-prefixes.d.ts +1 -1
- package/dist/storage/key-prefixes.js +16 -0
- package/dist/storage/lmdb.d.ts +54 -1
- package/dist/storage/lmdb.js +1 -1
- package/dist/storage/mailbox-keys.d.ts +80 -0
- package/dist/storage/mailbox-keys.js +14 -0
- package/dist/storage/memory.js +1 -1
- package/dist/storage/neon.js +2 -2
- package/dist/storage/node-sqlite-loader.d.ts +1 -1
- package/dist/storage/node-sqlite.js +51 -6
- package/dist/storage/outbox-keys.d.ts +77 -0
- package/dist/storage/outbox-keys.js +14 -0
- package/dist/storage/postgres.js +2 -2
- package/dist/storage/resolve.js +1 -1
- package/dist/storage/scoped-storage.js +1 -1
- package/dist/storage/storage-configuration.d.ts +6 -0
- package/dist/storage/testing.js +1 -1
- package/dist/storage/turso.js +2 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/web-extension.js +1 -1
- package/dist/worker/manifest/registry-contract-builder.d.ts +21 -3
- package/dist/worker/manifest/registry-contract-builder.js +40 -31
- package/dist/worker/protocol-messages.d.ts +17 -0
- package/dist/worker/protocol-schemas.d.ts +32 -0
- package/dist/worker/protocol-schemas.js +7 -3
- package/dist/worker/protocol-task-result.js +35 -3
- package/dist/worker/protocol.js +1 -1
- package/dist/worker/registry/types.d.ts +2 -0
- package/dist/worker/registry.d.ts +1 -1
- package/dist/worker/registry.js +3 -1
- package/dist/workers/workflow-runner.d.ts +9 -0
- package/dist/workers/workflow-runner.js +9 -2
- package/dist/workers/workflow-worker-entry.js +9 -4
- package/package.json +2 -2
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attempt-fenced settlement for the application command mailbox (WFT-84):
|
|
3
|
+
* lease renewal, acknowledgement, rejection, cancellation, and the bounded
|
|
4
|
+
* cleanup wait.
|
|
5
|
+
*
|
|
6
|
+
* Every function here proves the caller holds the current attempt before it
|
|
7
|
+
* writes anything, and every one re-reads durable state after a lost
|
|
8
|
+
* compare-and-swap rather than retrying with stale bytes. A stale claimant
|
|
9
|
+
* therefore cannot acknowledge, reject, cancel, extend, or heartbeat a newer
|
|
10
|
+
* attempt — it gets a `stale` result carrying the authoritative receipt.
|
|
11
|
+
*
|
|
12
|
+
* Renewal is the one mutation that emits no fleet event. It is liveness
|
|
13
|
+
* evidence, not a state transition: the record's disposition is unchanged, so
|
|
14
|
+
* publishing an event per heartbeat would flood the feed without telling a
|
|
15
|
+
* consumer anything a receipt read does not already say.
|
|
16
|
+
*
|
|
17
|
+
* @module core/mailbox-settlement
|
|
18
|
+
*/
|
|
19
|
+
import type { JSONValue } from './json.ts';
|
|
20
|
+
import type { ApplicationCommandCancellationResult, ApplicationCommandCleanupResult, ApplicationCommandRenewalResult, ApplicationCommandSettleResult } from './mailbox-contract.ts';
|
|
21
|
+
import { type MailboxRuntime } from './mailbox-internals.ts';
|
|
22
|
+
import type { ApplicationCommandFailure } from './mailbox-types.ts';
|
|
23
|
+
/**
|
|
24
|
+
* Extend a lease and report liveness for the current attempt.
|
|
25
|
+
*
|
|
26
|
+
* The returned `cancellationRequested` flag is the cross-process cancellation
|
|
27
|
+
* channel. A claimant in another process never sees the attempt-scoped
|
|
28
|
+
* `AbortSignal`, so renewal is where it learns that cancellation was requested.
|
|
29
|
+
*/
|
|
30
|
+
export declare function renewClaim(runtime: MailboxRuntime, options: {
|
|
31
|
+
readonly commandId: string;
|
|
32
|
+
readonly attemptToken: string;
|
|
33
|
+
readonly progress?: JSONValue | undefined;
|
|
34
|
+
}): Promise<ApplicationCommandRenewalResult>;
|
|
35
|
+
/** Settle a claimed command successfully. */
|
|
36
|
+
export declare function acknowledgeClaim(runtime: MailboxRuntime, options: {
|
|
37
|
+
readonly commandId: string;
|
|
38
|
+
readonly attemptToken: string;
|
|
39
|
+
readonly outcome?: JSONValue | undefined;
|
|
40
|
+
}): Promise<ApplicationCommandSettleResult>;
|
|
41
|
+
/**
|
|
42
|
+
* Settle a claimed command as failed, optionally scheduling a retry at the
|
|
43
|
+
* command's original FIFO position.
|
|
44
|
+
*/
|
|
45
|
+
export declare function rejectClaim(runtime: MailboxRuntime, options: {
|
|
46
|
+
readonly commandId: string;
|
|
47
|
+
readonly attemptToken: string;
|
|
48
|
+
readonly failure: ApplicationCommandFailure;
|
|
49
|
+
readonly retry: boolean;
|
|
50
|
+
}): Promise<ApplicationCommandSettleResult>;
|
|
51
|
+
/**
|
|
52
|
+
* Record a durable cancellation request and, when the claimant is in this
|
|
53
|
+
* process, abort its attempt-scoped signal.
|
|
54
|
+
*
|
|
55
|
+
* Cancellation is durable before any acknowledgement: the abort fires only
|
|
56
|
+
* after the record commits, so a crash between the two cannot leave a claimant
|
|
57
|
+
* aborted without the request being persisted.
|
|
58
|
+
*/
|
|
59
|
+
export declare function requestCancellation(runtime: MailboxRuntime, options: {
|
|
60
|
+
readonly commandId: string;
|
|
61
|
+
readonly reason?: string | undefined;
|
|
62
|
+
}): Promise<ApplicationCommandCancellationResult>;
|
|
63
|
+
/**
|
|
64
|
+
* Read whether a cancelled command's claimant has finished.
|
|
65
|
+
*
|
|
66
|
+
* `pending` means the mailbox has not seen the attempt settle. It never claims
|
|
67
|
+
* the handler stopped — only that cleanup is still outstanding.
|
|
68
|
+
*/
|
|
69
|
+
export declare function readCleanupState(runtime: MailboxRuntime, commandId: string): Promise<ApplicationCommandCleanupResult>;
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { leaseCommitSerial } from "./application-primitive-attempt-registry.js";
|
|
2
|
+
import {
|
|
3
|
+
commitCommandTransition,
|
|
4
|
+
isTerminalRecord,
|
|
5
|
+
MailboxContentionError,
|
|
6
|
+
MAX_MAILBOX_TRANSITION_ATTEMPTS,
|
|
7
|
+
releaseAttemptController,
|
|
8
|
+
releaseAttemptsForCommand,
|
|
9
|
+
toApplicationCommandReceipt
|
|
10
|
+
} from "./mailbox-internals.js";
|
|
11
|
+
import { commitMailboxTransition, loadCommand, planCommandTransition } from "./mailbox-storage.js";
|
|
12
|
+
import { recoverExpiredCommand } from "./mailbox-transitions-recovery.js";
|
|
13
|
+
import {
|
|
14
|
+
acknowledgeCommand,
|
|
15
|
+
rejectCommand,
|
|
16
|
+
renewCommandLease,
|
|
17
|
+
requestCommandCancellation
|
|
18
|
+
} from "./mailbox-transitions.js";
|
|
19
|
+
import { isApplicationCommandLeased } from "./mailbox-types.js";
|
|
20
|
+
export async function renewClaim(runtime, options) {
|
|
21
|
+
for (let attempt = 1;attempt <= MAX_MAILBOX_TRANSITION_ATTEMPTS; attempt += 1) {
|
|
22
|
+
const loaded = await loadCommand(runtime.storage, runtime.keys, options.commandId);
|
|
23
|
+
if (loaded === null)
|
|
24
|
+
return { status: "unknown" };
|
|
25
|
+
const now = runtime.now(), transition = renewCommandLease(loaded.record, {
|
|
26
|
+
attemptToken: options.attemptToken,
|
|
27
|
+
now,
|
|
28
|
+
progress: options.progress
|
|
29
|
+
});
|
|
30
|
+
if (!transition.ok) {
|
|
31
|
+
releaseAttemptController(runtime, options.attemptToken, "This attempt is no longer current: its renewal was refused.", options.commandId);
|
|
32
|
+
return {
|
|
33
|
+
status: transition.reason === "deadline-exceeded" ? "deadline-exceeded" : "stale",
|
|
34
|
+
receipt: toApplicationCommandReceipt(loaded.record)
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (!await commitMailboxTransition(runtime.storage, runtime.events, {
|
|
38
|
+
...planCommandTransition(runtime.keys, {
|
|
39
|
+
previous: loaded.record,
|
|
40
|
+
expectedBytes: loaded.bytes,
|
|
41
|
+
next: transition.next,
|
|
42
|
+
event: null,
|
|
43
|
+
now
|
|
44
|
+
})
|
|
45
|
+
}))
|
|
46
|
+
continue;
|
|
47
|
+
if (runtime.now() >= transition.next.absoluteDeadlineAt) {
|
|
48
|
+
const receipt = await deadLetterRenewed(runtime, options.commandId, toApplicationCommandReceipt(transition.next));
|
|
49
|
+
releaseAttemptController(runtime, options.attemptToken, "The application mailbox dead-lettered this command at its absolute deadline.", options.commandId);
|
|
50
|
+
return { status: "deadline-exceeded", receipt };
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
status: "renewed",
|
|
54
|
+
visibilityExpiresAt: transition.next.visibilityExpiresAt,
|
|
55
|
+
cancellationRequested: transition.next.state === "cancellation-requested",
|
|
56
|
+
receipt: toApplicationCommandReceipt(transition.next)
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
throw new MailboxContentionError("renew", options.commandId);
|
|
60
|
+
}
|
|
61
|
+
async function deadLetterRenewed(runtime, commandId, renewed) {
|
|
62
|
+
const loaded = await loadCommand(runtime.storage, runtime.keys, commandId);
|
|
63
|
+
if (loaded === null)
|
|
64
|
+
return renewed;
|
|
65
|
+
const receipt = await deadLetterExpired(runtime, loaded, runtime.now());
|
|
66
|
+
if (receipt !== null)
|
|
67
|
+
return receipt;
|
|
68
|
+
const current = await loadCommand(runtime.storage, runtime.keys, commandId);
|
|
69
|
+
return current === null ? renewed : toApplicationCommandReceipt(current.record);
|
|
70
|
+
}
|
|
71
|
+
export async function acknowledgeClaim(runtime, options) {
|
|
72
|
+
return settle(runtime, options.commandId, options.attemptToken, "acknowledge", (record, now) => acknowledgeCommand(record, {
|
|
73
|
+
attemptToken: options.attemptToken,
|
|
74
|
+
now,
|
|
75
|
+
outcome: options.outcome
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
export async function rejectClaim(runtime, options) {
|
|
79
|
+
return settle(runtime, options.commandId, options.attemptToken, "reject", (record, now) => rejectCommand(record, {
|
|
80
|
+
attemptToken: options.attemptToken,
|
|
81
|
+
now,
|
|
82
|
+
retry: options.retry,
|
|
83
|
+
failure: options.failure,
|
|
84
|
+
retryBackoffMs: runtime.policy.retryBackoffMs,
|
|
85
|
+
maxRetryBackoffMs: runtime.policy.maxRetryBackoffMs
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
async function settle(runtime, commandId, attemptToken, operation, decide) {
|
|
89
|
+
for (let attempt = 1;attempt <= MAX_MAILBOX_TRANSITION_ATTEMPTS; attempt += 1) {
|
|
90
|
+
const loaded = await loadCommand(runtime.storage, runtime.keys, commandId);
|
|
91
|
+
if (loaded === null) {
|
|
92
|
+
releaseRefusedAttempt(runtime, commandId, attemptToken);
|
|
93
|
+
return { status: "unknown" };
|
|
94
|
+
}
|
|
95
|
+
const now = runtime.now(), transition = decide(loaded.record, now);
|
|
96
|
+
if (!transition.ok) {
|
|
97
|
+
releaseRefusedAttempt(runtime, commandId, attemptToken);
|
|
98
|
+
return {
|
|
99
|
+
status: transition.reason === "deadline-exceeded" ? "deadline-exceeded" : "stale",
|
|
100
|
+
receipt: toApplicationCommandReceipt(loaded.record)
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
if (!await commitCommandTransition(runtime, {
|
|
104
|
+
previous: loaded.record,
|
|
105
|
+
expectedBytes: loaded.bytes,
|
|
106
|
+
next: transition.next,
|
|
107
|
+
now
|
|
108
|
+
}))
|
|
109
|
+
continue;
|
|
110
|
+
if (isApplicationCommandLeased(loaded.record))
|
|
111
|
+
releaseAttemptController(runtime, loaded.record.attemptToken, "The application mailbox released this attempt when the command settled.");
|
|
112
|
+
return {
|
|
113
|
+
status: isTerminalRecord(transition.next) ? "settled" : "retrying",
|
|
114
|
+
receipt: toApplicationCommandReceipt(transition.next)
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
throw new MailboxContentionError(operation, commandId);
|
|
118
|
+
}
|
|
119
|
+
function releaseTerminalAttempts(runtime, commandId, observedAt) {
|
|
120
|
+
releaseAttemptsForCommand(runtime, commandId, "This command is terminal; its attempt is over.", void 0, observedAt);
|
|
121
|
+
}
|
|
122
|
+
function releaseRefusedAttempt(runtime, commandId, attemptToken) {
|
|
123
|
+
releaseAttemptController(runtime, attemptToken, "This attempt is no longer current: its settlement was refused.", commandId);
|
|
124
|
+
}
|
|
125
|
+
export async function requestCancellation(runtime, options) {
|
|
126
|
+
for (let attempt = 1;attempt <= MAX_MAILBOX_TRANSITION_ATTEMPTS; attempt += 1) {
|
|
127
|
+
const observedAt = leaseCommitSerial(), loaded = await loadCommand(runtime.storage, runtime.keys, options.commandId);
|
|
128
|
+
if (loaded === null) {
|
|
129
|
+
releaseTerminalAttempts(runtime, options.commandId, observedAt);
|
|
130
|
+
return { status: "unknown" };
|
|
131
|
+
}
|
|
132
|
+
const now = runtime.now(), transition = requestCommandCancellation(loaded.record, { now, reason: options.reason });
|
|
133
|
+
if (!transition.ok) {
|
|
134
|
+
if (transition.reason === "deadline-exceeded") {
|
|
135
|
+
const expired = await deadLetterExpired(runtime, loaded, now);
|
|
136
|
+
if (expired === null)
|
|
137
|
+
continue;
|
|
138
|
+
releaseTerminalAttempts(runtime, options.commandId, observedAt);
|
|
139
|
+
return { status: "already-terminal", receipt: expired };
|
|
140
|
+
}
|
|
141
|
+
if (transition.reason === "not-leased" && isApplicationCommandLeased(loaded.record)) {
|
|
142
|
+
abortLocalClaimant(runtime, loaded.record.attemptToken);
|
|
143
|
+
return {
|
|
144
|
+
status: "requested",
|
|
145
|
+
receipt: toApplicationCommandReceipt(loaded.record),
|
|
146
|
+
cleanupPending: !0
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
releaseTerminalAttempts(runtime, options.commandId, observedAt);
|
|
150
|
+
return { status: "already-terminal", receipt: toApplicationCommandReceipt(loaded.record) };
|
|
151
|
+
}
|
|
152
|
+
if (!await commitCommandTransition(runtime, {
|
|
153
|
+
previous: loaded.record,
|
|
154
|
+
expectedBytes: loaded.bytes,
|
|
155
|
+
next: transition.next,
|
|
156
|
+
now
|
|
157
|
+
}))
|
|
158
|
+
continue;
|
|
159
|
+
if (transition.next.state === "cancellation-requested") {
|
|
160
|
+
abortLocalClaimant(runtime, transition.next.attemptToken);
|
|
161
|
+
return {
|
|
162
|
+
status: "requested",
|
|
163
|
+
receipt: toApplicationCommandReceipt(transition.next),
|
|
164
|
+
cleanupPending: !0
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
return { status: "cancelled", receipt: toApplicationCommandReceipt(transition.next) };
|
|
168
|
+
}
|
|
169
|
+
throw new MailboxContentionError("cancel", options.commandId);
|
|
170
|
+
}
|
|
171
|
+
async function deadLetterExpired(runtime, loaded, now) {
|
|
172
|
+
const transition = recoverExpiredCommand(loaded.record, {
|
|
173
|
+
now,
|
|
174
|
+
retryBackoffMs: runtime.policy.retryBackoffMs,
|
|
175
|
+
maxRetryBackoffMs: runtime.policy.maxRetryBackoffMs
|
|
176
|
+
});
|
|
177
|
+
if (!transition.ok)
|
|
178
|
+
return null;
|
|
179
|
+
if (!await commitCommandTransition(runtime, {
|
|
180
|
+
previous: loaded.record,
|
|
181
|
+
expectedBytes: loaded.bytes,
|
|
182
|
+
next: transition.next,
|
|
183
|
+
now
|
|
184
|
+
}))
|
|
185
|
+
return null;
|
|
186
|
+
if (isApplicationCommandLeased(loaded.record))
|
|
187
|
+
releaseAttemptController(runtime, loaded.record.attemptToken, "The application mailbox dead-lettered this command at its absolute deadline.");
|
|
188
|
+
return toApplicationCommandReceipt(transition.next);
|
|
189
|
+
}
|
|
190
|
+
function abortLocalClaimant(runtime, attemptToken) {
|
|
191
|
+
const registration = runtime.attemptControllers.get(attemptToken);
|
|
192
|
+
if (registration !== void 0 && !registration.controller.signal.aborted)
|
|
193
|
+
registration.controller.abort(Error("The application mailbox cancelled this command."));
|
|
194
|
+
}
|
|
195
|
+
export async function readCleanupState(runtime, commandId) {
|
|
196
|
+
const observedAt = leaseCommitSerial(), loaded = await loadCommand(runtime.storage, runtime.keys, commandId);
|
|
197
|
+
if (loaded === null) {
|
|
198
|
+
releaseAttemptsForCommand(runtime, commandId, "This command no longer exists; its receipt was retired.", void 0, observedAt);
|
|
199
|
+
return { status: "unknown" };
|
|
200
|
+
}
|
|
201
|
+
releaseAttemptsForCommand(runtime, commandId, "This attempt is no longer the current lease on its command.", isApplicationCommandLeased(loaded.record) ? loaded.record.attemptToken : void 0, observedAt);
|
|
202
|
+
const receipt = toApplicationCommandReceipt(loaded.record);
|
|
203
|
+
if (receipt.terminalAt !== void 0 && receipt.cleanupPending !== !0)
|
|
204
|
+
return { status: "settled", receipt };
|
|
205
|
+
return { status: "pending", receipt };
|
|
206
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable reads, index maintenance, and the atomic state-plus-event commit for
|
|
3
|
+
* the application command mailbox (WFT-84).
|
|
4
|
+
*
|
|
5
|
+
* Every mutation goes through {@link commitMailboxTransition}, the mailbox's binding
|
|
6
|
+
* of the shared `commitApplicationTransition`. When the mailbox
|
|
7
|
+
* was built with an event sink, the caller's state operations and the sink's own
|
|
8
|
+
* event write land in one `conditionalBatch`, so no restart can expose the state
|
|
9
|
+
* transition without its event or the other way round. Without a sink the same
|
|
10
|
+
* operations commit through `storageConditionalBatch` directly, which keeps the
|
|
11
|
+
* atomicity guarantee and makes a lost compare-and-swap exactly detectable.
|
|
12
|
+
*
|
|
13
|
+
* @module core/mailbox-storage
|
|
14
|
+
*/
|
|
15
|
+
import { type BatchOperation, type ConditionalBatchCondition, type Storage } from '../storage/interface.ts';
|
|
16
|
+
import { type ApplicationCommitPlan, type ApplicationEventSink } from './application-primitive-commit.ts';
|
|
17
|
+
import type { LoadedCommandRecord } from './mailbox-contract.ts';
|
|
18
|
+
import { type ApplicationCommandIdempotencyRecord, type ApplicationCommandRecord, type MailboxRecord } from './mailbox-types.ts';
|
|
19
|
+
/** Every key builder for one `(namespace, resourceId)` mailbox, bound once. */
|
|
20
|
+
export type MailboxKeys = Readonly<{
|
|
21
|
+
header: string;
|
|
22
|
+
sinkProbe: (nonce: string) => string;
|
|
23
|
+
commandPrefix: string;
|
|
24
|
+
command: (commandId: string) => string;
|
|
25
|
+
readyPrefix: string;
|
|
26
|
+
ready: (sequence: number) => string;
|
|
27
|
+
bySequencePrefix: string;
|
|
28
|
+
bySequence: (sequence: number) => string;
|
|
29
|
+
idempotency: (key: string) => string;
|
|
30
|
+
terminalPrefix: string;
|
|
31
|
+
terminal: (terminalAt: number, commandId: string) => string;
|
|
32
|
+
}>;
|
|
33
|
+
/**
|
|
34
|
+
* Bind every mailbox storage key to one namespace and resource.
|
|
35
|
+
*/
|
|
36
|
+
export declare function createMailboxKeys(namespace: string, resourceId: string): MailboxKeys;
|
|
37
|
+
/** The empty header a mailbox starts from, so a first admission has something to compare against. */
|
|
38
|
+
export declare function emptyMailboxRecord(namespace: string, resourceId: string): MailboxRecord;
|
|
39
|
+
/** A header read together with the exact bytes it decoded from, for compare-and-swap. */
|
|
40
|
+
export type LoadedMailboxRecord = {
|
|
41
|
+
readonly record: MailboxRecord;
|
|
42
|
+
/** `null` when the mailbox has never been written — the condition for a first admission. */
|
|
43
|
+
readonly bytes: Uint8Array | null;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Read the per-mailbox header, treating an absent key as a fresh mailbox.
|
|
47
|
+
*
|
|
48
|
+
* @throws {PersistedDataCorruptError} When the stored header is malformed.
|
|
49
|
+
*/
|
|
50
|
+
export declare function loadMailboxHeader(storage: Storage, keys: MailboxKeys, namespace: string, resourceId: string): Promise<LoadedMailboxRecord>;
|
|
51
|
+
/**
|
|
52
|
+
* Read one command record with the exact bytes it decoded from.
|
|
53
|
+
*
|
|
54
|
+
* @throws {PersistedDataCorruptError} When the stored record is malformed.
|
|
55
|
+
*/
|
|
56
|
+
export declare function loadCommand(storage: Storage, keys: MailboxKeys, commandId: string): Promise<LoadedCommandRecord | null>;
|
|
57
|
+
/**
|
|
58
|
+
* Read the idempotency binding for a retry key.
|
|
59
|
+
*
|
|
60
|
+
* @throws {PersistedDataCorruptError} When the stored binding is malformed.
|
|
61
|
+
*/
|
|
62
|
+
export declare function loadIdempotencyBinding(storage: Storage, keys: MailboxKeys, idempotencyKey: string): Promise<{
|
|
63
|
+
readonly record: ApplicationCommandIdempotencyRecord;
|
|
64
|
+
readonly bytes: Uint8Array;
|
|
65
|
+
} | null>;
|
|
66
|
+
/**
|
|
67
|
+
* Read the FIFO head: the lowest-sequence entry still in the delivery index.
|
|
68
|
+
*
|
|
69
|
+
* Strict FIFO is the mailbox's ordering contract, so the head is the only entry
|
|
70
|
+
* a claim may consider. A later command never overtakes a delayed head.
|
|
71
|
+
*
|
|
72
|
+
* @throws {PersistedDataCorruptError} When an index entry is malformed.
|
|
73
|
+
*/
|
|
74
|
+
export declare function loadDeliveryHead(storage: Storage, keys: MailboxKeys): Promise<{
|
|
75
|
+
readonly key: string;
|
|
76
|
+
readonly bytes: Uint8Array;
|
|
77
|
+
readonly commandId: string;
|
|
78
|
+
} | null>;
|
|
79
|
+
/**
|
|
80
|
+
* Put/delete operations that keep the delivery and terminal indexes consistent
|
|
81
|
+
* with a record's new state.
|
|
82
|
+
*
|
|
83
|
+
* The delivery entry is keyed by the command's original admission sequence, so
|
|
84
|
+
* a redelivered command re-enters the queue at the position it was first
|
|
85
|
+
* admitted to rather than at the back.
|
|
86
|
+
*/
|
|
87
|
+
export declare function indexOperationsFor(keys: MailboxKeys, previous: ApplicationCommandRecord | null, next: ApplicationCommandRecord): BatchOperation[];
|
|
88
|
+
/** Whether a record is in the delivery index: admitted or released, not yet claimed or settled. */
|
|
89
|
+
export declare function isWaitingState(record: ApplicationCommandRecord): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Commit one mailbox transition, atomically with its fleet event when a sink is
|
|
92
|
+
* configured. The mailbox's binding of the shared commit: see
|
|
93
|
+
* `application-primitive-commit.ts` for the compare-and-swap classification and
|
|
94
|
+
* the sink probe.
|
|
95
|
+
*/
|
|
96
|
+
export declare function commitMailboxTransition(storage: Storage, events: ApplicationEventSink | undefined, plan: ApplicationCommitPlan): Promise<boolean>;
|
|
97
|
+
/**
|
|
98
|
+
* Persist a command record plus its index maintenance as one plan.
|
|
99
|
+
*
|
|
100
|
+
* `expectedBytes` must be the exact bytes the record was read as — not a
|
|
101
|
+
* re-encoding of the decoded value, which `conditionalBatch`'s whole-value byte
|
|
102
|
+
* comparison would reject.
|
|
103
|
+
*/
|
|
104
|
+
export declare function planCommandTransition(keys: MailboxKeys, options: {
|
|
105
|
+
readonly previous: ApplicationCommandRecord | null;
|
|
106
|
+
readonly expectedBytes: Uint8Array | null;
|
|
107
|
+
readonly next: ApplicationCommandRecord;
|
|
108
|
+
readonly event: {
|
|
109
|
+
readonly kind: string;
|
|
110
|
+
readonly payload: unknown;
|
|
111
|
+
} | null;
|
|
112
|
+
readonly now: number;
|
|
113
|
+
readonly extraConditions?: readonly ConditionalBatchCondition[] | undefined;
|
|
114
|
+
readonly extraOperations?: readonly BatchOperation[] | undefined;
|
|
115
|
+
}): ApplicationCommitPlan;
|
|
116
|
+
/** The put operation that advances the mailbox header. */
|
|
117
|
+
export declare function headerOperation(keys: MailboxKeys, record: MailboxRecord): BatchOperation;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import {
|
|
2
|
+
KEYS
|
|
3
|
+
} from "../storage/interface.js";
|
|
4
|
+
import {
|
|
5
|
+
commitApplicationTransition
|
|
6
|
+
} from "./application-primitive-commit.js";
|
|
7
|
+
import { decodeApplicationCommandRecord, encodeApplicationCommandRecord } from "./mailbox-codec.js";
|
|
8
|
+
import {
|
|
9
|
+
decodeApplicationCommandIdempotencyRecord,
|
|
10
|
+
decodeApplicationReadyEntry,
|
|
11
|
+
decodeMailboxRecord,
|
|
12
|
+
encodeApplicationReadyEntry,
|
|
13
|
+
encodeMailboxRecord
|
|
14
|
+
} from "./mailbox-index-codec.js";
|
|
15
|
+
import {
|
|
16
|
+
MAILBOX_RECORD_VERSION
|
|
17
|
+
} from "./mailbox-types.js";
|
|
18
|
+
export function createMailboxKeys(namespace, resourceId) {
|
|
19
|
+
return {
|
|
20
|
+
header: KEYS.applicationMailbox(namespace, resourceId),
|
|
21
|
+
sinkProbe: (nonce) => KEYS.applicationMailboxSinkProbe(namespace, resourceId, nonce),
|
|
22
|
+
commandPrefix: KEYS.applicationCommandPrefix(namespace, resourceId),
|
|
23
|
+
command: (commandId) => KEYS.applicationCommand(namespace, resourceId, commandId),
|
|
24
|
+
readyPrefix: KEYS.applicationCommandReadyPrefix(namespace, resourceId),
|
|
25
|
+
ready: (sequence) => KEYS.applicationCommandReady(namespace, resourceId, sequence),
|
|
26
|
+
bySequencePrefix: KEYS.applicationCommandBySequencePrefix(namespace, resourceId),
|
|
27
|
+
bySequence: (sequence) => KEYS.applicationCommandBySequence(namespace, resourceId, sequence),
|
|
28
|
+
idempotency: (key) => KEYS.applicationCommandIdempotency(namespace, resourceId, key),
|
|
29
|
+
terminalPrefix: KEYS.applicationCommandTerminalPrefix(namespace, resourceId),
|
|
30
|
+
terminal: (terminalAt, commandId) => KEYS.applicationCommandTerminal(namespace, resourceId, terminalAt, commandId)
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export function emptyMailboxRecord(namespace, resourceId) {
|
|
34
|
+
return {
|
|
35
|
+
recordVersion: MAILBOX_RECORD_VERSION,
|
|
36
|
+
namespace,
|
|
37
|
+
resourceId,
|
|
38
|
+
nextSequence: 0,
|
|
39
|
+
openCount: 0,
|
|
40
|
+
admittedCount: 0
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export async function loadMailboxHeader(storage, keys, namespace, resourceId) {
|
|
44
|
+
const bytes = await storage.get(keys.header);
|
|
45
|
+
if (bytes === null)
|
|
46
|
+
return { record: emptyMailboxRecord(namespace, resourceId), bytes: null };
|
|
47
|
+
return { record: decodeMailboxRecord(bytes, keys.header), bytes };
|
|
48
|
+
}
|
|
49
|
+
export async function loadCommand(storage, keys, commandId) {
|
|
50
|
+
const key = keys.command(commandId), bytes = await storage.get(key);
|
|
51
|
+
if (bytes === null)
|
|
52
|
+
return null;
|
|
53
|
+
return { record: decodeApplicationCommandRecord(bytes, key), bytes };
|
|
54
|
+
}
|
|
55
|
+
export async function loadIdempotencyBinding(storage, keys, idempotencyKey) {
|
|
56
|
+
const key = keys.idempotency(idempotencyKey), bytes = await storage.get(key);
|
|
57
|
+
if (bytes === null)
|
|
58
|
+
return null;
|
|
59
|
+
return { record: decodeApplicationCommandIdempotencyRecord(bytes, key), bytes };
|
|
60
|
+
}
|
|
61
|
+
export async function loadDeliveryHead(storage, keys) {
|
|
62
|
+
for await (const [key, value] of storage.scan(keys.readyPrefix, { limit: 1 }))
|
|
63
|
+
return { key, bytes: value, commandId: decodeApplicationReadyEntry(value, key) };
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
export function indexOperationsFor(keys, previous, next) {
|
|
67
|
+
const operations = [], wasWaiting = previous !== null && isWaitingState(previous), willWait = isWaitingState(next);
|
|
68
|
+
if (wasWaiting && !willWait)
|
|
69
|
+
operations.push({ type: "delete", key: keys.ready(next.sequence) });
|
|
70
|
+
if (willWait && !wasWaiting)
|
|
71
|
+
operations.push({
|
|
72
|
+
type: "put",
|
|
73
|
+
key: keys.ready(next.sequence),
|
|
74
|
+
value: encodeApplicationReadyEntry(next.commandId)
|
|
75
|
+
});
|
|
76
|
+
if (isTerminalState(next) && (previous === null || !isTerminalState(previous)))
|
|
77
|
+
operations.push({
|
|
78
|
+
type: "put",
|
|
79
|
+
key: keys.terminal(next.terminalAt, next.commandId),
|
|
80
|
+
value: encodeApplicationReadyEntry(next.commandId)
|
|
81
|
+
});
|
|
82
|
+
return operations;
|
|
83
|
+
}
|
|
84
|
+
export function isWaitingState(record) {
|
|
85
|
+
return record.state === "accepted" || record.state === "available";
|
|
86
|
+
}
|
|
87
|
+
function isTerminalState(record) {
|
|
88
|
+
return record.state === "applied" || record.state === "rejected" || record.state === "cancelled" || record.state === "dead-lettered";
|
|
89
|
+
}
|
|
90
|
+
export function commitMailboxTransition(storage, events, plan) {
|
|
91
|
+
return commitApplicationTransition(storage, events, plan, "application mailbox");
|
|
92
|
+
}
|
|
93
|
+
export function planCommandTransition(keys, options) {
|
|
94
|
+
return {
|
|
95
|
+
sinkProbeKey: keys.sinkProbe(crypto.randomUUID()),
|
|
96
|
+
conditions: [
|
|
97
|
+
{ key: keys.command(options.next.commandId), expectedValue: options.expectedBytes },
|
|
98
|
+
...options.extraConditions ?? []
|
|
99
|
+
],
|
|
100
|
+
operations: [
|
|
101
|
+
{
|
|
102
|
+
type: "put",
|
|
103
|
+
key: keys.command(options.next.commandId),
|
|
104
|
+
value: encodeApplicationCommandRecord(options.next)
|
|
105
|
+
},
|
|
106
|
+
...indexOperationsFor(keys, options.previous, options.next),
|
|
107
|
+
...options.extraOperations ?? []
|
|
108
|
+
],
|
|
109
|
+
event: options.event,
|
|
110
|
+
now: options.now
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
export function headerOperation(keys, record) {
|
|
114
|
+
return { type: "put", key: keys.header, value: encodeMailboxRecord(record) };
|
|
115
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The primitives every mailbox transition shares (WFT-84):
|
|
3
|
+
* the rejection vocabulary, the transition result shape, non-terminal
|
|
4
|
+
* narrowing, identity-field carry-over, and retry backoff.
|
|
5
|
+
*
|
|
6
|
+
* Extracted so `mailbox-transitions.ts` and
|
|
7
|
+
* `mailbox-transitions-recovery.ts` can both use them without
|
|
8
|
+
* importing each other — a runtime cycle this repository forbids outright.
|
|
9
|
+
*
|
|
10
|
+
* @module core/mailbox-transition-helpers
|
|
11
|
+
*/
|
|
12
|
+
import { computeRetryBackoffMs } from './application-primitive-timing.ts';
|
|
13
|
+
import type { ApplicationCommandAccepted, ApplicationCommandAvailable, ApplicationCommandCancelling, ApplicationCommandClaimed, ApplicationCommandRecord, ApplicationCommandTerminalRecord } from './mailbox-types.ts';
|
|
14
|
+
export { computeRetryBackoffMs };
|
|
15
|
+
/**
|
|
16
|
+
* Why a proposed transition is illegal. Stable and low-cardinality, so callers
|
|
17
|
+
* can map each reason onto a discriminated result without string matching.
|
|
18
|
+
*/
|
|
19
|
+
export type MailboxTransitionRejection = 'stale-attempt' | 'not-leased' | 'not-waiting' | 'not-due' | 'deadline-exceeded' | 'already-terminal';
|
|
20
|
+
/**
|
|
21
|
+
* The outcome of a proposed transition: the record to persist, or why the edge
|
|
22
|
+
* is illegal.
|
|
23
|
+
*/
|
|
24
|
+
export type MailboxTransition<TNext> = {
|
|
25
|
+
readonly ok: true;
|
|
26
|
+
readonly next: TNext;
|
|
27
|
+
} | {
|
|
28
|
+
readonly ok: false;
|
|
29
|
+
readonly reason: MailboxTransitionRejection;
|
|
30
|
+
};
|
|
31
|
+
export declare function rejectedTransition<TNext>(reason: MailboxTransitionRejection): MailboxTransition<TNext>;
|
|
32
|
+
export declare function succeededTransition<TNext>(next: TNext): MailboxTransition<TNext>;
|
|
33
|
+
/**
|
|
34
|
+
* Narrow a record to the four non-terminal states.
|
|
35
|
+
*
|
|
36
|
+
* `isApplicationCommandTerminalState` narrows the `state` string but not the
|
|
37
|
+
* record it came from, so every transition below needs this to stay cast-free.
|
|
38
|
+
*/
|
|
39
|
+
export declare function isTerminalCommandRecord(record: ApplicationCommandRecord): record is ApplicationCommandTerminalRecord;
|
|
40
|
+
export declare function nonTerminalCommandRecord(record: ApplicationCommandRecord): ApplicationCommandAccepted | ApplicationCommandAvailable | ApplicationCommandClaimed | ApplicationCommandCancelling | null;
|
|
41
|
+
/** Strip the state-specific fields so a transition rebuilds a record from identity alone. */
|
|
42
|
+
export declare function applicationCommandIdentityFields(record: ApplicationCommandRecord): {
|
|
43
|
+
readonly recordVersion: 1;
|
|
44
|
+
readonly namespace: string;
|
|
45
|
+
readonly resourceId: string;
|
|
46
|
+
readonly commandId: string;
|
|
47
|
+
readonly sequence: number;
|
|
48
|
+
readonly idempotencyKey: string | undefined;
|
|
49
|
+
readonly caller: string;
|
|
50
|
+
readonly target: string;
|
|
51
|
+
readonly kind: string;
|
|
52
|
+
readonly payload: import("./mailbox-types.ts").ApplicationCommandPayload;
|
|
53
|
+
readonly payloadDigest: string;
|
|
54
|
+
readonly payloadMediaType: string | undefined;
|
|
55
|
+
readonly payloadSchema: string | undefined;
|
|
56
|
+
readonly causation: Readonly<{
|
|
57
|
+
correlationId?: string | undefined;
|
|
58
|
+
causationId?: string | undefined;
|
|
59
|
+
traceparent?: string | undefined;
|
|
60
|
+
}> | undefined;
|
|
61
|
+
readonly acceptedAt: number;
|
|
62
|
+
readonly absoluteDeadlineAt: number;
|
|
63
|
+
readonly maxAttempts: number;
|
|
64
|
+
readonly visibilityTimeoutMs: number;
|
|
65
|
+
readonly generation: number;
|
|
66
|
+
readonly attempt: number;
|
|
67
|
+
readonly retryCount: number;
|
|
68
|
+
readonly firstClaimedAt: number | undefined;
|
|
69
|
+
readonly availableAt: number;
|
|
70
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { computeRetryBackoffMs } from "./application-primitive-timing.js";
|
|
2
|
+
import { MAILBOX_RECORD_VERSION, isApplicationCommandTerminalState } from "./mailbox-types.js";
|
|
3
|
+
|
|
4
|
+
export { computeRetryBackoffMs };
|
|
5
|
+
export function rejectedTransition(reason) {
|
|
6
|
+
return { ok: !1, reason };
|
|
7
|
+
}
|
|
8
|
+
export function succeededTransition(next) {
|
|
9
|
+
return { ok: !0, next };
|
|
10
|
+
}
|
|
11
|
+
export function isTerminalCommandRecord(record) {
|
|
12
|
+
return isApplicationCommandTerminalState(record.state);
|
|
13
|
+
}
|
|
14
|
+
export function nonTerminalCommandRecord(record) {
|
|
15
|
+
return isTerminalCommandRecord(record) ? null : record;
|
|
16
|
+
}
|
|
17
|
+
export function applicationCommandIdentityFields(record) {
|
|
18
|
+
return {
|
|
19
|
+
recordVersion: MAILBOX_RECORD_VERSION,
|
|
20
|
+
namespace: record.namespace,
|
|
21
|
+
resourceId: record.resourceId,
|
|
22
|
+
commandId: record.commandId,
|
|
23
|
+
sequence: record.sequence,
|
|
24
|
+
idempotencyKey: record.idempotencyKey,
|
|
25
|
+
caller: record.caller,
|
|
26
|
+
target: record.target,
|
|
27
|
+
kind: record.kind,
|
|
28
|
+
payload: record.payload,
|
|
29
|
+
payloadDigest: record.payloadDigest,
|
|
30
|
+
payloadMediaType: record.payloadMediaType,
|
|
31
|
+
payloadSchema: record.payloadSchema,
|
|
32
|
+
causation: record.causation,
|
|
33
|
+
acceptedAt: record.acceptedAt,
|
|
34
|
+
absoluteDeadlineAt: record.absoluteDeadlineAt,
|
|
35
|
+
maxAttempts: record.maxAttempts,
|
|
36
|
+
visibilityTimeoutMs: record.visibilityTimeoutMs,
|
|
37
|
+
generation: record.generation + 1,
|
|
38
|
+
attempt: record.attempt,
|
|
39
|
+
retryCount: record.retryCount,
|
|
40
|
+
firstClaimedAt: record.firstClaimedAt,
|
|
41
|
+
availableAt: record.availableAt
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The time-driven recovery transitions for the application command mailbox
|
|
3
|
+
* (WFT-84): reclaiming an expired lease and terminalizing a command past its
|
|
4
|
+
* absolute deadline.
|
|
5
|
+
*
|
|
6
|
+
* Split out of `mailbox-transitions.ts` only to keep both files
|
|
7
|
+
* under this repository's file-size ceiling; `recoverExpiredCommand` is
|
|
8
|
+
* re-exported from there so callers still have one import.
|
|
9
|
+
*
|
|
10
|
+
* @module core/mailbox-transitions-recovery
|
|
11
|
+
*/
|
|
12
|
+
import { type MailboxTransition } from './mailbox-transition-helpers.ts';
|
|
13
|
+
import type { ApplicationCommandAccepted, ApplicationCommandRecord, ApplicationCommandTerminalRecord } from './mailbox-types.ts';
|
|
14
|
+
/**
|
|
15
|
+
* Recover a command whose lease expired or whose absolute deadline passed.
|
|
16
|
+
*
|
|
17
|
+
* A claimed command returns to `accepted` at its original FIFO position while
|
|
18
|
+
* attempts remain, and is dead-lettered once they are gone. A
|
|
19
|
+
* cancellation-requested command becomes `cancelled` with `cleanupPending:
|
|
20
|
+
* true` — the mailbox stopped waiting for the claimant, which is not the same
|
|
21
|
+
* as the claimant having stopped. Any non-terminal command past its absolute
|
|
22
|
+
* deadline is dead-lettered regardless of remaining attempts.
|
|
23
|
+
*/
|
|
24
|
+
export declare function recoverExpiredCommand(record: ApplicationCommandRecord, options: {
|
|
25
|
+
readonly now: number;
|
|
26
|
+
readonly retryBackoffMs: number;
|
|
27
|
+
readonly maxRetryBackoffMs: number;
|
|
28
|
+
}): MailboxTransition<ApplicationCommandAccepted | ApplicationCommandTerminalRecord>;
|