@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,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The public input, result, and option types for the durable application
|
|
3
|
+
* command mailbox (WFT-84).
|
|
4
|
+
*
|
|
5
|
+
* Two rules shape every signature here. First, expected outcomes are
|
|
6
|
+
* discriminated results, never exceptions: an idempotency conflict, a full
|
|
7
|
+
* backlog, a stale attempt token, and an already-terminal command are all
|
|
8
|
+
* ordinary control flow a caller must branch on. Exceptions are reserved for
|
|
9
|
+
* caller mistakes (`ApplicationCommandValidationError`) and corrupt persisted
|
|
10
|
+
* state (`PersistedDataCorruptError`). Second, every read is non-consuming:
|
|
11
|
+
* `receipt`, `list`, `capacity`, and `cleanupState` never claim, start, or
|
|
12
|
+
* advance work.
|
|
13
|
+
*
|
|
14
|
+
* @module core/mailbox-contract
|
|
15
|
+
*/
|
|
16
|
+
import type { BatchOperation, ConditionalBatchCondition, Storage } from '../storage/interface.ts';
|
|
17
|
+
import type { JSONValue } from './json.ts';
|
|
18
|
+
import type { ApplicationCommandCausation, ApplicationCommandFailure, ApplicationCommandPayload, ApplicationCommandRecord, ApplicationCommandState } from './mailbox-types.ts';
|
|
19
|
+
/**
|
|
20
|
+
* The transaction-composable append contract the mailbox needs from a durable
|
|
21
|
+
* event feed (WFT-83).
|
|
22
|
+
*
|
|
23
|
+
* Declared structurally rather than imported from `server/fleet-event-feed.ts`
|
|
24
|
+
* so `src/core` keeps no runtime dependency on `src/server`. A real
|
|
25
|
+
* `FleetEventFeed` satisfies it as-is — pass one straight in.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { MemoryStorage } from '@lostgradient/weft';
|
|
30
|
+
* import type { MailboxEventSink } from '@lostgradient/weft';
|
|
31
|
+
* import { createFleetEventFeed } from '@lostgradient/weft/server/handler';
|
|
32
|
+
*
|
|
33
|
+
* const events: MailboxEventSink = createFleetEventFeed(new MemoryStorage());
|
|
34
|
+
* void events;
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export type MailboxEventSink = {
|
|
38
|
+
append(event: {
|
|
39
|
+
readonly kind: string;
|
|
40
|
+
readonly emittedAtMs: number;
|
|
41
|
+
readonly payload: unknown;
|
|
42
|
+
readonly workflowId?: string | undefined;
|
|
43
|
+
}, options?: {
|
|
44
|
+
readonly conditions?: readonly ConditionalBatchCondition[] | undefined;
|
|
45
|
+
readonly operations?: readonly BatchOperation[] | undefined;
|
|
46
|
+
}): Promise<unknown>;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* What a claimant may supply when rejecting a command: only the `application`
|
|
50
|
+
* reason. `attempts-exhausted`, `deadline-exceeded`, and `cancelled` each name
|
|
51
|
+
* a mailbox-owned terminal mechanism and are written by the transition that
|
|
52
|
+
* owns it; the broader `ApplicationCommandFailure` is what receipts carry.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* import type { ApplicationCommandRejection } from '@lostgradient/weft';
|
|
57
|
+
*
|
|
58
|
+
* const rejection: ApplicationCommandRejection = { reason: 'application', message: 'unsupported kind' };
|
|
59
|
+
* console.log(rejection.reason); // 'application'
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export type ApplicationCommandRejection = Readonly<{
|
|
63
|
+
reason: 'application';
|
|
64
|
+
message?: string | undefined;
|
|
65
|
+
details?: JSONValue | undefined;
|
|
66
|
+
}>;
|
|
67
|
+
/**
|
|
68
|
+
* Construction options for one `(namespace, resourceId)` mailbox.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```ts
|
|
72
|
+
* import { MemoryStorage, type MailboxOptions } from '@lostgradient/weft';
|
|
73
|
+
*
|
|
74
|
+
* const options: MailboxOptions = {
|
|
75
|
+
* storage: new MemoryStorage(),
|
|
76
|
+
* namespace: 'bureau',
|
|
77
|
+
* resourceId: 'agent-7',
|
|
78
|
+
* maxBacklog: 512,
|
|
79
|
+
* };
|
|
80
|
+
* console.log(options.namespace); // 'bureau'
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export type MailboxOptions = {
|
|
84
|
+
/** Durable backend. Must report `conditionalBatch` support. */
|
|
85
|
+
readonly storage: Storage;
|
|
86
|
+
/** Opaque application namespace. Weft never interprets it. */
|
|
87
|
+
readonly namespace: string;
|
|
88
|
+
/** Opaque resource identifier. One mailbox, one FIFO order. */
|
|
89
|
+
readonly resourceId: string;
|
|
90
|
+
/**
|
|
91
|
+
* Optional durable event feed. When supplied, every state transition and its
|
|
92
|
+
* fleet event commit in one conditional batch, so no restart can expose one
|
|
93
|
+
* side without the other.
|
|
94
|
+
*/
|
|
95
|
+
readonly events?: MailboxEventSink | undefined;
|
|
96
|
+
/** Maximum open (non-terminal) commands. Admission past it is rejected before any write. Default 1000. */
|
|
97
|
+
readonly maxBacklog?: number | undefined;
|
|
98
|
+
/** Default claim lease duration in milliseconds. Default 30000. */
|
|
99
|
+
readonly visibilityTimeoutMs?: number | undefined;
|
|
100
|
+
/** Default absolute per-command deadline in milliseconds from admission. Default 3600000. */
|
|
101
|
+
readonly commandTimeoutMs?: number | undefined;
|
|
102
|
+
/** Default maximum claims per command before dead-lettering. Default 3. */
|
|
103
|
+
readonly maxAttempts?: number | undefined;
|
|
104
|
+
/** Retry backoff base in milliseconds. Default 1000. */
|
|
105
|
+
readonly retryBackoffMs?: number | undefined;
|
|
106
|
+
/** Ceiling on retry backoff in milliseconds. Default 60000. */
|
|
107
|
+
readonly maxRetryBackoffMs?: number | undefined;
|
|
108
|
+
/** How long a terminal receipt is retained before a maintenance sweep may delete it. Default 86400000. */
|
|
109
|
+
readonly terminalRetentionMs?: number | undefined;
|
|
110
|
+
/** Maximum bytes an inline payload may encode to. Default 262144. */
|
|
111
|
+
readonly maxInlinePayloadBytes?: number | undefined;
|
|
112
|
+
/**
|
|
113
|
+
* How many command records one maintenance scan page reads. Default 500.
|
|
114
|
+
*
|
|
115
|
+
* A pass walks the whole keyspace in pages of this size, up to a bounded page
|
|
116
|
+
* count, then hands its cursor to the next pass. Lower it on a constrained
|
|
117
|
+
* runtime that cannot afford a large scan per call.
|
|
118
|
+
*/
|
|
119
|
+
readonly maintenanceBatchSize?: number | undefined;
|
|
120
|
+
/** Injected clock. Defaults to `Date.now`. */
|
|
121
|
+
readonly now?: (() => number) | undefined;
|
|
122
|
+
/** Injected identifier source, for deterministic tests. Defaults to `crypto.randomUUID`. */
|
|
123
|
+
readonly generateId?: (() => string) | undefined;
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* A command offered to the mailbox.
|
|
127
|
+
*
|
|
128
|
+
* `commandId` is minted by the mailbox, not supplied here: `idempotencyKey` is
|
|
129
|
+
* the caller's only retry handle, and it binds to
|
|
130
|
+
* `(caller, target, kind, payloadDigest)`.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```ts
|
|
134
|
+
* import type { ApplicationCommandInput } from '@lostgradient/weft';
|
|
135
|
+
*
|
|
136
|
+
* const command: ApplicationCommandInput = {
|
|
137
|
+
* caller: 'user:42',
|
|
138
|
+
* target: 'agent:7',
|
|
139
|
+
* kind: 'steer',
|
|
140
|
+
* payload: { form: 'inline', value: { text: 'stop' } },
|
|
141
|
+
* idempotencyKey: 'steer-1',
|
|
142
|
+
* };
|
|
143
|
+
* console.log(command.kind); // 'steer'
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
export type ApplicationCommandInput = {
|
|
147
|
+
/** Opaque caller identity. Part of the idempotency binding. */
|
|
148
|
+
readonly caller: string;
|
|
149
|
+
/** Opaque target within the resource. Part of the idempotency binding. */
|
|
150
|
+
readonly target: string;
|
|
151
|
+
/** Opaque command kind. Part of the idempotency binding. */
|
|
152
|
+
readonly kind: string;
|
|
153
|
+
readonly payload: ApplicationCommandPayload;
|
|
154
|
+
/** Retry handle. Absent means every admission creates a new command. */
|
|
155
|
+
readonly idempotencyKey?: string | undefined;
|
|
156
|
+
readonly payloadMediaType?: string | undefined;
|
|
157
|
+
readonly payloadSchema?: string | undefined;
|
|
158
|
+
readonly causation?: ApplicationCommandCausation | undefined;
|
|
159
|
+
/** Delay before the command is released for delivery. Default 0. */
|
|
160
|
+
readonly availableAfterMs?: number | undefined;
|
|
161
|
+
/** Per-command overrides of the mailbox defaults. */
|
|
162
|
+
readonly maxAttempts?: number | undefined;
|
|
163
|
+
readonly visibilityTimeoutMs?: number | undefined;
|
|
164
|
+
readonly commandTimeoutMs?: number | undefined;
|
|
165
|
+
};
|
|
166
|
+
/**
|
|
167
|
+
* The outcome of offering a command.
|
|
168
|
+
*
|
|
169
|
+
* `admitted` and `duplicate` both carry the authoritative receipt — a duplicate
|
|
170
|
+
* returns the original, never a second command. `conflict` means the
|
|
171
|
+
* idempotency key is already bound to a different
|
|
172
|
+
* `(caller, target, kind, payloadDigest)`; the original command is untouched.
|
|
173
|
+
* `rejected` means the backlog is full and nothing was persisted.
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```ts
|
|
177
|
+
* import type { ApplicationCommandAdmission } from '@lostgradient/weft';
|
|
178
|
+
*
|
|
179
|
+
* declare const admission: ApplicationCommandAdmission;
|
|
180
|
+
* if (admission.status === 'admitted') console.log(admission.receipt.commandId);
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export type ApplicationCommandAdmission = {
|
|
184
|
+
readonly status: 'admitted';
|
|
185
|
+
readonly receipt: ApplicationCommandReceipt;
|
|
186
|
+
} | {
|
|
187
|
+
readonly status: 'duplicate';
|
|
188
|
+
readonly receipt: ApplicationCommandReceipt;
|
|
189
|
+
} | {
|
|
190
|
+
readonly status: 'conflict';
|
|
191
|
+
readonly receipt: ApplicationCommandReceipt;
|
|
192
|
+
readonly reason: 'idempotency-identity-mismatch';
|
|
193
|
+
} | {
|
|
194
|
+
readonly status: 'rejected';
|
|
195
|
+
readonly reason: 'backlog-full';
|
|
196
|
+
readonly capacity: MailboxCapacity;
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* An immutable point-in-time view of a command. Safe to share across observers:
|
|
200
|
+
* reading one never claims, starts, or advances work.
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* ```ts
|
|
204
|
+
* import type { ApplicationCommandReceipt } from '@lostgradient/weft';
|
|
205
|
+
*
|
|
206
|
+
* declare const receipt: ApplicationCommandReceipt;
|
|
207
|
+
* console.log(receipt.state, receipt.attempt);
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
export type ApplicationCommandReceipt = Readonly<{
|
|
211
|
+
commandId: string;
|
|
212
|
+
namespace: string;
|
|
213
|
+
resourceId: string;
|
|
214
|
+
sequence: number;
|
|
215
|
+
state: ApplicationCommandState;
|
|
216
|
+
caller: string;
|
|
217
|
+
target: string;
|
|
218
|
+
kind: string;
|
|
219
|
+
payloadDigest: string;
|
|
220
|
+
payloadForm: ApplicationCommandPayload['form'];
|
|
221
|
+
payloadMediaType?: string | undefined;
|
|
222
|
+
payloadSchema?: string | undefined;
|
|
223
|
+
idempotencyKey?: string | undefined;
|
|
224
|
+
causation?: ApplicationCommandCausation | undefined;
|
|
225
|
+
acceptedAt: number;
|
|
226
|
+
availableAt: number;
|
|
227
|
+
absoluteDeadlineAt: number;
|
|
228
|
+
attempt: number;
|
|
229
|
+
retryCount: number;
|
|
230
|
+
maxAttempts: number;
|
|
231
|
+
generation: number;
|
|
232
|
+
/**
|
|
233
|
+
* Lease liveness, present only while an attempt holds the command.
|
|
234
|
+
*
|
|
235
|
+
* The attempt token itself is deliberately NOT here. It is a fencing
|
|
236
|
+
* credential, and a receipt is readable by any observer — publishing it would
|
|
237
|
+
* let a bystander settle work it never claimed.
|
|
238
|
+
*/
|
|
239
|
+
claimedAt?: number | undefined;
|
|
240
|
+
visibilityExpiresAt?: number | undefined;
|
|
241
|
+
lastActivityAt?: number | undefined;
|
|
242
|
+
progress?: JSONValue | undefined;
|
|
243
|
+
cancellationRequestedAt?: number | undefined;
|
|
244
|
+
cancellationReason?: string | undefined;
|
|
245
|
+
terminalAt?: number | undefined;
|
|
246
|
+
outcome?: JSONValue | undefined;
|
|
247
|
+
failure?: ApplicationCommandFailure | undefined;
|
|
248
|
+
/** True when the command terminalized while an attempt still held it and never settled. */
|
|
249
|
+
cleanupPending?: boolean | undefined;
|
|
250
|
+
}>;
|
|
251
|
+
/** Bounded backlog accounting. Deliberately low-cardinality: no per-command detail.
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```ts
|
|
255
|
+
* import type { MailboxCapacity } from '@lostgradient/weft';
|
|
256
|
+
*
|
|
257
|
+
* declare const capacity: MailboxCapacity;
|
|
258
|
+
* console.log(capacity.open, capacity.remaining, capacity.limit);
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
export type MailboxCapacity = Readonly<{
|
|
262
|
+
/** Commands admitted and not yet terminal. */
|
|
263
|
+
open: number;
|
|
264
|
+
/** Configured ceiling on `open`. */
|
|
265
|
+
limit: number;
|
|
266
|
+
/** `limit - open`, floored at zero. */
|
|
267
|
+
remaining: number;
|
|
268
|
+
/** Lifetime admissions. */
|
|
269
|
+
admitted: number;
|
|
270
|
+
}>;
|
|
271
|
+
/** Bounded listing options. `limit` is clamped to 1000.
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* ```ts
|
|
275
|
+
* import type { MailboxListOptions } from '@lostgradient/weft';
|
|
276
|
+
*
|
|
277
|
+
* const options: MailboxListOptions = { limit: 50, states: ['available'] };
|
|
278
|
+
* console.log(options.limit); // 50
|
|
279
|
+
* ```
|
|
280
|
+
*/
|
|
281
|
+
export type MailboxListOptions = {
|
|
282
|
+
readonly limit?: number | undefined;
|
|
283
|
+
readonly states?: readonly ApplicationCommandState[] | undefined;
|
|
284
|
+
};
|
|
285
|
+
export type { ApplicationCommandCancellationResult, ApplicationCommandClaim, ApplicationCommandClaimedPayload, ApplicationCommandCleanupResult, ApplicationCommandRenewalResult, ApplicationCommandSettleResult, MailboxClaimResult, MailboxMaintenanceReport, MailboxWaitOptions, } from './mailbox-claims.ts';
|
|
286
|
+
/** Internal helper alias: the decoded record plus the exact bytes it was read as. */
|
|
287
|
+
export type LoadedCommandRecord = {
|
|
288
|
+
readonly record: ApplicationCommandRecord;
|
|
289
|
+
readonly bytes: Uint8Array;
|
|
290
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delivery for the application command mailbox (WFT-84): leasing the FIFO head
|
|
3
|
+
* to one attempt and handing that attempt a digest-verified payload.
|
|
4
|
+
*
|
|
5
|
+
* Strict FIFO is the ordering contract. A claim only ever considers the
|
|
6
|
+
* lowest-sequence entry in the delivery index, so a later command never
|
|
7
|
+
* overtakes a delayed head — `claim()` reports `held` instead of skipping
|
|
8
|
+
* ahead. That also means head-of-line blocking is real and intended: a command
|
|
9
|
+
* in retry backoff holds its resource's queue until it is due or dead-lettered.
|
|
10
|
+
*
|
|
11
|
+
* @module core/mailbox-delivery
|
|
12
|
+
*/
|
|
13
|
+
import type { ApplicationCommandClaimedPayload, MailboxClaimResult } from './mailbox-contract.ts';
|
|
14
|
+
import { type MailboxRuntime } from './mailbox-internals.ts';
|
|
15
|
+
import type { ApplicationCommandRecord } from './mailbox-types.ts';
|
|
16
|
+
/**
|
|
17
|
+
* Recompute an inline payload's digest and fail closed on a mismatch.
|
|
18
|
+
*
|
|
19
|
+
* A reference payload cannot be verified here — Weft never dereferences the
|
|
20
|
+
* locator — so the consumer receives the stored digest and `verified: false`
|
|
21
|
+
* rather than a guarantee the mailbox cannot back up.
|
|
22
|
+
*
|
|
23
|
+
* @throws {PersistedDataCorruptError} When a stored inline payload no longer
|
|
24
|
+
* matches the digest admission recorded for it.
|
|
25
|
+
*/
|
|
26
|
+
export declare function verifyClaimedPayload(runtime: MailboxRuntime, record: ApplicationCommandRecord): Promise<ApplicationCommandClaimedPayload>;
|
|
27
|
+
/**
|
|
28
|
+
* Lease the FIFO head of a mailbox to one attempt.
|
|
29
|
+
*
|
|
30
|
+
* The returned claim carries an attempt-scoped `AbortSignal` registered in this
|
|
31
|
+
* process, so a cancellation request raised here reaches the claimant
|
|
32
|
+
* immediately. A claimant in another process learns about cancellation from
|
|
33
|
+
* `renew()` instead — the signal is process-local by construction.
|
|
34
|
+
*/
|
|
35
|
+
export declare function claimNextCommand(runtime: MailboxRuntime, options?: {
|
|
36
|
+
readonly signal?: AbortSignal | undefined;
|
|
37
|
+
}): Promise<MailboxClaimResult>;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { storageConditionalBatch } from "../storage/interface.js";
|
|
2
|
+
import { computePayloadDigest } from "./application-payload-digest.js";
|
|
3
|
+
import { raceAbort } from "./application-primitive-abort.js";
|
|
4
|
+
import {
|
|
5
|
+
nextLeaseCommitSerial
|
|
6
|
+
} from "./application-primitive-attempt-registry.js";
|
|
7
|
+
import {
|
|
8
|
+
commitCommandTransition,
|
|
9
|
+
MailboxContentionError,
|
|
10
|
+
MAX_MAILBOX_TRANSITION_ATTEMPTS,
|
|
11
|
+
toApplicationCommandReceipt
|
|
12
|
+
} from "./mailbox-internals.js";
|
|
13
|
+
import { isWaitingState, loadCommand, loadDeliveryHead } from "./mailbox-storage.js";
|
|
14
|
+
import { recoverExpiredCommand } from "./mailbox-transitions-recovery.js";
|
|
15
|
+
import { claimWaitingCommand } from "./mailbox-transitions.js";
|
|
16
|
+
import { requireClockInstant, requireGeneratedIdentifier } from "./mailbox-validation.js";
|
|
17
|
+
import { PersistedDataCorruptError } from "./persisted-data-incompatible-error.js";
|
|
18
|
+
let localClaimSerial = 0;
|
|
19
|
+
export async function verifyClaimedPayload(runtime, record) {
|
|
20
|
+
if (record.payload.form === "reference")
|
|
21
|
+
return {
|
|
22
|
+
form: "reference",
|
|
23
|
+
reference: record.payload.reference,
|
|
24
|
+
digest: record.payload.digest,
|
|
25
|
+
byteLength: record.payload.byteLength,
|
|
26
|
+
verified: !1
|
|
27
|
+
};
|
|
28
|
+
const digest = await computePayloadDigest(record.payload.value);
|
|
29
|
+
if (digest !== record.payloadDigest)
|
|
30
|
+
throw new PersistedDataCorruptError(runtime.keys.command(record.commandId));
|
|
31
|
+
return { form: "inline", value: record.payload.value, digest, verified: !0 };
|
|
32
|
+
}
|
|
33
|
+
function isOrphanedEntry(runtime, head, loaded) {
|
|
34
|
+
return !isWaitingState(loaded.record) || head.key !== runtime.keys.ready(loaded.record.sequence);
|
|
35
|
+
}
|
|
36
|
+
async function discardOrphanedEntry(runtime, head, observed) {
|
|
37
|
+
return storageConditionalBatch(runtime.storage, [
|
|
38
|
+
{ key: head.key, expectedValue: head.bytes },
|
|
39
|
+
{
|
|
40
|
+
key: runtime.keys.command(head.commandId),
|
|
41
|
+
expectedValue: observed === null ? null : observed.bytes
|
|
42
|
+
}
|
|
43
|
+
], [{ type: "delete", key: head.key }]);
|
|
44
|
+
}
|
|
45
|
+
async function terminalizeExpiredHead(runtime, loaded, now) {
|
|
46
|
+
const transition = recoverExpiredCommand(loaded.record, {
|
|
47
|
+
now,
|
|
48
|
+
retryBackoffMs: runtime.policy.retryBackoffMs,
|
|
49
|
+
maxRetryBackoffMs: runtime.policy.maxRetryBackoffMs
|
|
50
|
+
});
|
|
51
|
+
if (!transition.ok)
|
|
52
|
+
return !0;
|
|
53
|
+
return commitCommandTransition(runtime, {
|
|
54
|
+
previous: loaded.record,
|
|
55
|
+
expectedBytes: loaded.bytes,
|
|
56
|
+
next: transition.next,
|
|
57
|
+
now
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
async function resolveDeliverableHead(runtime, now) {
|
|
61
|
+
const head = await loadDeliveryHead(runtime.storage, runtime.keys);
|
|
62
|
+
if (head === null)
|
|
63
|
+
return { status: "empty" };
|
|
64
|
+
const loaded = await loadCommand(runtime.storage, runtime.keys, head.commandId);
|
|
65
|
+
if (loaded === null || isOrphanedEntry(runtime, head, loaded))
|
|
66
|
+
return { status: "retry", progressed: await discardOrphanedEntry(runtime, head, loaded) };
|
|
67
|
+
if (now >= loaded.record.absoluteDeadlineAt)
|
|
68
|
+
return { status: "retry", progressed: await terminalizeExpiredHead(runtime, loaded, now) };
|
|
69
|
+
if (now < loaded.record.availableAt)
|
|
70
|
+
return {
|
|
71
|
+
status: "held",
|
|
72
|
+
availableAt: Math.min(loaded.record.availableAt, loaded.record.absoluteDeadlineAt)
|
|
73
|
+
};
|
|
74
|
+
return { status: "claimable", loaded };
|
|
75
|
+
}
|
|
76
|
+
function registerAttemptController(runtime, attemptToken, commandId) {
|
|
77
|
+
const controller = new AbortController, release = runtime.adoptAttempt(attemptToken);
|
|
78
|
+
if (release === null) {
|
|
79
|
+
controller.abort(Error("The application mailbox was disposed while this claim committed."));
|
|
80
|
+
return { controller, registration: null };
|
|
81
|
+
}
|
|
82
|
+
const registration = {
|
|
83
|
+
controller,
|
|
84
|
+
release,
|
|
85
|
+
subjectId: commandId,
|
|
86
|
+
committedSerial: null
|
|
87
|
+
};
|
|
88
|
+
runtime.attemptControllers.set(attemptToken, registration);
|
|
89
|
+
return { controller, registration };
|
|
90
|
+
}
|
|
91
|
+
function releaseOwnRegistration(runtime, attemptToken, registration, reason) {
|
|
92
|
+
if (registration === null)
|
|
93
|
+
return;
|
|
94
|
+
if (runtime.attemptControllers.get(attemptToken) === registration)
|
|
95
|
+
runtime.attemptControllers.delete(attemptToken);
|
|
96
|
+
registration.release();
|
|
97
|
+
if (!registration.controller.signal.aborted)
|
|
98
|
+
registration.controller.abort(Error(reason));
|
|
99
|
+
}
|
|
100
|
+
export async function claimNextCommand(runtime, options) {
|
|
101
|
+
let losses = 0;
|
|
102
|
+
while (losses < MAX_MAILBOX_TRANSITION_ATTEMPTS) {
|
|
103
|
+
options?.signal?.throwIfAborted();
|
|
104
|
+
const outcome = await attemptClaim(runtime, options?.signal);
|
|
105
|
+
if ("status" in outcome)
|
|
106
|
+
return outcome;
|
|
107
|
+
if (outcome.lost)
|
|
108
|
+
losses += 1;
|
|
109
|
+
}
|
|
110
|
+
throw new MailboxContentionError("claim", null);
|
|
111
|
+
}
|
|
112
|
+
async function deadLetterCommittedLease(runtime, commandId) {
|
|
113
|
+
const loaded = await loadCommand(runtime.storage, runtime.keys, commandId);
|
|
114
|
+
if (loaded === null)
|
|
115
|
+
return;
|
|
116
|
+
const now = runtime.now(), transition = recoverExpiredCommand(loaded.record, {
|
|
117
|
+
now,
|
|
118
|
+
retryBackoffMs: runtime.policy.retryBackoffMs,
|
|
119
|
+
maxRetryBackoffMs: runtime.policy.maxRetryBackoffMs
|
|
120
|
+
});
|
|
121
|
+
if (!transition.ok)
|
|
122
|
+
return;
|
|
123
|
+
await commitCommandTransition(runtime, {
|
|
124
|
+
previous: loaded.record,
|
|
125
|
+
expectedBytes: loaded.bytes,
|
|
126
|
+
next: transition.next,
|
|
127
|
+
now
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
async function attemptClaim(runtime, signal) {
|
|
131
|
+
const now = runtime.now(), head = await observeHead(runtime, now, signal);
|
|
132
|
+
if (head.status === "empty")
|
|
133
|
+
return { status: "empty" };
|
|
134
|
+
if (head.status === "held")
|
|
135
|
+
return { status: "held", availableAt: head.availableAt };
|
|
136
|
+
if (head.status === "retry")
|
|
137
|
+
return { lost: !head.progressed };
|
|
138
|
+
return await leaseHead(runtime, head.loaded, signal) ?? { lost: !0 };
|
|
139
|
+
}
|
|
140
|
+
async function observeHead(runtime, now, signal) {
|
|
141
|
+
const observed = await raceAbort(() => resolveDeliverableHead(runtime, now), signal);
|
|
142
|
+
if (observed.aborted)
|
|
143
|
+
throw observed.reason;
|
|
144
|
+
signal?.throwIfAborted();
|
|
145
|
+
return observed.value;
|
|
146
|
+
}
|
|
147
|
+
async function leaseHead(runtime, loaded, requestSignal) {
|
|
148
|
+
const payload = await verifyClaimedPayload(runtime, loaded.record), committedAt = requireClockInstant(runtime.now());
|
|
149
|
+
requestSignal?.throwIfAborted();
|
|
150
|
+
const generated = requireGeneratedIdentifier(runtime.generateId(), "attemptToken");
|
|
151
|
+
localClaimSerial += 1;
|
|
152
|
+
const attemptToken = `${loaded.record.sequence}.${loaded.record.attempt + 1}.${localClaimSerial}.${generated}`, transition = claimWaitingCommand(loaded.record, { now: committedAt, attemptToken });
|
|
153
|
+
if (!transition.ok)
|
|
154
|
+
return null;
|
|
155
|
+
const { controller, registration } = registerAttemptController(runtime, attemptToken, loaded.record.commandId);
|
|
156
|
+
let committed;
|
|
157
|
+
try {
|
|
158
|
+
committed = await commitCommandTransition(runtime, {
|
|
159
|
+
previous: loaded.record,
|
|
160
|
+
expectedBytes: loaded.bytes,
|
|
161
|
+
next: transition.next,
|
|
162
|
+
now: committedAt
|
|
163
|
+
});
|
|
164
|
+
} catch (error) {
|
|
165
|
+
releaseOwnRegistration(runtime, attemptToken, registration, "The claim commit failed.");
|
|
166
|
+
throw error;
|
|
167
|
+
}
|
|
168
|
+
if (!committed) {
|
|
169
|
+
releaseOwnRegistration(runtime, attemptToken, registration, "The claim lost its compare-and-swap.");
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
if (registration !== null)
|
|
173
|
+
registration.committedSerial = nextLeaseCommitSerial();
|
|
174
|
+
if (runtime.now() >= transition.next.absoluteDeadlineAt) {
|
|
175
|
+
releaseOwnRegistration(runtime, attemptToken, registration, "The application mailbox dead-lettered this command at its absolute deadline.");
|
|
176
|
+
await deadLetterCommittedLease(runtime, transition.next.commandId);
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
if (requestSignal?.aborted === !0 && !controller.signal.aborted)
|
|
180
|
+
controller.abort(Error("The claim request was aborted while this claim committed."));
|
|
181
|
+
return {
|
|
182
|
+
status: "claimed",
|
|
183
|
+
claim: {
|
|
184
|
+
receipt: toApplicationCommandReceipt(transition.next),
|
|
185
|
+
payload,
|
|
186
|
+
attemptToken,
|
|
187
|
+
attempt: transition.next.attempt,
|
|
188
|
+
visibilityExpiresAt: transition.next.visibilityExpiresAt,
|
|
189
|
+
absoluteDeadlineAt: transition.next.absoluteDeadlineAt,
|
|
190
|
+
signal: controller.signal
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Field-level guards for the durable application command mailbox (WFT-84).
|
|
3
|
+
*
|
|
4
|
+
* The generic checks — identities, durable JSON metadata, clock readings,
|
|
5
|
+
* generated identifiers, derived instants, wait budgets — live in
|
|
6
|
+
* `application-primitive-guards.ts` and are bound here to the mailbox's own
|
|
7
|
+
* validation error class, so a mailbox caller always sees
|
|
8
|
+
* `ApplicationCommandValidationError`. What remains here is what only the
|
|
9
|
+
* mailbox validates: its backlog and listing ceilings, a claimant's rejection,
|
|
10
|
+
* and a cancellation reason.
|
|
11
|
+
*
|
|
12
|
+
* Everything here is re-exported from `mailbox-validation.ts`, so
|
|
13
|
+
* mailbox callers keep one import path.
|
|
14
|
+
*
|
|
15
|
+
* @module core/mailbox-guards
|
|
16
|
+
*/
|
|
17
|
+
import type { ApplicationCommandRejection } from './mailbox-contract.ts';
|
|
18
|
+
import type { ApplicationCommandFailure } from './mailbox-types.ts';
|
|
19
|
+
import { WeftError } from './weft-error.ts';
|
|
20
|
+
export { byteLengthOf, DEFAULT_WAIT_POLL_INTERVAL_MS, isWellFormedString, MAX_APPLICATION_IDENTITY_BYTES, MAX_DURABLE_METADATA_BYTES, MAX_TIMER_DELAY_MS, } from './application-primitive-guards.ts';
|
|
21
|
+
/** Maximum bytes in an idempotency key. */
|
|
22
|
+
export declare const MAX_APPLICATION_IDEMPOTENCY_KEY_BYTES = 256;
|
|
23
|
+
/** Maximum bytes in a content-addressed payload reference. */
|
|
24
|
+
export { MAX_APPLICATION_PAYLOAD_REFERENCE_BYTES } from './application-primitive-payload.ts';
|
|
25
|
+
/** Maximum claims allowed for one command. */
|
|
26
|
+
export declare const MAX_APPLICATION_COMMAND_ATTEMPTS = 100;
|
|
27
|
+
/** Maximum open commands a mailbox may be configured to hold. */
|
|
28
|
+
export declare const MAX_MAILBOX_BACKLOG = 1000000;
|
|
29
|
+
/** Maximum receipts one `list()` call may return. */
|
|
30
|
+
export declare const MAX_MAILBOX_LIST_LIMIT = 1000;
|
|
31
|
+
/** Maximum bytes in a caller-supplied failure message. */
|
|
32
|
+
export declare const MAX_FAILURE_MESSAGE_BYTES = 2048;
|
|
33
|
+
/** Maximum bytes in a caller-supplied cancellation reason. */
|
|
34
|
+
export declare const MAX_CANCELLATION_REASON_BYTES = 2048;
|
|
35
|
+
/**
|
|
36
|
+
* Thrown when a caller hands the mailbox something it cannot admit: a missing
|
|
37
|
+
* or oversized identity component, an unusable payload, or an out-of-range
|
|
38
|
+
* policy value.
|
|
39
|
+
*
|
|
40
|
+
* This is a caller mistake, not an expected outcome — a full backlog and an
|
|
41
|
+
* idempotency conflict are returned as discriminated results instead.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* import { ApplicationCommandValidationError } from '@lostgradient/weft';
|
|
46
|
+
*
|
|
47
|
+
* const error = new ApplicationCommandValidationError('caller must be a non-empty string.');
|
|
48
|
+
* console.log(error.code); // 'ApplicationCommandValidationError'
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare class ApplicationCommandValidationError extends WeftError<'ApplicationCommandValidationError'> {
|
|
52
|
+
constructor(message: string, options?: ErrorOptions);
|
|
53
|
+
}
|
|
54
|
+
export declare const requireIdentity: (value: unknown, field: string, maxBytes: number) => string, optionalIdentityOf: (value: unknown, field: string, maxBytes: number) => string | undefined, requirePositiveInteger: (value: unknown, field: string, maximum: number) => number, requireNonNegativeInteger: (value: unknown, field: string, maximum: number) => number, validateDurableJSONValue: (value: unknown, field: string) => import("./json.ts").JSONValue | undefined, requireGeneratedIdentifier: (value: string, field: string) => string, requireClockInstant: (now: number, source?: string) => number, requireDerivedInstant: (instant: number, field: string) => number, requireMaintenanceInstant: (now: number) => number, requireWaitBudget: (options: {
|
|
55
|
+
readonly timeoutMs?: number | undefined;
|
|
56
|
+
readonly pollIntervalMs?: number | undefined;
|
|
57
|
+
}) => {
|
|
58
|
+
readonly timeoutMs: number;
|
|
59
|
+
readonly pollIntervalMs: number;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Validate a caller-supplied failure record before it becomes terminal evidence.
|
|
63
|
+
*
|
|
64
|
+
* @throws {ApplicationCommandValidationError} When `details` is not JSON-safe.
|
|
65
|
+
*/
|
|
66
|
+
export declare function validateFailure(failure: ApplicationCommandRejection): ApplicationCommandFailure;
|
|
67
|
+
/**
|
|
68
|
+
* Validate a caller-supplied cancellation reason before it becomes part of a
|
|
69
|
+
* durable record.
|
|
70
|
+
*
|
|
71
|
+
* @throws {ApplicationCommandValidationError} When the reason is oversized or
|
|
72
|
+
* not well-formed.
|
|
73
|
+
*/
|
|
74
|
+
export declare function validateCancellationReason(reason: string | undefined): string | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* Clamp a caller-supplied listing limit into the bounded range.
|
|
77
|
+
*/
|
|
78
|
+
export declare function clampListLimit(limit: number | undefined): number;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { createApplicationGuards } from "./application-primitive-guards.js";
|
|
2
|
+
import { WeftError } from "./weft-error.js";
|
|
3
|
+
export {
|
|
4
|
+
byteLengthOf,
|
|
5
|
+
DEFAULT_WAIT_POLL_INTERVAL_MS,
|
|
6
|
+
isWellFormedString,
|
|
7
|
+
MAX_APPLICATION_IDENTITY_BYTES,
|
|
8
|
+
MAX_DURABLE_METADATA_BYTES,
|
|
9
|
+
MAX_TIMER_DELAY_MS
|
|
10
|
+
} from "./application-primitive-guards.js";
|
|
11
|
+
export const MAX_APPLICATION_IDEMPOTENCY_KEY_BYTES = 256;
|
|
12
|
+
export { MAX_APPLICATION_PAYLOAD_REFERENCE_BYTES } from "./application-primitive-payload.js";
|
|
13
|
+
export const MAX_APPLICATION_COMMAND_ATTEMPTS = 100, MAX_MAILBOX_BACKLOG = 1e6, MAX_MAILBOX_LIST_LIMIT = 1000, MAX_FAILURE_MESSAGE_BYTES = 2048, MAX_CANCELLATION_REASON_BYTES = 2048;
|
|
14
|
+
|
|
15
|
+
export class ApplicationCommandValidationError extends WeftError {
|
|
16
|
+
constructor(message, options) {
|
|
17
|
+
super("ApplicationCommandValidationError", message, options);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const guards = createApplicationGuards(ApplicationCommandValidationError);
|
|
21
|
+
export const {
|
|
22
|
+
requireIdentity,
|
|
23
|
+
optionalIdentityOf,
|
|
24
|
+
requirePositiveInteger,
|
|
25
|
+
requireNonNegativeInteger,
|
|
26
|
+
validateDurableJSONValue,
|
|
27
|
+
requireGeneratedIdentifier,
|
|
28
|
+
requireClockInstant,
|
|
29
|
+
requireDerivedInstant,
|
|
30
|
+
requireMaintenanceInstant,
|
|
31
|
+
requireWaitBudget
|
|
32
|
+
} = guards;
|
|
33
|
+
const CALLER_FAILURE_REASONS = new Set([
|
|
34
|
+
"application"
|
|
35
|
+
]);
|
|
36
|
+
export function validateFailure(failure) {
|
|
37
|
+
if (typeof failure !== "object" || failure === null)
|
|
38
|
+
throw new ApplicationCommandValidationError("failure must be an object.");
|
|
39
|
+
const reason = failure.reason;
|
|
40
|
+
if (!CALLER_FAILURE_REASONS.has(reason))
|
|
41
|
+
throw new ApplicationCommandValidationError(`failure.reason must be one of ${[...CALLER_FAILURE_REASONS].join(", ")}; attempts-exhausted, deadline-exceeded, and cancelled are assigned by the mailbox.`);
|
|
42
|
+
const details = validateDurableJSONValue(failure.details, "failure.details");
|
|
43
|
+
return {
|
|
44
|
+
reason,
|
|
45
|
+
message: optionalIdentityOf(failure.message, "failure.message", MAX_FAILURE_MESSAGE_BYTES),
|
|
46
|
+
details
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export function validateCancellationReason(reason) {
|
|
50
|
+
return optionalIdentityOf(reason, "reason", MAX_CANCELLATION_REASON_BYTES);
|
|
51
|
+
}
|
|
52
|
+
export function clampListLimit(limit) {
|
|
53
|
+
if (limit === void 0)
|
|
54
|
+
return 100;
|
|
55
|
+
if (!Number.isSafeInteger(limit) || limit < 1)
|
|
56
|
+
throw new ApplicationCommandValidationError("limit must be a positive safe integer.");
|
|
57
|
+
return Math.min(limit, MAX_MAILBOX_LIST_LIMIT);
|
|
58
|
+
}
|