@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,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded per-`(name, revision)` load-state diagnostics for dynamic
|
|
3
|
+
* workflow sources (WFT-15/16): the `idle -> loading -> ready|failed`
|
|
4
|
+
* state machine, waiter-count bookkeeping, and the `loading -> cancelled`
|
|
5
|
+
* transition. The `record*`/`begin*`/`end*` functions are pure state
|
|
6
|
+
* mutation, individually unit-testable; the `*AndDispatch` wrappers pair
|
|
7
|
+
* each with the matching `workflow-source:load-*` event, gated on the pure
|
|
8
|
+
* function's boolean return so a late, orphaned settle never re-dispatches
|
|
9
|
+
* `ready`/`failed` after the key already moved to `cancelled`, and a fresh
|
|
10
|
+
* attempt for the same key resets cleanly back to `loading` first.
|
|
11
|
+
* `source-resolution.ts` calls only the `*AndDispatch` wrappers.
|
|
12
|
+
*
|
|
13
|
+
* @module core/engine/source-diagnostics
|
|
14
|
+
*/
|
|
15
|
+
import type { WorkflowSourceKind } from '../source/index.ts';
|
|
16
|
+
import type { Engine } from './index.ts';
|
|
17
|
+
import type { EngineInternals } from './internals.ts';
|
|
18
|
+
import { type SourceLoadDiagnostics } from './source-runtime-state.ts';
|
|
19
|
+
/** Bounded diagnostics for one `(name, revision)`, or `undefined` when no load was ever attempted. */
|
|
20
|
+
export declare function readSourceLoadDiagnostics(internals: EngineInternals, name: string, revision: string): SourceLoadDiagnostics | undefined;
|
|
21
|
+
/** Record that a fresh shared load for `(name, revision)` just started. */
|
|
22
|
+
export declare function recordSourceLoadStarted(internals: EngineInternals, name: string, revision: string, kind: WorkflowSourceKind, now: number): void;
|
|
23
|
+
/**
|
|
24
|
+
* Record a successful load, UNLESS the key already moved on (a `cancelled`
|
|
25
|
+
* transition from the last waiter releasing, or a fresh attempt already
|
|
26
|
+
* reset it back to `loading` for a NEW load this settle does not belong
|
|
27
|
+
* to). Returns whether the caller should dispatch `WorkflowSourceLoadReadyEvent`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function recordSourceLoadReady(internals: EngineInternals, name: string, revision: string, now: number): boolean;
|
|
30
|
+
/** The failed-load counterpart of {@link recordSourceLoadReady}. */
|
|
31
|
+
export declare function recordSourceLoadFailed(internals: EngineInternals, name: string, revision: string, now: number, error: unknown): boolean;
|
|
32
|
+
/** Increment the outstanding-waiter count for `(name, revision)`. Call once per `resolveWorkflowSource()` call, before any await. */
|
|
33
|
+
export declare function beginSourceWaiter(internals: EngineInternals, name: string, revision: string): void;
|
|
34
|
+
/**
|
|
35
|
+
* Decrement the outstanding-waiter count for `(name, revision)`; call in
|
|
36
|
+
* every `resolveWorkflowSource()` call's own `finally`. Returns whether
|
|
37
|
+
* this was the LAST outstanding waiter releasing while the shared load is
|
|
38
|
+
* still `loading` — the caller should transition diagnostics to
|
|
39
|
+
* `cancelled` and dispatch `WorkflowSourceLoadCancelledEvent`.
|
|
40
|
+
*/
|
|
41
|
+
export declare function endSourceWaiterAndCheckCancellation(internals: EngineInternals, name: string, revision: string): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* When a new caller joins a still-in-flight shared load whose diagnostics
|
|
44
|
+
* were marked `cancelled` (the last waiter released while the shared
|
|
45
|
+
* promise was still unsettled, and a later caller then joined that SAME
|
|
46
|
+
* orphaned promise instead of starting a fresh one — single-flight never
|
|
47
|
+
* aborts the shared load itself, only per-caller waiter interest), restore
|
|
48
|
+
* the state to `loading` so the eventual settle reaches its normal
|
|
49
|
+
* `ready`/`failed` transition instead of being silently suppressed by
|
|
50
|
+
* `recordSourceLoadReady`/`recordSourceLoadFailed`'s own `state !==
|
|
51
|
+
* 'loading'` guard. Never dispatches a fresh `WorkflowSourceLoadStartedEvent`
|
|
52
|
+
* — the load itself did not restart, only diagnostics visibility into it
|
|
53
|
+
* did. A no-op for any state other than `cancelled` (in particular,
|
|
54
|
+
* `getOrCreateSharedSourceLoad`'s cache-miss branch already sets `loading`
|
|
55
|
+
* itself via {@link recordSourceLoadStartedAndDispatch} for a genuinely new
|
|
56
|
+
* load, so this never fires there).
|
|
57
|
+
*/
|
|
58
|
+
export declare function reviveOrphanedSourceLoadDiagnostics(internals: EngineInternals, name: string, revision: string): void;
|
|
59
|
+
/** Current outstanding-waiter count for `(name, revision)`. */
|
|
60
|
+
export declare function readSourceWaiterCount(internals: EngineInternals, name: string, revision: string): number;
|
|
61
|
+
/** Bundles the identity a `source-resolution.ts` call site already has in scope, so the `*AndDispatch` wrappers below take one argument instead of five. */
|
|
62
|
+
export type SourceEventContext = {
|
|
63
|
+
engine: Engine;
|
|
64
|
+
internals: EngineInternals;
|
|
65
|
+
name: string;
|
|
66
|
+
revision: string;
|
|
67
|
+
kind: WorkflowSourceKind;
|
|
68
|
+
};
|
|
69
|
+
/** {@link recordSourceLoadStarted} plus dispatching `WorkflowSourceLoadStartedEvent`. */
|
|
70
|
+
export declare function recordSourceLoadStartedAndDispatch(ctx: SourceEventContext, now: number): void;
|
|
71
|
+
/** {@link recordSourceLoadReady} plus dispatching `WorkflowSourceLoadReadyEvent` when it returns `true`. */
|
|
72
|
+
export declare function recordSourceLoadReadyAndDispatch(ctx: SourceEventContext, now: number): void;
|
|
73
|
+
/** {@link recordSourceLoadFailed} plus dispatching `WorkflowSourceLoadFailedEvent` when it returns `true`. */
|
|
74
|
+
export declare function recordSourceLoadFailedAndDispatch(ctx: SourceEventContext, now: number, error: unknown): void;
|
|
75
|
+
/** {@link endSourceWaiterAndCheckCancellation} plus dispatching `WorkflowSourceLoadCancelledEvent` when it returns `true`. */
|
|
76
|
+
export declare function endSourceWaiterAndDispatchCancellation(engine: Engine, internals: EngineInternals, name: string, revision: string): void;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import {
|
|
2
|
+
WorkflowSourceLoadCancelledEvent,
|
|
3
|
+
WorkflowSourceLoadFailedEvent,
|
|
4
|
+
WorkflowSourceLoadReadyEvent,
|
|
5
|
+
WorkflowSourceLoadStartedEvent
|
|
6
|
+
} from "../events/workflow-source-events.js";
|
|
7
|
+
import { classifyErrorAsFailureCategory } from "../failure-categories.js";
|
|
8
|
+
import {
|
|
9
|
+
decrementWaiterCount,
|
|
10
|
+
incrementWaiterCount,
|
|
11
|
+
readWaiterCount
|
|
12
|
+
} from "./source-runtime-state.js";
|
|
13
|
+
function getOrCreateDiagnosticsEntry(internals, name, revision) {
|
|
14
|
+
let byRevision = internals.sources.diagnostics.get(name);
|
|
15
|
+
if (byRevision === void 0) {
|
|
16
|
+
byRevision = new Map;
|
|
17
|
+
internals.sources.diagnostics.set(name, byRevision);
|
|
18
|
+
}
|
|
19
|
+
let entry = byRevision.get(revision);
|
|
20
|
+
if (entry === void 0) {
|
|
21
|
+
entry = {
|
|
22
|
+
state: "idle",
|
|
23
|
+
kind: "module",
|
|
24
|
+
requestedRevision: revision,
|
|
25
|
+
loadStartedAt: void 0,
|
|
26
|
+
loadDurationMs: void 0,
|
|
27
|
+
lastFailureCategory: void 0
|
|
28
|
+
};
|
|
29
|
+
byRevision.set(revision, entry);
|
|
30
|
+
}
|
|
31
|
+
return entry;
|
|
32
|
+
}
|
|
33
|
+
export function readSourceLoadDiagnostics(internals, name, revision) {
|
|
34
|
+
return internals.sources.diagnostics.get(name)?.get(revision);
|
|
35
|
+
}
|
|
36
|
+
export function recordSourceLoadStarted(internals, name, revision, kind, now) {
|
|
37
|
+
const entry = getOrCreateDiagnosticsEntry(internals, name, revision);
|
|
38
|
+
entry.state = "loading";
|
|
39
|
+
entry.kind = kind;
|
|
40
|
+
entry.loadStartedAt = now;
|
|
41
|
+
entry.loadDurationMs = void 0;
|
|
42
|
+
entry.lastFailureCategory = void 0;
|
|
43
|
+
}
|
|
44
|
+
export function recordSourceLoadReady(internals, name, revision, now) {
|
|
45
|
+
const entry = readSourceLoadDiagnostics(internals, name, revision);
|
|
46
|
+
if (entry === void 0 || entry.state !== "loading")
|
|
47
|
+
return !1;
|
|
48
|
+
entry.state = "ready";
|
|
49
|
+
entry.loadDurationMs = entry.loadStartedAt === void 0 ? void 0 : now - entry.loadStartedAt;
|
|
50
|
+
return !0;
|
|
51
|
+
}
|
|
52
|
+
export function recordSourceLoadFailed(internals, name, revision, now, error) {
|
|
53
|
+
const entry = readSourceLoadDiagnostics(internals, name, revision);
|
|
54
|
+
if (entry === void 0 || entry.state !== "loading")
|
|
55
|
+
return !1;
|
|
56
|
+
entry.state = "failed";
|
|
57
|
+
entry.loadDurationMs = entry.loadStartedAt === void 0 ? void 0 : now - entry.loadStartedAt;
|
|
58
|
+
entry.lastFailureCategory = classifyErrorAsFailureCategory(error, {
|
|
59
|
+
defaultErrorCategory: "application"
|
|
60
|
+
});
|
|
61
|
+
return !0;
|
|
62
|
+
}
|
|
63
|
+
export function beginSourceWaiter(internals, name, revision) {
|
|
64
|
+
incrementWaiterCount(internals.sources.waitersByKey, name, revision);
|
|
65
|
+
}
|
|
66
|
+
export function endSourceWaiterAndCheckCancellation(internals, name, revision) {
|
|
67
|
+
if (decrementWaiterCount(internals.sources.waitersByKey, name, revision) > 0)
|
|
68
|
+
return !1;
|
|
69
|
+
const entry = readSourceLoadDiagnostics(internals, name, revision);
|
|
70
|
+
if (entry === void 0 || entry.state !== "loading")
|
|
71
|
+
return !1;
|
|
72
|
+
entry.state = "cancelled";
|
|
73
|
+
return !0;
|
|
74
|
+
}
|
|
75
|
+
export function reviveOrphanedSourceLoadDiagnostics(internals, name, revision) {
|
|
76
|
+
const entry = readSourceLoadDiagnostics(internals, name, revision);
|
|
77
|
+
if (entry === void 0 || entry.state !== "cancelled")
|
|
78
|
+
return;
|
|
79
|
+
entry.state = "loading";
|
|
80
|
+
}
|
|
81
|
+
export function readSourceWaiterCount(internals, name, revision) {
|
|
82
|
+
return readWaiterCount(internals.sources.waitersByKey, name, revision);
|
|
83
|
+
}
|
|
84
|
+
export function recordSourceLoadStartedAndDispatch(ctx, now) {
|
|
85
|
+
recordSourceLoadStarted(ctx.internals, ctx.name, ctx.revision, ctx.kind, now);
|
|
86
|
+
ctx.engine.dispatchEvent(new WorkflowSourceLoadStartedEvent(ctx.name, ctx.revision, ctx.kind));
|
|
87
|
+
}
|
|
88
|
+
export function recordSourceLoadReadyAndDispatch(ctx, now) {
|
|
89
|
+
if (!recordSourceLoadReady(ctx.internals, ctx.name, ctx.revision, now))
|
|
90
|
+
return;
|
|
91
|
+
const loadDurationMs = readSourceLoadDiagnostics(ctx.internals, ctx.name, ctx.revision).loadDurationMs;
|
|
92
|
+
ctx.engine.dispatchEvent(new WorkflowSourceLoadReadyEvent(ctx.name, ctx.revision, ctx.kind, loadDurationMs));
|
|
93
|
+
}
|
|
94
|
+
export function recordSourceLoadFailedAndDispatch(ctx, now, error) {
|
|
95
|
+
if (!recordSourceLoadFailed(ctx.internals, ctx.name, ctx.revision, now, error))
|
|
96
|
+
return;
|
|
97
|
+
const diagnostics = readSourceLoadDiagnostics(ctx.internals, ctx.name, ctx.revision);
|
|
98
|
+
ctx.engine.dispatchEvent(new WorkflowSourceLoadFailedEvent(ctx.name, ctx.revision, ctx.kind, diagnostics.loadDurationMs ?? 0, diagnostics.lastFailureCategory));
|
|
99
|
+
}
|
|
100
|
+
export function endSourceWaiterAndDispatchCancellation(engine, internals, name, revision) {
|
|
101
|
+
if (!endSourceWaiterAndCheckCancellation(internals, name, revision))
|
|
102
|
+
return;
|
|
103
|
+
const kind = readSourceLoadDiagnostics(internals, name, revision)?.kind ?? "module";
|
|
104
|
+
engine.dispatchEvent(new WorkflowSourceLoadCancelledEvent(name, revision, kind));
|
|
105
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `registerSource()` — the synchronous entry point for a dynamic workflow
|
|
3
|
+
* source (WFT-13/14). Mirrors `engine.register()`'s own "stays synchronous,
|
|
4
|
+
* defers the real work" contract: this records a catalog candidate keyed
|
|
5
|
+
* `(name, revision)` and returns — it never invokes the source's loader and
|
|
6
|
+
* never touches storage. The loader runs only inside a later, explicit
|
|
7
|
+
* `resolveWorkflowSource()` call (`source-resolution.ts`).
|
|
8
|
+
*
|
|
9
|
+
* @module core/engine/source-registration
|
|
10
|
+
*/
|
|
11
|
+
import type { WorkflowSourceHandle } from '../source/index.ts';
|
|
12
|
+
import type { EngineInternals } from './internals.ts';
|
|
13
|
+
/**
|
|
14
|
+
* Record `source` as a lazily-resolvable candidate for
|
|
15
|
+
* `(source.descriptor.name, source.descriptor.revision)`. Synchronous and
|
|
16
|
+
* side-effect-free beyond the in-memory record: never invokes
|
|
17
|
+
* `source.load`, never reads or writes storage.
|
|
18
|
+
*
|
|
19
|
+
* Collision rules, checked in both directions against `engine.register()`'s
|
|
20
|
+
* own state so a workflow name can never be simultaneously eager and lazy:
|
|
21
|
+
*
|
|
22
|
+
* - A name already eagerly registered (`internals.registrations` — set by
|
|
23
|
+
* BOTH branches of `engine.register()`, unlike `workflowDefinitionsByName`,
|
|
24
|
+
* which only the builder-produced branch populates; checking that narrower
|
|
25
|
+
* map here would let a plain `{ name, handler }` `WorkflowDefinition`
|
|
26
|
+
* registered via `engine.register()` collide silently with a same-named
|
|
27
|
+
* `registerSource()` call) cannot also be registered as a source — throws.
|
|
28
|
+
* - Re-registering the identical `source` object reference for the same
|
|
29
|
+
* `(name, revision)` is idempotent (a no-op), mirroring `engine.register()`'s
|
|
30
|
+
* own same-reference-is-idempotent rule for eager definitions.
|
|
31
|
+
* - Registering a *different* handle under the same `(name, revision)` key
|
|
32
|
+
* throws — a revision identity, once claimed, names exactly one source.
|
|
33
|
+
* - Multiple *different* revisions of the same lazy name may coexist
|
|
34
|
+
* unregistered — this is the direct lazy analog of the catalog already
|
|
35
|
+
* supporting multiple installed revisions per name (WFT-9/10); nothing in
|
|
36
|
+
* this batch's acceptance criteria forbids it.
|
|
37
|
+
*
|
|
38
|
+
* The symmetric check — an eager `engine.register()` call for a name
|
|
39
|
+
* already claimed by a source — lives in `registration.ts`'s
|
|
40
|
+
* `commitWorkflowDefinition`.
|
|
41
|
+
*/
|
|
42
|
+
export declare function registerSource(internals: EngineInternals, source: WorkflowSourceHandle): void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { utf8ByteLength } from "../../worker/manifest/utf8.js";
|
|
2
|
+
import { MAX_CONTRACT_IDENTIFIER_BYTES } from "../contract/limits.js";
|
|
3
|
+
import { validateWorkflowOrActivityName } from "../types/name-grammar.js";
|
|
4
|
+
function assertWellFormedSourceDescriptor(source) {
|
|
5
|
+
const { kind, name, revision } = source.descriptor;
|
|
6
|
+
if (typeof kind !== "string" || kind.length === 0)
|
|
7
|
+
throw TypeError("registerSource(): source.descriptor.kind must be a non-empty string");
|
|
8
|
+
if (typeof name !== "string" || name.length === 0)
|
|
9
|
+
throw TypeError("registerSource(): source.descriptor.name must be a non-empty string");
|
|
10
|
+
if (typeof revision !== "string" || revision.length === 0)
|
|
11
|
+
throw TypeError("registerSource(): source.descriptor.revision must be a non-empty string");
|
|
12
|
+
const revisionBytes = utf8ByteLength(revision);
|
|
13
|
+
if (revisionBytes > MAX_CONTRACT_IDENTIFIER_BYTES)
|
|
14
|
+
throw TypeError(`registerSource(): source.descriptor.revision is ${revisionBytes} bytes, exceeding the maximum identifier size of ${MAX_CONTRACT_IDENTIFIER_BYTES}`);
|
|
15
|
+
}
|
|
16
|
+
export function registerSource(internals, source) {
|
|
17
|
+
if (internals.inlineStrategy === null)
|
|
18
|
+
throw Error('registerSource() is only supported in inline execution mode; a dynamically-loaded definition cannot be shipped to a Worker realm. Use workflowExecutionMode: "inline", or register this workflow eagerly with engine.register() instead.');
|
|
19
|
+
assertWellFormedSourceDescriptor(source);
|
|
20
|
+
const { name, revision } = source.descriptor;
|
|
21
|
+
validateWorkflowOrActivityName(name, "workflow");
|
|
22
|
+
Object.freeze(source.descriptor);
|
|
23
|
+
if (internals.registrations.has(name))
|
|
24
|
+
throw Error(`Cannot registerSource("${name}"): "${name}" is already registered as an eager workflow via engine.register(). A workflow name may not be both eagerly registered and a dynamic source.`);
|
|
25
|
+
let byRevision = internals.sources.byName.get(name);
|
|
26
|
+
if (byRevision === void 0) {
|
|
27
|
+
byRevision = new Map;
|
|
28
|
+
internals.sources.byName.set(name, byRevision);
|
|
29
|
+
}
|
|
30
|
+
const existing = byRevision.get(revision);
|
|
31
|
+
if (existing === void 0) {
|
|
32
|
+
byRevision.set(revision, source);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (existing === source)
|
|
36
|
+
return;
|
|
37
|
+
throw Error(`Cannot registerSource("${name}", "${revision}"): a different source handle is already registered for this exact (name, revision) key.`);
|
|
38
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `resolveWorkflowSource()` — the async, single-flight entry point that
|
|
3
|
+
* loads, validates, and installs one dynamic workflow source revision
|
|
4
|
+
* (WFT-13/14).
|
|
5
|
+
*
|
|
6
|
+
* Single-flight per `(name, revision)`: the underlying load+validate+install
|
|
7
|
+
* work is shared by every concurrent caller for the same key via
|
|
8
|
+
* `internals.sources.resolutionsInFlight`, but each caller races that shared
|
|
9
|
+
* work against its OWN per-call cancellation interest — a cancelled waiter
|
|
10
|
+
* never aborts a load another waiter still needs, and the shared load itself
|
|
11
|
+
* is never tied to any individual caller's lifetime. Disposal aborts every
|
|
12
|
+
* outstanding waiter (rejecting each pending `resolveWorkflowSource()` call)
|
|
13
|
+
* without touching the shared load, which keeps running to its own settle.
|
|
14
|
+
*
|
|
15
|
+
* @module core/engine/source-resolution
|
|
16
|
+
*/
|
|
17
|
+
import type { WorkflowRevisionRecord } from '../catalog/index.ts';
|
|
18
|
+
import type { Engine } from './index.ts';
|
|
19
|
+
/**
|
|
20
|
+
* Options accepted by {@link resolveWorkflowSource}.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { Engine } from '@lostgradient/weft';
|
|
25
|
+
* import type { ResolveWorkflowSourceOptions } from '@lostgradient/weft';
|
|
26
|
+
*
|
|
27
|
+
* declare const engine: Engine;
|
|
28
|
+
* const options: ResolveWorkflowSourceOptions = { signal: AbortSignal.timeout(5_000) };
|
|
29
|
+
* const record = await engine.resolveWorkflowSource('checkout', 'r1', options);
|
|
30
|
+
* console.log(record.manifest.revision);
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export type ResolveWorkflowSourceOptions = {
|
|
34
|
+
/** When aborted, this caller's own `resolveWorkflowSource()` call rejects; a load already in flight for other callers is unaffected. */
|
|
35
|
+
signal?: AbortSignal;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Load, validate, and install one dynamic workflow source revision
|
|
39
|
+
* previously recorded via `engine.registerSource()`. Returns the installed
|
|
40
|
+
* {@link WorkflowRevisionRecord} immediately, without invoking the loader
|
|
41
|
+
* at all, when `(name, revision)` is already durably installed — including
|
|
42
|
+
* a revision installed by a different process. When that is the case,
|
|
43
|
+
* `internals.sources.resolved` is NOT populated for this key (there
|
|
44
|
+
* is no locally-loaded `WorkflowDefinition` to stash — only the durable
|
|
45
|
+
* manifest was ever read) even though the catalog itself considers the
|
|
46
|
+
* revision installed; a caller reading `internals.sources.resolved` must
|
|
47
|
+
* account for that gap rather than assuming every installed revision has a
|
|
48
|
+
* live definition available in this process — see
|
|
49
|
+
* {@link resolveWorkflowSourceForExecution} for the internal-only variant
|
|
50
|
+
* that closes exactly this gap for callers that need a local definition.
|
|
51
|
+
* This fast path still requires
|
|
52
|
+
* `registerSource()` to have been called for this exact key first (see
|
|
53
|
+
* {@link resolveCachedOrHandle}), and still validates a pinned
|
|
54
|
+
* `workflowVersion`/`contractHash` against the cached manifest — the ONLY
|
|
55
|
+
* thing it skips is re-invoking the loader and re-running
|
|
56
|
+
* {@link import('../source/index.ts').validateResolvedWorkflowSource}.
|
|
57
|
+
*
|
|
58
|
+
* Single-flight per `(name, revision)` — see the module doc for the full
|
|
59
|
+
* cancellation contract. Throws a plain `Error` when `registerSource()` was
|
|
60
|
+
* never called for this exact key (a programmer error, not untrusted-input
|
|
61
|
+
* rejection); throws {@link WorkflowSourceValidationError} when the loaded
|
|
62
|
+
* module fails validation, OR when a cached manifest contradicts a pinned
|
|
63
|
+
* `workflowVersion`/`contractHash`; throws {@link EngineDisposedError} when
|
|
64
|
+
* the engine is disposed, either already or during the call; propagates
|
|
65
|
+
* {@link import('../catalog/index.ts').WorkflowCatalogConflictError}
|
|
66
|
+
* unwrapped on a genuine content conflict with an already-installed
|
|
67
|
+
* revision.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* import { Engine, workflowSource } from '@lostgradient/weft';
|
|
72
|
+
*
|
|
73
|
+
* declare const engine: Engine;
|
|
74
|
+
* declare const loadCheckout: () => Promise<{
|
|
75
|
+
* checkout: import('@lostgradient/weft').WorkflowDefinition<unknown, unknown, 'checkout'>;
|
|
76
|
+
* }>;
|
|
77
|
+
* engine.registerSource(
|
|
78
|
+
* workflowSource(
|
|
79
|
+
* { name: 'checkout', location: './checkout.ts', exportName: 'checkout', revision: 'r1' },
|
|
80
|
+
* loadCheckout,
|
|
81
|
+
* ),
|
|
82
|
+
* );
|
|
83
|
+
* const record = await engine.resolveWorkflowSource('checkout', 'r1');
|
|
84
|
+
* console.log(record.manifest.revision);
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export declare function resolveWorkflowSource(engine: Engine, name: string, revision: string, options?: ResolveWorkflowSourceOptions): Promise<WorkflowRevisionRecord>;
|
|
88
|
+
/**
|
|
89
|
+
* Internal-only variant of {@link resolveWorkflowSource} used exclusively by
|
|
90
|
+
* `resolveExecutableRegistration()` (`dynamic-source-execution.ts`, WFT-15).
|
|
91
|
+
* Identical cancellation, disposal, and single-flight contract, with one
|
|
92
|
+
* difference: a cache hit whose local resolved-definition cache
|
|
93
|
+
* (`internals.sources.resolved`) is still empty for this exact key falls
|
|
94
|
+
* through to a real load instead of returning the cached manifest —
|
|
95
|
+
* closing the cross-process-restart gap {@link resolveWorkflowSource}'s own
|
|
96
|
+
* doc calls out. `catalog.install()` is idempotent on byte-identical
|
|
97
|
+
* content, so re-installing an already-installed manifest never throws.
|
|
98
|
+
* Not exported from the package root — reached only via
|
|
99
|
+
* `resolveExecutableRegistration`.
|
|
100
|
+
*/
|
|
101
|
+
export declare function resolveWorkflowSourceForExecution(engine: Engine, name: string, revision: string, options?: ResolveWorkflowSourceOptions): Promise<WorkflowRevisionRecord>;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import {
|
|
2
|
+
checkWorkflowCompatibility,
|
|
3
|
+
DEFAULT_WORKFLOW_COMPATIBILITY_POLICY
|
|
4
|
+
} from "../contract/compatibility.js";
|
|
5
|
+
import {
|
|
6
|
+
buildExpectedManifest,
|
|
7
|
+
resolveSourceModule,
|
|
8
|
+
validateResolvedWorkflowSource,
|
|
9
|
+
WorkflowSourceValidationError
|
|
10
|
+
} from "../source/index.js";
|
|
11
|
+
import { ensureWorkflowCatalogReady, isWorkflowCatalogReady } from "./catalog-readiness.js";
|
|
12
|
+
import { WorkflowSourceNotRegisteredError } from "./dynamic-source-errors.js";
|
|
13
|
+
import { EngineDisposedError } from "./errors.js";
|
|
14
|
+
import { getInternals, getWorkflowCatalog } from "./internals.js";
|
|
15
|
+
import {
|
|
16
|
+
beginSourceWaiter,
|
|
17
|
+
endSourceWaiterAndDispatchCancellation,
|
|
18
|
+
recordSourceLoadFailedAndDispatch,
|
|
19
|
+
recordSourceLoadReadyAndDispatch,
|
|
20
|
+
recordSourceLoadStartedAndDispatch,
|
|
21
|
+
reviveOrphanedSourceLoadDiagnostics
|
|
22
|
+
} from "./source-diagnostics.js";
|
|
23
|
+
function toAbortError(signal) {
|
|
24
|
+
const reason = signal.reason;
|
|
25
|
+
return reason instanceof Error ? reason : Error("resolveWorkflowSource() aborted");
|
|
26
|
+
}
|
|
27
|
+
function abortRejection(signal) {
|
|
28
|
+
return new Promise((_resolve, reject) => {
|
|
29
|
+
signal.addEventListener("abort", () => reject(toAbortError(signal)), { once: !0 });
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
async function runSharedSourceLoad(engine, internals, name, revision, handle) {
|
|
33
|
+
const resolved = await resolveSourceModule(handle.descriptor, handle);
|
|
34
|
+
if (!resolved.ok)
|
|
35
|
+
throw new WorkflowSourceValidationError(name, revision, [resolved.reason]);
|
|
36
|
+
const outcome = await validateResolvedWorkflowSource(handle.descriptor, resolved.moduleValue);
|
|
37
|
+
if (!outcome.ok)
|
|
38
|
+
throw new WorkflowSourceValidationError(name, revision, outcome.reasons);
|
|
39
|
+
if (internals.disposed)
|
|
40
|
+
throw new EngineDisposedError;
|
|
41
|
+
const installed = await getWorkflowCatalog(engine).install(outcome.manifest, outcome.definition);
|
|
42
|
+
if (!internals.disposed) {
|
|
43
|
+
let resolvedByRevision = internals.sources.resolved.get(name);
|
|
44
|
+
if (resolvedByRevision === void 0) {
|
|
45
|
+
resolvedByRevision = new Map;
|
|
46
|
+
internals.sources.resolved.set(name, resolvedByRevision);
|
|
47
|
+
}
|
|
48
|
+
resolvedByRevision.set(revision, {
|
|
49
|
+
definition: outcome.loadedDefinition,
|
|
50
|
+
activityRegistry: outcome.activityRegistry
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return { manifest: installed.manifest, installedAt: installed.installedAt };
|
|
54
|
+
}
|
|
55
|
+
function getOrCreateSharedSourceLoad(engine, internals, name, revision, handle) {
|
|
56
|
+
let byRevision = internals.sources.resolutionsInFlight.get(name);
|
|
57
|
+
if (byRevision === void 0) {
|
|
58
|
+
byRevision = new Map;
|
|
59
|
+
internals.sources.resolutionsInFlight.set(name, byRevision);
|
|
60
|
+
}
|
|
61
|
+
const existing = byRevision.get(revision);
|
|
62
|
+
if (existing !== void 0) {
|
|
63
|
+
reviveOrphanedSourceLoadDiagnostics(internals, name, revision);
|
|
64
|
+
return existing;
|
|
65
|
+
}
|
|
66
|
+
const eventContext = {
|
|
67
|
+
engine,
|
|
68
|
+
internals,
|
|
69
|
+
name,
|
|
70
|
+
revision,
|
|
71
|
+
kind: handle.descriptor.kind
|
|
72
|
+
};
|
|
73
|
+
recordSourceLoadStartedAndDispatch(eventContext, internals.options.getNow());
|
|
74
|
+
const shared = runSharedSourceLoad(engine, internals, name, revision, handle).then((record) => {
|
|
75
|
+
recordSourceLoadReadyAndDispatch(eventContext, internals.options.getNow());
|
|
76
|
+
return record;
|
|
77
|
+
}, (error) => {
|
|
78
|
+
recordSourceLoadFailedAndDispatch(eventContext, internals.options.getNow(), error);
|
|
79
|
+
throw error;
|
|
80
|
+
}).finally(() => {
|
|
81
|
+
const currentByRevision = internals.sources.resolutionsInFlight.get(name);
|
|
82
|
+
if (currentByRevision?.get(revision) !== shared)
|
|
83
|
+
return;
|
|
84
|
+
currentByRevision.delete(revision);
|
|
85
|
+
if (currentByRevision.size === 0)
|
|
86
|
+
internals.sources.resolutionsInFlight.delete(name);
|
|
87
|
+
});
|
|
88
|
+
shared.catch(() => {});
|
|
89
|
+
byRevision.set(revision, shared);
|
|
90
|
+
return shared;
|
|
91
|
+
}
|
|
92
|
+
function createWaiterAbort(options) {
|
|
93
|
+
const controller = new AbortController, forwardAbort = () => controller.abort(options?.signal?.reason);
|
|
94
|
+
if (options?.signal?.aborted)
|
|
95
|
+
forwardAbort();
|
|
96
|
+
else
|
|
97
|
+
options?.signal?.addEventListener("abort", forwardAbort, { once: !0 });
|
|
98
|
+
return { controller, detach: () => options?.signal?.removeEventListener("abort", forwardAbort) };
|
|
99
|
+
}
|
|
100
|
+
async function resolveCachedOrHandle(engine, internals, name, revision, requireLocalDefinition) {
|
|
101
|
+
const handle = internals.sources.byName.get(name)?.get(revision);
|
|
102
|
+
if (handle === void 0)
|
|
103
|
+
throw new WorkflowSourceNotRegisteredError(name, revision);
|
|
104
|
+
if (!isWorkflowCatalogReady(engine))
|
|
105
|
+
await ensureWorkflowCatalogReady(engine);
|
|
106
|
+
const existing = await getWorkflowCatalog(engine).resolveEntry(name, revision);
|
|
107
|
+
if (existing !== void 0) {
|
|
108
|
+
const expectedManifest = buildExpectedManifest(handle.descriptor, existing.manifest), verdict = checkWorkflowCompatibility(expectedManifest, existing.manifest, DEFAULT_WORKFLOW_COMPATIBILITY_POLICY);
|
|
109
|
+
if (!verdict.compatible)
|
|
110
|
+
throw new WorkflowSourceValidationError(name, revision, verdict.reasons);
|
|
111
|
+
if (requireLocalDefinition && internals.sources.resolved.get(name)?.get(revision) === void 0)
|
|
112
|
+
return { handle };
|
|
113
|
+
return { cached: existing };
|
|
114
|
+
}
|
|
115
|
+
return { handle };
|
|
116
|
+
}
|
|
117
|
+
export async function resolveWorkflowSource(engine, name, revision, options) {
|
|
118
|
+
return resolveWorkflowSourceCore(engine, name, revision, options, !1);
|
|
119
|
+
}
|
|
120
|
+
export async function resolveWorkflowSourceForExecution(engine, name, revision, options) {
|
|
121
|
+
return resolveWorkflowSourceCore(engine, name, revision, options, !0);
|
|
122
|
+
}
|
|
123
|
+
async function resolveWorkflowSourceCore(engine, name, revision, options, requireLocalDefinition) {
|
|
124
|
+
const internals = getInternals(engine), waiter = createWaiterAbort(options);
|
|
125
|
+
if (waiter.controller.signal.aborted) {
|
|
126
|
+
waiter.detach();
|
|
127
|
+
throw toAbortError(waiter.controller.signal);
|
|
128
|
+
}
|
|
129
|
+
if (internals.disposed) {
|
|
130
|
+
waiter.detach();
|
|
131
|
+
throw new EngineDisposedError;
|
|
132
|
+
}
|
|
133
|
+
internals.sources.waiterControllers.add(waiter.controller);
|
|
134
|
+
beginSourceWaiter(internals, name, revision);
|
|
135
|
+
try {
|
|
136
|
+
const cachedOrHandle = resolveCachedOrHandle(engine, internals, name, revision, requireLocalDefinition), cachedOrHandleAbort = abortRejection(waiter.controller.signal);
|
|
137
|
+
cachedOrHandleAbort.catch(() => {});
|
|
138
|
+
let outcome;
|
|
139
|
+
try {
|
|
140
|
+
outcome = await Promise.race([cachedOrHandle, cachedOrHandleAbort]);
|
|
141
|
+
} finally {
|
|
142
|
+
cachedOrHandle.catch(() => {});
|
|
143
|
+
}
|
|
144
|
+
if (outcome.cached !== void 0)
|
|
145
|
+
return outcome.cached;
|
|
146
|
+
const shared = getOrCreateSharedSourceLoad(engine, internals, name, revision, outcome.handle), waiterAbort = abortRejection(waiter.controller.signal);
|
|
147
|
+
waiterAbort.catch(() => {});
|
|
148
|
+
return await Promise.race([shared, waiterAbort]);
|
|
149
|
+
} finally {
|
|
150
|
+
waiter.detach();
|
|
151
|
+
internals.sources.waiterControllers.delete(waiter.controller);
|
|
152
|
+
endSourceWaiterAndDispatchCancellation(engine, internals, name, revision);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `EngineInternals.sources` — the single consolidated container for every
|
|
3
|
+
* piece of process-local, in-memory state the dynamic workflow-source
|
|
4
|
+
* pipeline (WFT-13/14, WFT-15/16) needs: registered candidates, in-flight
|
|
5
|
+
* single-flight loads, per-caller waiter controllers, locally-resolved
|
|
6
|
+
* definitions, and bounded per-`(name, revision)` diagnostics.
|
|
7
|
+
*
|
|
8
|
+
* WFT-13/14 originally spread this across five flat `EngineInternals`
|
|
9
|
+
* fields (`workflowSourcesByName`, `sourceResolutionsInFlight`,
|
|
10
|
+
* `sourceResolutionWaiterControllers`, `resolvedWorkflowSources`, plus the
|
|
11
|
+
* `ResolvedSource` type alias). WFT-15/16 folds them into one field —
|
|
12
|
+
* `internals.sources: WorkflowSourceRuntimeState` — both because
|
|
13
|
+
* `internals.ts` and `lifecycle/start.ts` are already at the repository's
|
|
14
|
+
* 500-line implementation-file ceiling (no headroom for four more
|
|
15
|
+
* documented fields) and because the diagnostics state this batch adds
|
|
16
|
+
* (`diagnostics`, `waitersByKey`, `lastResolvedRevisionByName`) is the same
|
|
17
|
+
* kind of per-`(name, revision)` bookkeeping the original four fields
|
|
18
|
+
* already were — one container, one owner.
|
|
19
|
+
*
|
|
20
|
+
* Every consumer reaches this state via `internals.sources.<field>` rather
|
|
21
|
+
* than a flat `internals.<field>` — see `scripts/check-engine-internals-field-access.ts`,
|
|
22
|
+
* which is updated in the same commit to the single `sources` name.
|
|
23
|
+
*
|
|
24
|
+
* @module core/engine/source-runtime-state
|
|
25
|
+
*/
|
|
26
|
+
import type { ActivityRegistry } from '../activity-registry.ts';
|
|
27
|
+
import type { WorkflowDefinition } from '../types.ts';
|
|
28
|
+
import type { FailureCategory } from '../types/identity.ts';
|
|
29
|
+
type SourceHandle = import('../source/index.ts').WorkflowSourceHandle;
|
|
30
|
+
type CatalogRevisionRecord = import('../catalog/index.ts').WorkflowRevisionRecord;
|
|
31
|
+
type WorkflowSourceKind = import('../source/index.ts').WorkflowSourceKind;
|
|
32
|
+
/** A successful `resolveWorkflowSource()`'s live, in-process definition and activity registry. */
|
|
33
|
+
export type ResolvedSource = {
|
|
34
|
+
definition: WorkflowDefinition;
|
|
35
|
+
activityRegistry: ActivityRegistry;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Load-state machine for one `(name, revision)`, backing both the
|
|
39
|
+
* `weft.catalog.diagnostics` `source` extension and the
|
|
40
|
+
* `workflow-source:load-*` events. `'idle'` is the type-level starting
|
|
41
|
+
* point before the first `resolveWorkflowSource()` call for a key, and IS
|
|
42
|
+
* observable externally: `weft.catalog.diagnostics` reports it for any
|
|
43
|
+
* `registerSource()`-registered revision that has never had a load start
|
|
44
|
+
* (see `buildSourceDiagnostics()` in `catalog-removal.ts`), and no
|
|
45
|
+
* `workflow-source:load-*` event is emitted for that state.
|
|
46
|
+
*/
|
|
47
|
+
export type SourceLoadState = 'idle' | 'loading' | 'ready' | 'failed' | 'cancelled';
|
|
48
|
+
/** Bounded, per-`(name, revision)` diagnostics — no manifest or contract content, only identity and state. */
|
|
49
|
+
export type SourceLoadDiagnostics = {
|
|
50
|
+
state: SourceLoadState;
|
|
51
|
+
kind: WorkflowSourceKind;
|
|
52
|
+
requestedRevision: string;
|
|
53
|
+
loadStartedAt: number | undefined;
|
|
54
|
+
loadDurationMs: number | undefined;
|
|
55
|
+
lastFailureCategory: FailureCategory | undefined;
|
|
56
|
+
};
|
|
57
|
+
/** The consolidated dynamic workflow-source runtime state — see the module doc. */
|
|
58
|
+
export type WorkflowSourceRuntimeState = {
|
|
59
|
+
/** `registerSource()` candidates, keyed name then revision. Registering never invokes the loader. */
|
|
60
|
+
byName: Map<string, Map<string, SourceHandle>>;
|
|
61
|
+
/** In-flight `resolveWorkflowSource` single-flight load per `(name, revision)`. */
|
|
62
|
+
resolutionsInFlight: Map<string, Map<string, Promise<CatalogRevisionRecord>>>;
|
|
63
|
+
/** Per-caller `AbortController`s from in-flight `resolveWorkflowSource()` calls; disposal aborts every waiter without touching the shared load. */
|
|
64
|
+
waiterControllers: Set<AbortController>;
|
|
65
|
+
/**
|
|
66
|
+
* Outstanding-waiter count per `(name, revision)`, keyed name then
|
|
67
|
+
* revision — a flat composite-string key is not safe here, since unlike a
|
|
68
|
+
* workflow `name`, a source `revision` is only byte-length-bounded, not
|
|
69
|
+
* grammar-restricted, so it may contain whatever separator character a
|
|
70
|
+
* flat key would pick. Incremented/decremented inside
|
|
71
|
+
* `resolveWorkflowSource`'s own try/finally. Drives the `loading` ->
|
|
72
|
+
* `cancelled` diagnostics transition: that transition fires only when
|
|
73
|
+
* the LAST outstanding waiter for a key releases while the shared load
|
|
74
|
+
* is still unsettled.
|
|
75
|
+
*/
|
|
76
|
+
waitersByKey: Map<string, Map<string, number>>;
|
|
77
|
+
/** A successful `resolveWorkflowSource()`'s live definition, keyed name then revision. */
|
|
78
|
+
resolved: Map<string, Map<string, ResolvedSource>>;
|
|
79
|
+
/** The revision `resolveExecutableRegistration()` most recently resolved for a name — used by the sync-only fallback readers (`finalizer.ts`, `constraints.ts`). */
|
|
80
|
+
lastResolvedRevisionByName: Map<string, string>;
|
|
81
|
+
/** Bounded per-`(name, revision)` load-state diagnostics, keyed name then revision. */
|
|
82
|
+
diagnostics: Map<string, Map<string, SourceLoadDiagnostics>>;
|
|
83
|
+
};
|
|
84
|
+
/** Build an empty {@link WorkflowSourceRuntimeState}. */
|
|
85
|
+
export declare function createWorkflowSourceRuntimeState(): WorkflowSourceRuntimeState;
|
|
86
|
+
/** Read the nested `name -> revision -> value` count at `(name, revision)` from {@link WorkflowSourceRuntimeState.waitersByKey}, defaulting to `0`. */
|
|
87
|
+
export declare function readWaiterCount(waitersByKey: WorkflowSourceRuntimeState['waitersByKey'], name: string, revision: string): number;
|
|
88
|
+
/** Increment the waiter count at `(name, revision)`, creating intermediate maps as needed. Returns the new count. */
|
|
89
|
+
export declare function incrementWaiterCount(waitersByKey: WorkflowSourceRuntimeState['waitersByKey'], name: string, revision: string): number;
|
|
90
|
+
/** Decrement the waiter count at `(name, revision)`, removing empty intermediate maps. Returns the new count (never negative). */
|
|
91
|
+
export declare function decrementWaiterCount(waitersByKey: WorkflowSourceRuntimeState['waitersByKey'], name: string, revision: string): number;
|
|
92
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export function createWorkflowSourceRuntimeState() {
|
|
2
|
+
return {
|
|
3
|
+
byName: new Map,
|
|
4
|
+
resolutionsInFlight: new Map,
|
|
5
|
+
waiterControllers: new Set,
|
|
6
|
+
waitersByKey: new Map,
|
|
7
|
+
resolved: new Map,
|
|
8
|
+
lastResolvedRevisionByName: new Map,
|
|
9
|
+
diagnostics: new Map
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export function readWaiterCount(waitersByKey, name, revision) {
|
|
13
|
+
return waitersByKey.get(name)?.get(revision) ?? 0;
|
|
14
|
+
}
|
|
15
|
+
export function incrementWaiterCount(waitersByKey, name, revision) {
|
|
16
|
+
let byRevision = waitersByKey.get(name);
|
|
17
|
+
if (byRevision === void 0) {
|
|
18
|
+
byRevision = new Map;
|
|
19
|
+
waitersByKey.set(name, byRevision);
|
|
20
|
+
}
|
|
21
|
+
const next = (byRevision.get(revision) ?? 0) + 1;
|
|
22
|
+
byRevision.set(revision, next);
|
|
23
|
+
return next;
|
|
24
|
+
}
|
|
25
|
+
export function decrementWaiterCount(waitersByKey, name, revision) {
|
|
26
|
+
const byRevision = waitersByKey.get(name), current = byRevision?.get(revision) ?? 0, next = Math.max(0, current - 1);
|
|
27
|
+
if (byRevision === void 0)
|
|
28
|
+
return next;
|
|
29
|
+
if (next === 0) {
|
|
30
|
+
byRevision.delete(revision);
|
|
31
|
+
if (byRevision.size === 0)
|
|
32
|
+
waitersByKey.delete(name);
|
|
33
|
+
} else
|
|
34
|
+
byRevision.set(revision, next);
|
|
35
|
+
return next;
|
|
36
|
+
}
|