@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,158 @@
|
|
|
1
|
+
import {
|
|
2
|
+
raceAbort,
|
|
3
|
+
raceAbortWithin,
|
|
4
|
+
WaitBudgetElapsedError
|
|
5
|
+
} from "./application-primitive-abort.js";
|
|
6
|
+
import { delayUnlessAborted } from "./application-primitive-timing.js";
|
|
7
|
+
import { requireWaitBudget } from "./outbox-guards.js";
|
|
8
|
+
import { runOutboxMaintenance } from "./outbox-maintenance.js";
|
|
9
|
+
import { deliverNext, requireAdapter } from "./outbox-runner.js";
|
|
10
|
+
import { loadOutboxHeader } from "./outbox-storage.js";
|
|
11
|
+
function count(counters, receipt) {
|
|
12
|
+
switch (receipt.state) {
|
|
13
|
+
case "acknowledged":
|
|
14
|
+
counters.acknowledged += 1;
|
|
15
|
+
return !0;
|
|
16
|
+
case "rejected":
|
|
17
|
+
counters.rejected += 1;
|
|
18
|
+
return !0;
|
|
19
|
+
case "retry-scheduled":
|
|
20
|
+
counters.retryScheduled += 1;
|
|
21
|
+
return !1;
|
|
22
|
+
case "dead-lettered":
|
|
23
|
+
counters.deadLettered += 1;
|
|
24
|
+
return !0;
|
|
25
|
+
case "cancelled":
|
|
26
|
+
counters.cancelled += 1;
|
|
27
|
+
return !0;
|
|
28
|
+
case "unknown-outcome":
|
|
29
|
+
counters.unknown += 1;
|
|
30
|
+
return !0;
|
|
31
|
+
default:
|
|
32
|
+
return !1;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export async function drainOutbox(runtime, options) {
|
|
36
|
+
requireAdapter(runtime);
|
|
37
|
+
const { timeoutMs, pollIntervalMs } = requireWaitBudget(options), deadline = runtime.now() + timeoutMs, counters = {
|
|
38
|
+
acknowledged: 0,
|
|
39
|
+
rejected: 0,
|
|
40
|
+
retryScheduled: 0,
|
|
41
|
+
deadLettered: 0,
|
|
42
|
+
cancelled: 0,
|
|
43
|
+
unknown: 0
|
|
44
|
+
}, stop = drainStopSignal(options.signal, timeoutMs);
|
|
45
|
+
let drained = !1;
|
|
46
|
+
try {
|
|
47
|
+
let lastKnownPending = await readOpenCount(runtime, stop.signal);
|
|
48
|
+
lastKnownPending = subtract(lastKnownPending, await maintainOutbox(runtime, counters, stop.signal));
|
|
49
|
+
while (drainActive(runtime, stop.signal) && !budgetSpent(timeoutMs, deadline, runtime.now())) {
|
|
50
|
+
const result = await deliverUnlessStopped(runtime, stop.signal);
|
|
51
|
+
if (result === null)
|
|
52
|
+
break;
|
|
53
|
+
if (result.status === "settled") {
|
|
54
|
+
lastKnownPending = absorbDelivery(counters, result, lastKnownPending);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const round = await pauseBeforeNextRound(runtime, result, {
|
|
58
|
+
counters,
|
|
59
|
+
deadline,
|
|
60
|
+
pending: lastKnownPending,
|
|
61
|
+
pollIntervalMs,
|
|
62
|
+
stop: stop.signal
|
|
63
|
+
});
|
|
64
|
+
lastKnownPending = round.pending;
|
|
65
|
+
drained = round.status === "drained";
|
|
66
|
+
if (round.status !== "again")
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
const pending = runtime.disposal.aborted ? lastKnownPending : await readOpenCount(runtime, stop.signal) ?? lastKnownPending;
|
|
70
|
+
return Object.freeze({ ...counters, pending, drained });
|
|
71
|
+
} finally {
|
|
72
|
+
stop.release();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function drainStopSignal(callerSignal, timeoutMs) {
|
|
76
|
+
const controller = new AbortController, onCallerAbort = () => {
|
|
77
|
+
controller.abort(callerSignal?.reason);
|
|
78
|
+
};
|
|
79
|
+
if (callerSignal?.aborted === !0)
|
|
80
|
+
onCallerAbort();
|
|
81
|
+
else
|
|
82
|
+
callerSignal?.addEventListener("abort", onCallerAbort, { once: !0 });
|
|
83
|
+
const timer = timeoutMs > 0 ? setTimeout(() => {
|
|
84
|
+
controller.abort(new WaitBudgetElapsedError);
|
|
85
|
+
}, timeoutMs) : null;
|
|
86
|
+
timer?.unref?.();
|
|
87
|
+
return {
|
|
88
|
+
signal: controller.signal,
|
|
89
|
+
release: () => {
|
|
90
|
+
callerSignal?.removeEventListener("abort", onCallerAbort);
|
|
91
|
+
if (timer !== null)
|
|
92
|
+
clearTimeout(timer);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
async function deliverUnlessStopped(runtime, stop) {
|
|
97
|
+
const delivery = deliverNext(runtime, { signal: stop }), raced = await raceAbort(() => delivery, stop);
|
|
98
|
+
if (raced.aborted) {
|
|
99
|
+
delivery.catch(() => {
|
|
100
|
+
return;
|
|
101
|
+
});
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
return raced.value;
|
|
105
|
+
}
|
|
106
|
+
function absorbDelivery(counters, result, pending) {
|
|
107
|
+
if (!result.committed)
|
|
108
|
+
return pending;
|
|
109
|
+
return count(counters, result.receipt) ? subtract(pending, 1) : pending;
|
|
110
|
+
}
|
|
111
|
+
function subtract(pending, closed) {
|
|
112
|
+
return pending === null ? null : Math.max(0, pending - (closed ?? 0));
|
|
113
|
+
}
|
|
114
|
+
function drainActive(runtime, stop) {
|
|
115
|
+
return !runtime.disposal.aborted && !stop.aborted;
|
|
116
|
+
}
|
|
117
|
+
function budgetSpent(timeoutMs, deadline, now) {
|
|
118
|
+
return timeoutMs > 0 && now >= deadline;
|
|
119
|
+
}
|
|
120
|
+
async function readOpenCount(runtime, stop) {
|
|
121
|
+
const raced = await raceAbortWithin(() => loadOutboxHeader(runtime.storage, runtime.keys, runtime.policy.namespace, runtime.policy.ownerId), null, stop);
|
|
122
|
+
return raced.aborted ? null : raced.value.record.openCount;
|
|
123
|
+
}
|
|
124
|
+
async function maintainOutbox(runtime, counters, stop) {
|
|
125
|
+
const pass = runOutboxMaintenance(runtime, runtime.now(), stop), raced = await raceAbort(() => pass, stop);
|
|
126
|
+
if (raced.aborted) {
|
|
127
|
+
pass.catch(() => {
|
|
128
|
+
return;
|
|
129
|
+
});
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
const report = raced.value;
|
|
133
|
+
counters.unknown += report.parked;
|
|
134
|
+
counters.deadLettered += report.deadLettered;
|
|
135
|
+
counters.retryScheduled += report.rescheduled;
|
|
136
|
+
return report.parked + report.deadLettered;
|
|
137
|
+
}
|
|
138
|
+
async function pauseBeforeNextRound(runtime, result, context) {
|
|
139
|
+
if (!drainActive(runtime, context.stop))
|
|
140
|
+
return { status: "stop", pending: context.pending };
|
|
141
|
+
const closed = await maintainOutbox(runtime, context.counters, context.stop), cached = subtract(context.pending, closed);
|
|
142
|
+
if (closed === null || runtime.disposal.aborted)
|
|
143
|
+
return { status: "stop", pending: cached };
|
|
144
|
+
const pending = await readOpenCount(runtime, context.stop);
|
|
145
|
+
if (pending === null)
|
|
146
|
+
return { status: "stop", pending: cached };
|
|
147
|
+
if (pending === 0)
|
|
148
|
+
return { status: "drained", pending };
|
|
149
|
+
const remaining = context.deadline - runtime.now();
|
|
150
|
+
if (remaining <= 0)
|
|
151
|
+
return { status: "stop", pending };
|
|
152
|
+
const wait = nextWait(result, remaining, context.pollIntervalMs, runtime.now());
|
|
153
|
+
return { status: await delayUnlessAborted(wait, runtime.disposal, context.stop) ? "again" : "stop", pending };
|
|
154
|
+
}
|
|
155
|
+
function nextWait(result, remaining, pollIntervalMs, now) {
|
|
156
|
+
const untilDue = result.status === "held" ? Math.max(1, result.availableAt - now) : pollIntervalMs;
|
|
157
|
+
return Math.min(remaining, pollIntervalMs, untilDue);
|
|
158
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enqueue for the application delivery outbox (WFT-85): validating an offered
|
|
3
|
+
* delivery, resolving its idempotency identity, enforcing backlog capacity,
|
|
4
|
+
* and committing the record with its indexes and fleet event.
|
|
5
|
+
*
|
|
6
|
+
* Enqueue is the one transition that also allocates: it advances the outbox
|
|
7
|
+
* header's sequence and open count in the same conditional batch as the record
|
|
8
|
+
* itself, so backlog accounting can never drift from the records it describes.
|
|
9
|
+
*
|
|
10
|
+
* @module core/outbox-enqueue
|
|
11
|
+
*/
|
|
12
|
+
import type { ApplicationDeliveryAdmission, ApplicationDeliveryInput, OutboxCapacity } from './outbox-contract.ts';
|
|
13
|
+
import { type OutboxRuntime } from './outbox-internals.ts';
|
|
14
|
+
/** Backlog accounting, shared by enqueue rejection and the public `capacity()`. */
|
|
15
|
+
export declare function capacityOf(runtime: OutboxRuntime, open: number, enqueued: number): OutboxCapacity;
|
|
16
|
+
/**
|
|
17
|
+
* Offer a delivery to the outbox.
|
|
18
|
+
*
|
|
19
|
+
* An exact retry of the same idempotency identity returns the original
|
|
20
|
+
* receipt. Reusing the key with a different destination, kind, or payload
|
|
21
|
+
* digest returns a conflict and leaves the original untouched. A full backlog
|
|
22
|
+
* is rejected before anything is persisted.
|
|
23
|
+
*/
|
|
24
|
+
export declare function enqueueDelivery(runtime: OutboxRuntime, delivery: ApplicationDeliveryInput): Promise<ApplicationDeliveryAdmission>;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { computeIdentityDigest } from "./application-payload-digest.js";
|
|
2
|
+
import { ApplicationDeliveryValidationError, requireGeneratedIdentifier } from "./outbox-guards.js";
|
|
3
|
+
import {
|
|
4
|
+
encodeApplicationDeliveryEntry,
|
|
5
|
+
encodeApplicationDeliveryIdempotencyRecord
|
|
6
|
+
} from "./outbox-index-codec.js";
|
|
7
|
+
import {
|
|
8
|
+
describeDeliveryTransition,
|
|
9
|
+
MAX_OUTBOX_TRANSITION_ATTEMPTS,
|
|
10
|
+
OutboxContentionError,
|
|
11
|
+
toApplicationDeliveryReceipt
|
|
12
|
+
} from "./outbox-internals.js";
|
|
13
|
+
import {
|
|
14
|
+
commitOutboxTransition,
|
|
15
|
+
headerOperation,
|
|
16
|
+
loadDelivery,
|
|
17
|
+
loadDeliveryIdempotencyBinding,
|
|
18
|
+
loadOutboxHeader,
|
|
19
|
+
planDeliveryTransition
|
|
20
|
+
} from "./outbox-storage.js";
|
|
21
|
+
import { createEnqueuedDeliveryRecord } from "./outbox-transitions.js";
|
|
22
|
+
import { OUTBOX_RECORD_VERSION } from "./outbox-types.js";
|
|
23
|
+
import { validateDeliveryInput } from "./outbox-validation.js";
|
|
24
|
+
import { PersistedDataCorruptError } from "./persisted-data-incompatible-error.js";
|
|
25
|
+
export function capacityOf(runtime, open, enqueued) {
|
|
26
|
+
const limit = runtime.policy.maxBacklog;
|
|
27
|
+
return Object.freeze({ open, limit, remaining: Math.max(0, limit - open), enqueued });
|
|
28
|
+
}
|
|
29
|
+
function identityOf(record) {
|
|
30
|
+
return computeIdentityDigest([record.destinationRef, record.kind, record.payloadDigest]);
|
|
31
|
+
}
|
|
32
|
+
export async function enqueueDelivery(runtime, delivery) {
|
|
33
|
+
const input = await validateDeliveryInput(delivery, runtime.policy), identityDigest = await identityOf(input);
|
|
34
|
+
for (let attempt = 1;attempt <= MAX_OUTBOX_TRANSITION_ATTEMPTS; attempt += 1) {
|
|
35
|
+
let expectedBinding = null;
|
|
36
|
+
if (input.idempotencyKey !== void 0) {
|
|
37
|
+
const resolved = await resolveIdempotency(runtime, input.idempotencyKey, identityDigest);
|
|
38
|
+
if (resolved.admission !== null)
|
|
39
|
+
return resolved.admission;
|
|
40
|
+
expectedBinding = resolved.staleBindingBytes;
|
|
41
|
+
}
|
|
42
|
+
const header = await loadOutboxHeader(runtime.storage, runtime.keys, runtime.policy.namespace, runtime.policy.ownerId);
|
|
43
|
+
if (header.record.openCount >= runtime.policy.maxBacklog)
|
|
44
|
+
return {
|
|
45
|
+
status: "rejected",
|
|
46
|
+
reason: "backlog-full",
|
|
47
|
+
capacity: capacityOf(runtime, header.record.openCount, header.record.enqueuedCount)
|
|
48
|
+
};
|
|
49
|
+
if (header.record.nextSequence >= Number.MAX_SAFE_INTEGER)
|
|
50
|
+
throw new ApplicationDeliveryValidationError("This outbox has exhausted its sequence allocator; no further deliveries can be enqueued under this namespace and owner id.");
|
|
51
|
+
const now = runtime.now(), record = createEnqueuedDeliveryRecord(input, {
|
|
52
|
+
namespace: runtime.policy.namespace,
|
|
53
|
+
ownerId: runtime.policy.ownerId,
|
|
54
|
+
deliveryId: requireGeneratedIdentifier(runtime.generateId(), "deliveryId"),
|
|
55
|
+
sequence: header.record.nextSequence,
|
|
56
|
+
now
|
|
57
|
+
}), idempotencyKey = input.idempotencyKey;
|
|
58
|
+
if (!await commitOutboxTransition(runtime.storage, runtime.events, planDeliveryTransition(runtime.keys, {
|
|
59
|
+
previous: null,
|
|
60
|
+
expectedBytes: null,
|
|
61
|
+
next: record,
|
|
62
|
+
event: describeDeliveryTransition(null, record),
|
|
63
|
+
now,
|
|
64
|
+
extraConditions: [
|
|
65
|
+
{ key: runtime.keys.header, expectedValue: header.bytes },
|
|
66
|
+
...idempotencyKey === void 0 ? [] : [{ key: runtime.keys.idempotency(idempotencyKey), expectedValue: expectedBinding }]
|
|
67
|
+
],
|
|
68
|
+
extraOperations: [
|
|
69
|
+
{
|
|
70
|
+
type: "put",
|
|
71
|
+
key: runtime.keys.bySequence(record.sequence),
|
|
72
|
+
value: encodeApplicationDeliveryEntry(record.deliveryId)
|
|
73
|
+
},
|
|
74
|
+
headerOperation(runtime.keys, {
|
|
75
|
+
...header.record,
|
|
76
|
+
nextSequence: header.record.nextSequence + 1,
|
|
77
|
+
openCount: header.record.openCount + 1,
|
|
78
|
+
enqueuedCount: header.record.enqueuedCount + 1
|
|
79
|
+
}),
|
|
80
|
+
...idempotencyKey === void 0 ? [] : [
|
|
81
|
+
{
|
|
82
|
+
type: "put",
|
|
83
|
+
key: runtime.keys.idempotency(idempotencyKey),
|
|
84
|
+
value: encodeApplicationDeliveryIdempotencyRecord({
|
|
85
|
+
recordVersion: OUTBOX_RECORD_VERSION,
|
|
86
|
+
deliveryId: record.deliveryId,
|
|
87
|
+
identityDigest
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
]
|
|
92
|
+
})))
|
|
93
|
+
continue;
|
|
94
|
+
return { status: "enqueued", receipt: toApplicationDeliveryReceipt(record) };
|
|
95
|
+
}
|
|
96
|
+
throw new OutboxContentionError("enqueue", null);
|
|
97
|
+
}
|
|
98
|
+
async function resolveIdempotency(runtime, idempotencyKey, identityDigest) {
|
|
99
|
+
const binding = await loadDeliveryIdempotencyBinding(runtime.storage, runtime.keys, idempotencyKey);
|
|
100
|
+
if (binding === null)
|
|
101
|
+
return { admission: null, staleBindingBytes: null };
|
|
102
|
+
const loaded = await loadDelivery(runtime.storage, runtime.keys, binding.record.deliveryId);
|
|
103
|
+
if (loaded === null)
|
|
104
|
+
return { admission: null, staleBindingBytes: binding.bytes };
|
|
105
|
+
const ownDigest = await identityOf(loaded.record);
|
|
106
|
+
if (loaded.record.idempotencyKey !== idempotencyKey || ownDigest !== binding.record.identityDigest)
|
|
107
|
+
throw new PersistedDataCorruptError(runtime.keys.idempotency(idempotencyKey));
|
|
108
|
+
const receipt = toApplicationDeliveryReceipt(loaded.record);
|
|
109
|
+
if (binding.record.identityDigest !== identityDigest)
|
|
110
|
+
return {
|
|
111
|
+
admission: { status: "conflict", receipt, reason: "idempotency-identity-mismatch" },
|
|
112
|
+
staleBindingBytes: null
|
|
113
|
+
};
|
|
114
|
+
return { admission: { status: "duplicate", receipt }, staleBindingBytes: null };
|
|
115
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The delivery outbox's binding of the shared application guards (WFT-85),
|
|
3
|
+
* plus the ceilings and checks only the outbox needs.
|
|
4
|
+
*
|
|
5
|
+
* Every guard throws `ApplicationDeliveryValidationError`, so a caller mistake
|
|
6
|
+
* surfaces as the outbox's own typed diagnostic rather than as the mailbox's.
|
|
7
|
+
*
|
|
8
|
+
* @module core/outbox-guards
|
|
9
|
+
*/
|
|
10
|
+
import type { ApplicationDeliveryFailure } from './outbox-types.ts';
|
|
11
|
+
import { WeftError } from './weft-error.ts';
|
|
12
|
+
export { DEFAULT_WAIT_POLL_INTERVAL_MS, MAX_APPLICATION_IDENTITY_BYTES, MAX_DURABLE_METADATA_BYTES, MAX_TIMER_DELAY_MS, } from './application-primitive-guards.ts';
|
|
13
|
+
export { MAX_APPLICATION_PAYLOAD_REFERENCE_BYTES } from './application-primitive-payload.ts';
|
|
14
|
+
/**
|
|
15
|
+
* Maximum bytes in an idempotency key or an external idempotency key. Matches
|
|
16
|
+
* the persisted-identifier ceiling the record decoder enforces, so a key
|
|
17
|
+
* admission accepts can never be one every later read rejects as corrupt.
|
|
18
|
+
*/
|
|
19
|
+
export declare const MAX_APPLICATION_DELIVERY_IDEMPOTENCY_KEY_BYTES = 256;
|
|
20
|
+
/** Maximum attempts any one delivery may be configured for. */
|
|
21
|
+
export declare const MAX_APPLICATION_DELIVERY_ATTEMPTS = 100;
|
|
22
|
+
/** Maximum open deliveries any one outbox may be configured for. */
|
|
23
|
+
export declare const MAX_OUTBOX_BACKLOG = 1000000;
|
|
24
|
+
/** Ceiling on a `list()` limit. */
|
|
25
|
+
export declare const MAX_OUTBOX_LIST_LIMIT = 1000;
|
|
26
|
+
/** Maximum bytes in a failure message. */
|
|
27
|
+
export declare const MAX_DELIVERY_FAILURE_MESSAGE_BYTES = 4096;
|
|
28
|
+
/** Maximum bytes in a cancellation reason. */
|
|
29
|
+
export declare const MAX_DELIVERY_CANCELLATION_REASON_BYTES = 1024;
|
|
30
|
+
/**
|
|
31
|
+
* Thrown when a caller supplies an invalid delivery, option, identifier, or
|
|
32
|
+
* outcome, or calls a disposed outbox.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* import { ApplicationDeliveryValidationError } from '@lostgradient/weft';
|
|
37
|
+
*
|
|
38
|
+
* const error = new ApplicationDeliveryValidationError('destinationRef must be a non-empty string.');
|
|
39
|
+
* console.log(error.code); // 'ApplicationDeliveryValidationError'
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare class ApplicationDeliveryValidationError extends WeftError<'ApplicationDeliveryValidationError'> {
|
|
43
|
+
constructor(message: string, options?: ErrorOptions);
|
|
44
|
+
}
|
|
45
|
+
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: {
|
|
46
|
+
readonly timeoutMs?: number | undefined;
|
|
47
|
+
readonly pollIntervalMs?: number | undefined;
|
|
48
|
+
}) => {
|
|
49
|
+
readonly timeoutMs: number;
|
|
50
|
+
readonly pollIntervalMs: number;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Validate the message and details a transport attached to an outcome before
|
|
54
|
+
* they become durable evidence. The reason is assigned by the outbox from the
|
|
55
|
+
* outcome's status, never taken from the caller.
|
|
56
|
+
*
|
|
57
|
+
* @throws {ApplicationDeliveryValidationError} When `details` is not JSON-safe
|
|
58
|
+
* or `message` is oversized.
|
|
59
|
+
*/
|
|
60
|
+
export declare function validateFailureEvidence(reason: ApplicationDeliveryFailure['reason'], message: unknown, details: unknown): ApplicationDeliveryFailure;
|
|
61
|
+
/**
|
|
62
|
+
* Bound a diagnostic string the outbox composes itself (an adapter's thrown
|
|
63
|
+
* error, say) to the failure-message ceiling, cutting on a character boundary
|
|
64
|
+
* and keeping the result well-formed, so a misbehaving transport cannot grow
|
|
65
|
+
* a delivery record without limit.
|
|
66
|
+
*/
|
|
67
|
+
export declare function boundFailureMessage(text: string): string;
|
|
68
|
+
/** Validate a caller-supplied cancellation reason before it becomes durable. */
|
|
69
|
+
export declare function validateCancellationReason(reason: string | undefined): string | undefined;
|
|
70
|
+
/** Clamp a caller-supplied listing limit into the bounded range. */
|
|
71
|
+
export declare function clampListLimit(limit: number | undefined): number;
|
|
72
|
+
/**
|
|
73
|
+
* Validate a caller-supplied delivery id before it reaches key construction,
|
|
74
|
+
* where an unpaired surrogate would escape as a raw `URIError`.
|
|
75
|
+
*/
|
|
76
|
+
export declare function validateDeliveryIdentifier(deliveryId: unknown): string;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {
|
|
2
|
+
byteLengthOf,
|
|
3
|
+
createApplicationGuards,
|
|
4
|
+
MAX_APPLICATION_IDENTITY_BYTES
|
|
5
|
+
} from "./application-primitive-guards.js";
|
|
6
|
+
import { WeftError } from "./weft-error.js";
|
|
7
|
+
export {
|
|
8
|
+
DEFAULT_WAIT_POLL_INTERVAL_MS,
|
|
9
|
+
MAX_APPLICATION_IDENTITY_BYTES,
|
|
10
|
+
MAX_DURABLE_METADATA_BYTES,
|
|
11
|
+
MAX_TIMER_DELAY_MS
|
|
12
|
+
} from "./application-primitive-guards.js";
|
|
13
|
+
export { MAX_APPLICATION_PAYLOAD_REFERENCE_BYTES } from "./application-primitive-payload.js";
|
|
14
|
+
export const MAX_APPLICATION_DELIVERY_IDEMPOTENCY_KEY_BYTES = MAX_APPLICATION_IDENTITY_BYTES, MAX_APPLICATION_DELIVERY_ATTEMPTS = 100, MAX_OUTBOX_BACKLOG = 1e6, MAX_OUTBOX_LIST_LIMIT = 1000, MAX_DELIVERY_FAILURE_MESSAGE_BYTES = 4096, MAX_DELIVERY_CANCELLATION_REASON_BYTES = 1024;
|
|
15
|
+
|
|
16
|
+
export class ApplicationDeliveryValidationError extends WeftError {
|
|
17
|
+
constructor(message, options) {
|
|
18
|
+
super("ApplicationDeliveryValidationError", message, options);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export const {
|
|
22
|
+
requireIdentity,
|
|
23
|
+
optionalIdentityOf,
|
|
24
|
+
requirePositiveInteger,
|
|
25
|
+
requireNonNegativeInteger,
|
|
26
|
+
validateDurableJSONValue,
|
|
27
|
+
requireGeneratedIdentifier,
|
|
28
|
+
requireClockInstant,
|
|
29
|
+
requireDerivedInstant,
|
|
30
|
+
requireMaintenanceInstant,
|
|
31
|
+
requireWaitBudget
|
|
32
|
+
} = createApplicationGuards(ApplicationDeliveryValidationError);
|
|
33
|
+
export function validateFailureEvidence(reason, message, details) {
|
|
34
|
+
return {
|
|
35
|
+
reason,
|
|
36
|
+
message: optionalIdentityOf(message, "message", MAX_DELIVERY_FAILURE_MESSAGE_BYTES),
|
|
37
|
+
details: validateDurableJSONValue(details, "details")
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export function boundFailureMessage(text) {
|
|
41
|
+
let bounded = text.toWellFormed();
|
|
42
|
+
while (byteLengthOf(bounded) > MAX_DELIVERY_FAILURE_MESSAGE_BYTES) {
|
|
43
|
+
const excess = byteLengthOf(bounded) - MAX_DELIVERY_FAILURE_MESSAGE_BYTES;
|
|
44
|
+
bounded = bounded.slice(0, -Math.max(1, Math.ceil(excess / 4))).toWellFormed();
|
|
45
|
+
}
|
|
46
|
+
return bounded;
|
|
47
|
+
}
|
|
48
|
+
export function validateCancellationReason(reason) {
|
|
49
|
+
return optionalIdentityOf(reason, "reason", MAX_DELIVERY_CANCELLATION_REASON_BYTES);
|
|
50
|
+
}
|
|
51
|
+
export function clampListLimit(limit) {
|
|
52
|
+
if (limit === void 0)
|
|
53
|
+
return 100;
|
|
54
|
+
if (!Number.isSafeInteger(limit) || limit < 1)
|
|
55
|
+
throw new ApplicationDeliveryValidationError("limit must be a positive safe integer.");
|
|
56
|
+
return Math.min(limit, MAX_OUTBOX_LIST_LIMIT);
|
|
57
|
+
}
|
|
58
|
+
export function validateDeliveryIdentifier(deliveryId) {
|
|
59
|
+
return requireIdentity(deliveryId, "deliveryId", 256);
|
|
60
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encoding and fail-closed decoding for the application outbox's index
|
|
3
|
+
* records (WFT-85): the per-outbox header, the idempotency binding, and the
|
|
4
|
+
* delivery-id entries the due, listing, and terminal indexes hold.
|
|
5
|
+
*
|
|
6
|
+
* @module core/outbox-index-codec
|
|
7
|
+
*/
|
|
8
|
+
import type { ApplicationDeliveryIdempotencyRecord, OutboxRecord } from './outbox-types.ts';
|
|
9
|
+
/**
|
|
10
|
+
* Decode the per-outbox header.
|
|
11
|
+
*
|
|
12
|
+
* @throws {PersistedDataCorruptError} When the stored bytes are malformed or
|
|
13
|
+
* name a different outbox than the key does.
|
|
14
|
+
*/
|
|
15
|
+
export declare function decodeOutboxRecord(bytes: Uint8Array, key: string): OutboxRecord;
|
|
16
|
+
/** Encode the per-outbox header. */
|
|
17
|
+
export declare function encodeOutboxRecord(record: OutboxRecord): Uint8Array;
|
|
18
|
+
/**
|
|
19
|
+
* Decode an idempotency binding.
|
|
20
|
+
*
|
|
21
|
+
* @throws {PersistedDataCorruptError} When the stored bytes are malformed.
|
|
22
|
+
*/
|
|
23
|
+
export declare function decodeApplicationDeliveryIdempotencyRecord(bytes: Uint8Array, key: string): ApplicationDeliveryIdempotencyRecord;
|
|
24
|
+
/** Encode an idempotency binding. */
|
|
25
|
+
export declare function encodeApplicationDeliveryIdempotencyRecord(record: ApplicationDeliveryIdempotencyRecord): Uint8Array;
|
|
26
|
+
/**
|
|
27
|
+
* Decode a due, listing, or terminal index entry: the delivery id it points at.
|
|
28
|
+
*
|
|
29
|
+
* @throws {PersistedDataCorruptError} When the entry is not a usable identifier.
|
|
30
|
+
*/
|
|
31
|
+
export declare function decodeApplicationDeliveryEntry(bytes: Uint8Array, key: string): string;
|
|
32
|
+
/** Encode a due, listing, or terminal index entry. */
|
|
33
|
+
export declare function encodeApplicationDeliveryEntry(deliveryId: string): Uint8Array;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { KEYS } from "../storage/interface.js";
|
|
2
|
+
import {
|
|
3
|
+
fail,
|
|
4
|
+
isRecordObject,
|
|
5
|
+
ownKey,
|
|
6
|
+
readIdentifier,
|
|
7
|
+
readInteger,
|
|
8
|
+
readString,
|
|
9
|
+
readVersion
|
|
10
|
+
} from "./application-primitive-codec.js";
|
|
11
|
+
import { decode, encode } from "./codec.js";
|
|
12
|
+
import { OUTBOX_RECORD_VERSION } from "./outbox-types.js";
|
|
13
|
+
export function decodeOutboxRecord(bytes, key) {
|
|
14
|
+
let decoded;
|
|
15
|
+
try {
|
|
16
|
+
decoded = decode(bytes);
|
|
17
|
+
} catch {
|
|
18
|
+
fail(key);
|
|
19
|
+
}
|
|
20
|
+
if (!isRecordObject(decoded))
|
|
21
|
+
fail(key);
|
|
22
|
+
readVersion(decoded, key, OUTBOX_RECORD_VERSION);
|
|
23
|
+
const namespace = readString(decoded, "namespace", key), ownerId = readString(decoded, "ownerId", key);
|
|
24
|
+
if (ownKey(() => KEYS.applicationOutbox(namespace, ownerId), key) !== key)
|
|
25
|
+
fail(key);
|
|
26
|
+
const nextSequence = readInteger(decoded, "nextSequence", key), openCount = readInteger(decoded, "openCount", key), enqueuedCount = readInteger(decoded, "enqueuedCount", key);
|
|
27
|
+
if (openCount > enqueuedCount || nextSequence < enqueuedCount)
|
|
28
|
+
fail(key);
|
|
29
|
+
return {
|
|
30
|
+
recordVersion: OUTBOX_RECORD_VERSION,
|
|
31
|
+
namespace,
|
|
32
|
+
ownerId,
|
|
33
|
+
nextSequence,
|
|
34
|
+
openCount,
|
|
35
|
+
enqueuedCount
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export function encodeOutboxRecord(record) {
|
|
39
|
+
return encode(record);
|
|
40
|
+
}
|
|
41
|
+
export function decodeApplicationDeliveryIdempotencyRecord(bytes, key) {
|
|
42
|
+
let decoded;
|
|
43
|
+
try {
|
|
44
|
+
decoded = decode(bytes);
|
|
45
|
+
} catch {
|
|
46
|
+
fail(key);
|
|
47
|
+
}
|
|
48
|
+
if (!isRecordObject(decoded))
|
|
49
|
+
fail(key);
|
|
50
|
+
readVersion(decoded, key, OUTBOX_RECORD_VERSION);
|
|
51
|
+
return {
|
|
52
|
+
recordVersion: OUTBOX_RECORD_VERSION,
|
|
53
|
+
deliveryId: readIdentifier(decoded.deliveryId, key),
|
|
54
|
+
identityDigest: readString(decoded, "identityDigest", key)
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export function encodeApplicationDeliveryIdempotencyRecord(record) {
|
|
58
|
+
return encode(record);
|
|
59
|
+
}
|
|
60
|
+
export function decodeApplicationDeliveryEntry(bytes, key) {
|
|
61
|
+
let decoded;
|
|
62
|
+
try {
|
|
63
|
+
decoded = decode(bytes);
|
|
64
|
+
} catch {
|
|
65
|
+
fail(key);
|
|
66
|
+
}
|
|
67
|
+
return readIdentifier(decoded, key);
|
|
68
|
+
}
|
|
69
|
+
export function encodeApplicationDeliveryEntry(deliveryId) {
|
|
70
|
+
return encode(deliveryId);
|
|
71
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared runtime plumbing for the application delivery outbox (WFT-85): the
|
|
3
|
+
* per-instance runtime, the contention error, receipt projection, fleet event
|
|
4
|
+
* description, process-local attempt release, and the commit that keeps the
|
|
5
|
+
* header's backlog accounting consistent with every transition.
|
|
6
|
+
*
|
|
7
|
+
* @module core/outbox-internals
|
|
8
|
+
*/
|
|
9
|
+
import type { BatchOperation, ConditionalBatchCondition, Storage } from '../storage/interface.ts';
|
|
10
|
+
import type { AttemptRegistry } from './application-primitive-attempt-registry.ts';
|
|
11
|
+
import type { ApplicationDeliveryAdapter, ApplicationDeliveryReceipt, OutboxEventSink } from './outbox-contract.ts';
|
|
12
|
+
import { type LoadedOutboxRecord, type OutboxKeys } from './outbox-storage.ts';
|
|
13
|
+
import { type ApplicationDeliveryRecord } from './outbox-types.ts';
|
|
14
|
+
import type { ResolvedOutboxPolicy } from './outbox-validation.ts';
|
|
15
|
+
import { WeftError } from './weft-error.ts';
|
|
16
|
+
/** How many times one operation re-reads and retries a lost compare-and-swap. */
|
|
17
|
+
export declare const MAX_OUTBOX_TRANSITION_ATTEMPTS = 25;
|
|
18
|
+
/** How many scan pages one maintenance pass may walk. */
|
|
19
|
+
export declare const OUTBOX_MAINTENANCE_MAX_PAGES = 200;
|
|
20
|
+
/** The registry-scope tag for the outbox, so it never shares a registry with the mailbox. */
|
|
21
|
+
export declare const OUTBOX_PRIMITIVE = "outbox";
|
|
22
|
+
/** Everything an outbox operation needs that is fixed at construction. */
|
|
23
|
+
export type OutboxRuntime = {
|
|
24
|
+
readonly storage: Storage;
|
|
25
|
+
readonly events: OutboxEventSink | undefined;
|
|
26
|
+
readonly adapter: ApplicationDeliveryAdapter | undefined;
|
|
27
|
+
readonly policy: ResolvedOutboxPolicy;
|
|
28
|
+
readonly keys: OutboxKeys;
|
|
29
|
+
readonly now: () => number;
|
|
30
|
+
readonly generateId: () => string;
|
|
31
|
+
/** The process-local disposal signal every wait and attempt races. */
|
|
32
|
+
readonly disposal: AbortSignal;
|
|
33
|
+
readonly attemptControllers: AttemptRegistry;
|
|
34
|
+
/** Record an attempt this handle now owns, or report that disposal already won. */
|
|
35
|
+
readonly adoptAttempt: (attemptToken: string) => (() => void) | null;
|
|
36
|
+
readonly readMaintenanceCursor: () => string | undefined;
|
|
37
|
+
readonly writeMaintenanceCursor: (cursor: string | undefined) => void;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Thrown when a transition keeps losing its compare-and-swap: durable
|
|
41
|
+
* contention on this outbox is real, and the caller decides whether to back
|
|
42
|
+
* off, shed load, or shard the owner.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* import { OutboxContentionError } from '@lostgradient/weft';
|
|
47
|
+
*
|
|
48
|
+
* const error = new OutboxContentionError('enqueue', null);
|
|
49
|
+
* console.log(error.code); // 'OutboxContentionError'
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare class OutboxContentionError extends WeftError<'OutboxContentionError'> {
|
|
53
|
+
/** The outbox operation that could not commit. */
|
|
54
|
+
readonly operation: string;
|
|
55
|
+
/** The delivery the operation targeted, or `null` for outbox-wide operations. */
|
|
56
|
+
readonly deliveryId: string | null;
|
|
57
|
+
constructor(operation: string, deliveryId: string | null);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Project a durable record into the immutable public receipt. The attempt
|
|
61
|
+
* token and the credential reference are never projected.
|
|
62
|
+
*/
|
|
63
|
+
export declare function toApplicationDeliveryReceipt(record: ApplicationDeliveryRecord): ApplicationDeliveryReceipt;
|
|
64
|
+
/**
|
|
65
|
+
* The durable fleet event that describes a transition. Bounded and free of
|
|
66
|
+
* secrets: no payload, no evidence, no failure details, and neither the
|
|
67
|
+
* destination nor the credential reference.
|
|
68
|
+
*/
|
|
69
|
+
export declare function describeDeliveryTransition(previous: ApplicationDeliveryRecord | null, next: ApplicationDeliveryRecord): {
|
|
70
|
+
readonly kind: string;
|
|
71
|
+
readonly payload: unknown;
|
|
72
|
+
};
|
|
73
|
+
/** Abort and forget the process-local controller for one attempt. */
|
|
74
|
+
export declare function releaseAttemptController(runtime: OutboxRuntime, attemptToken: string, reason: string, deliveryId?: string): void;
|
|
75
|
+
/**
|
|
76
|
+
* Release every attempt this process holds for one delivery that is not its
|
|
77
|
+
* current lease, fenced by the lease-commit serial the snapshot was read at.
|
|
78
|
+
*/
|
|
79
|
+
export declare function releaseAttemptsForDelivery(runtime: OutboxRuntime, deliveryId: string, reason: string, currentToken?: string, observedAt?: number): void;
|
|
80
|
+
/**
|
|
81
|
+
* Commit one delivery transition together with the index maintenance and
|
|
82
|
+
* backlog accounting it implies.
|
|
83
|
+
*
|
|
84
|
+
* Closing a delivery decrements the header's open count and an operator
|
|
85
|
+
* retry that reopens one increments it, each in the same conditional batch as
|
|
86
|
+
* the record, so `capacity()` can never drift from the records it describes.
|
|
87
|
+
* Enqueue builds its own header operation because it also allocates the
|
|
88
|
+
* sequence.
|
|
89
|
+
*/
|
|
90
|
+
export declare function commitDeliveryTransition(runtime: OutboxRuntime, options: {
|
|
91
|
+
readonly previous: ApplicationDeliveryRecord | null;
|
|
92
|
+
readonly expectedBytes: Uint8Array | null;
|
|
93
|
+
readonly next: ApplicationDeliveryRecord;
|
|
94
|
+
readonly now: number;
|
|
95
|
+
readonly extraConditions?: readonly ConditionalBatchCondition[] | undefined;
|
|
96
|
+
readonly extraOperations?: readonly BatchOperation[] | undefined;
|
|
97
|
+
/** A header the caller already read and decided on; the commit fences on these bytes. */
|
|
98
|
+
readonly header?: LoadedOutboxRecord | undefined;
|
|
99
|
+
}): Promise<boolean>;
|