@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,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Count schedules pinned to an exact `(type, revision)` (WFT-20). Wired into
|
|
3
|
+
* `catalog-removal.ts`'s `countWorkflowRevisionReferences()`, replacing the
|
|
4
|
+
* `pinnedSchedules: 0` stub WFT-12 left in place pending this batch (see
|
|
5
|
+
* that field's own doc comment: "always 0 until WFT-20").
|
|
6
|
+
*
|
|
7
|
+
* Mirrors `nonterminal-revision-count.ts`'s bounded-scan shape exactly: only
|
|
8
|
+
* top-level `schedule:{id}` records are schedule states — `schedule:{id}:*`
|
|
9
|
+
* suffix keys (timer index, run metadata) share the `schedule:` prefix but
|
|
10
|
+
* are not, the same skip `listSchedules`/`recoverOrphanedScheduleTimers`
|
|
11
|
+
* already apply.
|
|
12
|
+
*
|
|
13
|
+
* @module core/engine/pinned-schedule-revision-count
|
|
14
|
+
*/
|
|
15
|
+
import type { Storage } from '../../storage/interface.ts';
|
|
16
|
+
/**
|
|
17
|
+
* Scan `storage` for schedules whose `workflowType` and `pinnedRevision`
|
|
18
|
+
* match exactly, returning the count. Only `revisionPolicy: 'pinned'`
|
|
19
|
+
* schedules ever count — an `'active-at-fire'` schedule against the same
|
|
20
|
+
* `(type, revision)` never blocks removal, since it resolves whatever is
|
|
21
|
+
* active at each future fire regardless of what is being removed now. A
|
|
22
|
+
* `'cancelled'` pinned schedule is excluded too: it will never fire again,
|
|
23
|
+
* so it must not block removal of the revision it once pinned. A `'paused'`
|
|
24
|
+
* pinned schedule still counts — it can be resumed and fire again later.
|
|
25
|
+
*/
|
|
26
|
+
export declare function countPinnedSchedulesForRevision(storage: Storage, type: string, revision: string): Promise<number>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { decodeScheduleState } from "./validation/schedule.js";
|
|
2
|
+
export async function countPinnedSchedulesForRevision(storage, type, revision) {
|
|
3
|
+
let count = 0;
|
|
4
|
+
for await (const [key, bytes] of storage.scan("schedule:")) {
|
|
5
|
+
if (key.slice(9).includes(":"))
|
|
6
|
+
continue;
|
|
7
|
+
const state = decodeScheduleState(bytes);
|
|
8
|
+
if (!state)
|
|
9
|
+
continue;
|
|
10
|
+
if (state.workflowType !== type)
|
|
11
|
+
continue;
|
|
12
|
+
if (state.revisionPolicy !== "pinned" || state.pinnedRevision !== revision)
|
|
13
|
+
continue;
|
|
14
|
+
if (state.status === "cancelled")
|
|
15
|
+
continue;
|
|
16
|
+
count += 1;
|
|
17
|
+
}
|
|
18
|
+
return count;
|
|
19
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Revision resolution for a `revisionPolicy: 'pinned'` schedule (WFT-20):
|
|
3
|
+
* capture-time resolution (what revision would run right now, recorded on
|
|
4
|
+
* the schedule) and fire-time resolution (resolve and reserve EXACTLY the
|
|
5
|
+
* captured revision, enforcing a real, checkable commitment for an eager
|
|
6
|
+
* workflow type rather than silently degrading to active-at-fire behavior).
|
|
7
|
+
*
|
|
8
|
+
* Fire-time resolution deliberately does NOT reuse
|
|
9
|
+
* `resolveExecutableRegistrationForRevision()` unchanged for an eager type:
|
|
10
|
+
* that resolver's documented "eager ignores the pin" rule is correct for
|
|
11
|
+
* run RECOVERY (a process only ever runs the code it has loaded, so a stale
|
|
12
|
+
* pin on an eager type is harmless) but wrong for a schedule's
|
|
13
|
+
* forward-looking commitment — silently falling back to whatever is active
|
|
14
|
+
* would make a "pinned" schedule lie about what it guarantees, and would
|
|
15
|
+
* make `pinnedSchedules` reference-count accounting
|
|
16
|
+
* ({@link import('./pinned-schedule-revision-count.ts').countPinnedSchedulesForRevision})
|
|
17
|
+
* block removal of a revision nothing will ever actually run again.
|
|
18
|
+
*
|
|
19
|
+
* @module core/engine/pinned-schedule-revision
|
|
20
|
+
*/
|
|
21
|
+
import type { ConditionalBatchCondition } from '../../storage/interface.ts';
|
|
22
|
+
import type { ScheduleRevisionPolicy } from '../types.ts';
|
|
23
|
+
import { type ExecutableRegistration } from './dynamic-source-execution.ts';
|
|
24
|
+
import type { Engine } from './index.ts';
|
|
25
|
+
import type { EngineInternals } from './internals.ts';
|
|
26
|
+
/**
|
|
27
|
+
* Capture-time resolution: the revision that would run RIGHT NOW for `type`,
|
|
28
|
+
* reusing the same resolver (and revision-selection rule) a fresh
|
|
29
|
+
* `engine.start()` call would use. Called by `schedule()`/`updateSchedule()`
|
|
30
|
+
* when a caller requests `revisionPolicy: 'pinned'`, so the captured
|
|
31
|
+
* {@link import('../types/schedules.ts').ScheduleMetadata.pinnedRevision} is
|
|
32
|
+
* exactly what would have run had the schedule fired at this instant. No
|
|
33
|
+
* `inFlightStartsByRevision` reservation here — this is not launching a
|
|
34
|
+
* workflow, only recording a decision; the write that persists the pin is
|
|
35
|
+
* separately fenced against a concurrent `removeWorkflowRevision()` via
|
|
36
|
+
* `buildCatalogEntryRevisionCondition` at the `writeScheduleState` call site.
|
|
37
|
+
*/
|
|
38
|
+
export declare function resolveScheduleRevisionForPin(engine: Engine, internals: EngineInternals, type: string): Promise<string>;
|
|
39
|
+
/**
|
|
40
|
+
* `schedule()`'s create-time revision resolution — split out to keep that
|
|
41
|
+
* function under the complexity ceiling. For `revisionPolicy: 'pinned'`,
|
|
42
|
+
* captures and returns the current revision via
|
|
43
|
+
* {@link resolveScheduleRevisionForPin} (which already resolves, and for a
|
|
44
|
+
* lazy type loads, `type` internally). For `'active-at-fire'`, returns
|
|
45
|
+
* `undefined` and — for a lazy type not yet eagerly registered — resolves
|
|
46
|
+
* once here purely to trigger the loader at schedule-creation time, exactly
|
|
47
|
+
* as before this revision-policy field existed.
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveScheduleCreationRevision(internals: EngineInternals, type: string, revisionPolicy: ScheduleRevisionPolicy): Promise<string | undefined>;
|
|
50
|
+
/**
|
|
51
|
+
* Fire-time resolve-and-reserve for a pinned schedule occurrence — the
|
|
52
|
+
* pinned-revision counterpart of
|
|
53
|
+
* `catalog-removal.ts`'s `resolveAndReserveExecutableRegistration`, reusing
|
|
54
|
+
* the identical early/late `inFlightStartsByRevision` reservation shape so a
|
|
55
|
+
* concurrent `removeWorkflowRevision()` sees an in-flight reference the same
|
|
56
|
+
* way it would for an ordinary start.
|
|
57
|
+
*/
|
|
58
|
+
export declare function resolveAndReservePinnedExecutableRegistration(engine: Engine, internals: EngineInternals, type: string, revision: string): Promise<{
|
|
59
|
+
registration: ExecutableRegistration['entry'];
|
|
60
|
+
inFlightRevision: string | undefined;
|
|
61
|
+
resolvedRevision: string | undefined;
|
|
62
|
+
}>;
|
|
63
|
+
/**
|
|
64
|
+
* The `writeScheduleState` `extraConditions`/`onExtraConditionsLost` options
|
|
65
|
+
* that fence a pinned schedule's create/update write against a concurrent
|
|
66
|
+
* `removeWorkflowRevision()` landing between {@link resolveScheduleRevisionForPin}'s
|
|
67
|
+
* capture and this commit — see `storage-io.ts`'s `writeScheduleState` doc for
|
|
68
|
+
* why this is necessary (the scan-based `pinnedSchedules` reference count
|
|
69
|
+
* cannot see an uncommitted schedule write, so `removeWorkflowRevision()`'s
|
|
70
|
+
* own reference check cannot block it on its own). `undefined` (no fencing)
|
|
71
|
+
* when `pinnedRevision` is `undefined` — this write is not pinning.
|
|
72
|
+
*/
|
|
73
|
+
export declare function buildPinnedRevisionWriteOptions(internals: EngineInternals, type: string, pinnedRevision: string | undefined): Promise<{
|
|
74
|
+
extraConditions: ConditionalBatchCondition[];
|
|
75
|
+
onExtraConditionsLost: () => Error;
|
|
76
|
+
} | undefined>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { releaseInFlightStart, reserveInFlightStart } from "./catalog-removal.js";
|
|
2
|
+
import {
|
|
3
|
+
resolveExecutableRegistration,
|
|
4
|
+
resolveExecutableRegistrationForRevision
|
|
5
|
+
} from "./dynamic-source-execution.js";
|
|
6
|
+
import { buildCatalogEntryRevisionCondition } from "./lifecycle/start-commit.js";
|
|
7
|
+
import {
|
|
8
|
+
resolveCachedStartRevision,
|
|
9
|
+
resolveStartRevisionUncached
|
|
10
|
+
} from "./lifecycle/start-revision-resolution.js";
|
|
11
|
+
import { WorkflowRevisionUnavailableError } from "./revision-errors.js";
|
|
12
|
+
export async function resolveScheduleRevisionForPin(engine, internals, type) {
|
|
13
|
+
const { revision: resolvedRevision } = await resolveExecutableRegistration(engine, internals, type);
|
|
14
|
+
return resolveCachedStartRevision(internals, type, resolvedRevision) ?? await resolveStartRevisionUncached(internals, type);
|
|
15
|
+
}
|
|
16
|
+
async function resolvePinnedExecutableRegistration(engine, internals, type, revision, onRevisionChosen) {
|
|
17
|
+
const eager = internals.registrations.get(type);
|
|
18
|
+
if (eager !== void 0) {
|
|
19
|
+
if (internals.registeredCatalogRevisions.get(type) !== revision)
|
|
20
|
+
throw new WorkflowRevisionUnavailableError(type, revision, "not-registered");
|
|
21
|
+
onRevisionChosen?.(revision);
|
|
22
|
+
return { entry: eager, revision: void 0 };
|
|
23
|
+
}
|
|
24
|
+
onRevisionChosen?.(revision);
|
|
25
|
+
return resolveExecutableRegistrationForRevision(engine, internals, type, revision);
|
|
26
|
+
}
|
|
27
|
+
export async function resolveScheduleCreationRevision(internals, type, revisionPolicy) {
|
|
28
|
+
if (revisionPolicy === "pinned")
|
|
29
|
+
return resolveScheduleRevisionForPin(internals.engine, internals, type);
|
|
30
|
+
if (!internals.registrations.has(type))
|
|
31
|
+
await resolveExecutableRegistration(internals.engine, internals, type);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
export async function resolveAndReservePinnedExecutableRegistration(engine, internals, type, revision) {
|
|
35
|
+
let earlyReservation;
|
|
36
|
+
try {
|
|
37
|
+
const { entry: registration, revision: resolvedRevision } = await resolvePinnedExecutableRegistration(engine, internals, type, revision, (chosen) => {
|
|
38
|
+
earlyReservation = reserveInFlightStart(internals, type, chosen);
|
|
39
|
+
}), inFlightRevision = earlyReservation !== void 0 ? earlyReservation : reserveInFlightStart(internals, type, resolvedRevision);
|
|
40
|
+
return { registration, inFlightRevision, resolvedRevision };
|
|
41
|
+
} catch (error) {
|
|
42
|
+
releaseInFlightStart(internals, type, earlyReservation);
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export async function buildPinnedRevisionWriteOptions(internals, type, pinnedRevision) {
|
|
47
|
+
if (pinnedRevision === void 0)
|
|
48
|
+
return;
|
|
49
|
+
return {
|
|
50
|
+
extraConditions: [await buildCatalogEntryRevisionCondition(internals, type, pinnedRevision)],
|
|
51
|
+
onExtraConditionsLost: () => new WorkflowRevisionUnavailableError(type, pinnedRevision, "not-installed")
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -1,7 +1,113 @@
|
|
|
1
|
+
import { ActivityRegistry } from '../activity-registry.ts';
|
|
2
|
+
import { type ActivityDefinition, type QueryDefinition, type SignalDefinition, type UpdateDefinition, type WorkflowDefinition } from '../types.ts';
|
|
3
|
+
import type { RegistrationEntry } from './engine-internal-types.ts';
|
|
1
4
|
import type { EngineInternals } from './internals.ts';
|
|
2
5
|
export type RegistrationCallbacks = {
|
|
3
6
|
ensureRetentionSweepInterval: () => void;
|
|
4
7
|
dispatchEvent: (event: Event) => void;
|
|
5
8
|
};
|
|
9
|
+
/**
|
|
10
|
+
* Reject constraints on a workflow definition when the engine has no
|
|
11
|
+
* inline execution strategy. Exported so `dynamic-source-execution.ts`
|
|
12
|
+
* (WFT-15/16) can apply the identical guard to a dynamically-resolved
|
|
13
|
+
* definition — see that module's own call site.
|
|
14
|
+
*/
|
|
15
|
+
export declare function assertConstraintsSupported(internals: EngineInternals, name: string, registration: WorkflowDefinition): void;
|
|
16
|
+
/**
|
|
17
|
+
* Build the `RegistrationEntry` `engine.register()` would store for
|
|
18
|
+
* `registration`, without committing anything — pure normalization
|
|
19
|
+
* (base fields, optional fields, and, for a builder-produced definition,
|
|
20
|
+
* signal/update/query name-collision checks). Exported so the dynamic
|
|
21
|
+
* workflow-source validation pipeline (`core/source/validate.ts`, WFT-13/14)
|
|
22
|
+
* can normalize a loaded module's exported definition through the identical
|
|
23
|
+
* path `engine.register()` uses, rather than re-deriving a
|
|
24
|
+
* `RegistrationEntry` independently and risking the two producers drifting
|
|
25
|
+
* apart.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { workflow } from '@lostgradient/weft';
|
|
30
|
+
*
|
|
31
|
+
* const greet = workflow({ name: 'greet' }).execute(async function* (_ctx, input: string) {
|
|
32
|
+
* return `hello ${input}`;
|
|
33
|
+
* });
|
|
34
|
+
* console.log(greet.name);
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function buildRegistrationEntry(name: string, registration: WorkflowDefinition): RegistrationEntry;
|
|
38
|
+
/**
|
|
39
|
+
* Visit every RESOLVED `registerSource()`-registered type's normalized
|
|
40
|
+
* retention policy (via {@link buildRegistrationEntry}) — the dynamic-source
|
|
41
|
+
* counterpart to walking `internals.registrations.values()` directly for an
|
|
42
|
+
* eager type. Used by `bulk-operations-purge.ts` so a dynamic workflow's own
|
|
43
|
+
* (possibly shorter) retention window narrows the purge sweep's scan bound
|
|
44
|
+
* the same way an eager registration's does.
|
|
45
|
+
*/
|
|
46
|
+
export declare function forEachResolvedDynamicRetentionPolicy(internals: EngineInternals, visit: (policy: RegistrationEntry['retention']) => void): void;
|
|
47
|
+
/**
|
|
48
|
+
* True when at least one `registerSource()`-registered type has a
|
|
49
|
+
* registered candidate revision this process has NOT yet resolved — its
|
|
50
|
+
* retention policy (and everything else `buildRegistrationEntry` would
|
|
51
|
+
* derive) is genuinely unknown, so `getMinimumRetentionMs()`'s scan-bound
|
|
52
|
+
* optimization in `bulk-operations-purge.ts` cannot be trusted (WFT-19
|
|
53
|
+
* review round 1): it silently excluded exactly this class of workflow
|
|
54
|
+
* from the periodic retention sweep's scan bound, since an unresolved
|
|
55
|
+
* candidate's possibly-shorter-than-default retention window was invisible
|
|
56
|
+
* to the minimum computation. Used to fall back to an unbounded terminal
|
|
57
|
+
* scan while any such candidate remains unresolved — self-healing once
|
|
58
|
+
* `shouldPurgeWorkflowState`'s own per-run resolve installs it.
|
|
59
|
+
*/
|
|
60
|
+
export declare function hasUnresolvedDynamicSourceCandidate(internals: EngineInternals): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Structural predicate for `BuiltWorkflowDefinition` — the runtime shape
|
|
63
|
+
* `workflow({ name }).execute(...)` returns. Exported so the dynamic
|
|
64
|
+
* workflow-source validation pipeline (`core/source/validate.ts`, WFT-13/14)
|
|
65
|
+
* can reject a loaded export that is a hand-rolled `{ name, handler }`
|
|
66
|
+
* literal rather than a builder-produced definition — the same "removed
|
|
67
|
+
* bare-handler shape" rejection `engine.register()` itself applies via
|
|
68
|
+
* {@link buildRegistrationEntry}.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```ts
|
|
72
|
+
* import { workflow } from '@lostgradient/weft';
|
|
73
|
+
*
|
|
74
|
+
* const greet = workflow({ name: 'greet' }).execute(async function* (_ctx, input: string) {
|
|
75
|
+
* return `hello ${input}`;
|
|
76
|
+
* });
|
|
77
|
+
* console.log(typeof greet.activities === 'object');
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export declare function isBuilderWorkflowDefinition(value: unknown): value is WorkflowDefinition & {
|
|
81
|
+
readonly activities: Readonly<Record<string, Readonly<ActivityDefinition>>>;
|
|
82
|
+
readonly signals: Readonly<Record<string, Readonly<SignalDefinition<unknown>>>>;
|
|
83
|
+
readonly updates: Readonly<Record<string, Readonly<UpdateDefinition<unknown>>>>;
|
|
84
|
+
readonly queries: Readonly<Record<string, Readonly<QueryDefinition<unknown>>>>;
|
|
85
|
+
readonly searchAttributes: Readonly<Record<string, unknown>>;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Build a fresh per-workflow {@link ActivityRegistry} from a builder workflow's
|
|
89
|
+
* activities map. Each entry is defensively deep-cloned and then turned into a
|
|
90
|
+
* fresh `ActivityCallable` via {@link activity}, so the engine's registry holds
|
|
91
|
+
* its own callable references and the user's `BuiltWorkflowDefinition` cannot
|
|
92
|
+
* influence dispatch by post-registration mutation.
|
|
93
|
+
*
|
|
94
|
+
* Exported so the dynamic workflow-source validation pipeline
|
|
95
|
+
* (`core/source/validate.ts`, WFT-13/14) can build the same
|
|
96
|
+
* uncommitted-but-canonical per-workflow registry for a loaded module's
|
|
97
|
+
* export that `engine.register()` builds for an eagerly registered one —
|
|
98
|
+
* required so {@link import('../registry-workflow-manifest.ts').buildWorkflowManifestFromDefinition}
|
|
99
|
+
* produces byte-identical manifests for the two paths.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```ts
|
|
103
|
+
* import { workflow } from '@lostgradient/weft';
|
|
104
|
+
*
|
|
105
|
+
* const greet = workflow({ name: 'greet' }).execute(async function* (_ctx, input: string) {
|
|
106
|
+
* return `hello ${input}`;
|
|
107
|
+
* });
|
|
108
|
+
* console.log(Object.keys(greet.activities).length);
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export declare function buildPerWorkflowActivityRegistry(activities: Readonly<Record<string, Readonly<ActivityDefinition>>>): ActivityRegistry;
|
|
6
112
|
export declare function register(internals: EngineInternals, definition: unknown, callbacks: RegistrationCallbacks): void;
|
|
7
113
|
export declare function resolveWorkflowTypeTarget(internals: EngineInternals, target: string | Function, _callbacks: RegistrationCallbacks): string;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isRecord } from "../../worker/manifest/is-record.js";
|
|
1
2
|
import { ActivityRegistry } from "../activity-registry.js";
|
|
2
3
|
import { WorkflowDefinitionRegisteredEvent } from "../events.js";
|
|
3
4
|
import {
|
|
@@ -6,14 +7,15 @@ import {
|
|
|
6
7
|
} from "../types.js";
|
|
7
8
|
import { clonePlain } from "../types/clone-plain.js";
|
|
8
9
|
import { validateWorkflowOrActivityName } from "../types/name-grammar.js";
|
|
10
|
+
import { DEFAULT_WORKFLOW_VERSION } from "../versioning.js";
|
|
9
11
|
import { normalizeRetentionPolicy } from "./validation.js";
|
|
10
12
|
function copiedTags(tags) {
|
|
11
13
|
return tags === void 0 ? void 0 : [...tags];
|
|
12
14
|
}
|
|
13
15
|
function isWorkflowDefinition(value) {
|
|
14
|
-
return typeof value === "object" && value !== null && "name" in value && "handler" in value;
|
|
16
|
+
return typeof value === "object" && value !== null && "name" in value && "handler" in value && typeof value.handler === "function";
|
|
15
17
|
}
|
|
16
|
-
function assertConstraintsSupported(internals, name, registration) {
|
|
18
|
+
export function assertConstraintsSupported(internals, name, registration) {
|
|
17
19
|
if (!registration.constraints || registration.constraints.length === 0)
|
|
18
20
|
return;
|
|
19
21
|
if (internals.inlineStrategy === null)
|
|
@@ -23,7 +25,7 @@ function buildBaseRegistrationEntry(name, registration) {
|
|
|
23
25
|
const tags = copiedTags(registration.tags), normalizedRetention = normalizeRetentionPolicy(registration.retention, `registration("${name}").retention`);
|
|
24
26
|
return {
|
|
25
27
|
handler: registration.handler,
|
|
26
|
-
version: registration.version ??
|
|
28
|
+
version: registration.version ?? DEFAULT_WORKFLOW_VERSION,
|
|
27
29
|
...registration.description === void 0 ? {} : { description: registration.description },
|
|
28
30
|
...tags === void 0 ? {} : { tags },
|
|
29
31
|
...registration.inputSchema === void 0 ? {} : {
|
|
@@ -56,7 +58,7 @@ function applyOptionalRegistrationFields(entry, registration) {
|
|
|
56
58
|
if (registration.finalizer !== void 0)
|
|
57
59
|
entry.finalizer = registration.finalizer;
|
|
58
60
|
}
|
|
59
|
-
function buildRegistrationEntry(name, registration) {
|
|
61
|
+
export function buildRegistrationEntry(name, registration) {
|
|
60
62
|
const entry = buildBaseRegistrationEntry(name, registration);
|
|
61
63
|
applyOptionalRegistrationFields(entry, registration);
|
|
62
64
|
if (isBuilderWorkflowDefinition(registration)) {
|
|
@@ -66,6 +68,20 @@ function buildRegistrationEntry(name, registration) {
|
|
|
66
68
|
}
|
|
67
69
|
return entry;
|
|
68
70
|
}
|
|
71
|
+
export function forEachResolvedDynamicRetentionPolicy(internals, visit) {
|
|
72
|
+
for (const [type, revisions] of internals.sources.resolved)
|
|
73
|
+
for (const resolved of revisions.values())
|
|
74
|
+
visit(buildRegistrationEntry(type, resolved.definition).retention);
|
|
75
|
+
}
|
|
76
|
+
export function hasUnresolvedDynamicSourceCandidate(internals) {
|
|
77
|
+
for (const [type, byRevision] of internals.sources.byName) {
|
|
78
|
+
const resolvedForType = internals.sources.resolved.get(type);
|
|
79
|
+
for (const revision of byRevision.keys())
|
|
80
|
+
if (resolvedForType?.has(revision) !== !0)
|
|
81
|
+
return !0;
|
|
82
|
+
}
|
|
83
|
+
return !1;
|
|
84
|
+
}
|
|
69
85
|
function normalizeMessageDefinitions(workflowType, messageKind, definitions) {
|
|
70
86
|
const normalized = Object.create(null), sortedDefinitions = Object.values(definitions).toSorted((left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0);
|
|
71
87
|
for (const definition of sortedDefinitions) {
|
|
@@ -78,25 +94,30 @@ function normalizeMessageDefinitions(workflowType, messageKind, definitions) {
|
|
|
78
94
|
function commitWorkflowDefinition(internals, definition, callbacks) {
|
|
79
95
|
const name = definition.name;
|
|
80
96
|
validateWorkflowOrActivityName(name, "workflow");
|
|
97
|
+
if (internals.sources.byName.has(name))
|
|
98
|
+
throw Error(`Cannot register("${name}"): "${name}" is already registered as a dynamic workflow source via engine.registerSource(). A workflow name may not be both eagerly registered and a dynamic source.`);
|
|
81
99
|
assertConstraintsSupported(internals, name, definition);
|
|
82
100
|
const entry = buildRegistrationEntry(name, definition);
|
|
83
101
|
internals.registrations.set(name, entry);
|
|
84
102
|
callbacks.ensureRetentionSweepInterval();
|
|
85
103
|
internals.workflowTypesByHandler.set(definition.handler, name);
|
|
104
|
+
internals.registeredCatalogRevisions.delete(name);
|
|
105
|
+
if (!internals.pendingCatalogInstalls.includes(name))
|
|
106
|
+
internals.pendingCatalogInstalls.push(name);
|
|
86
107
|
callbacks.dispatchEvent(new WorkflowDefinitionRegisteredEvent(name));
|
|
87
108
|
}
|
|
88
109
|
function hasNonNullObjectField(value, key) {
|
|
89
110
|
if (!(key in value))
|
|
90
111
|
return !1;
|
|
91
112
|
const fieldValue = value[key];
|
|
92
|
-
return
|
|
113
|
+
return isRecord(fieldValue);
|
|
93
114
|
}
|
|
94
|
-
function isBuilderWorkflowDefinition(value) {
|
|
115
|
+
export function isBuilderWorkflowDefinition(value) {
|
|
95
116
|
if (!isWorkflowDefinition(value))
|
|
96
117
|
return !1;
|
|
97
118
|
return hasNonNullObjectField(value, "activities") && hasNonNullObjectField(value, "signals") && hasNonNullObjectField(value, "updates") && hasNonNullObjectField(value, "queries") && hasNonNullObjectField(value, "searchAttributes");
|
|
98
119
|
}
|
|
99
|
-
function buildPerWorkflowActivityRegistry(activities) {
|
|
120
|
+
export function buildPerWorkflowActivityRegistry(activities) {
|
|
100
121
|
const registry = new ActivityRegistry;
|
|
101
122
|
for (const definition of Object.values(activities)) {
|
|
102
123
|
const clonedDefinition = clonePlain(definition), callable = activity(clonedDefinition);
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { purgeInternal } from "./bulk-operations.js";
|
|
2
|
+
import { resolveLastKnownDynamicRegistration } from "./dynamic-source-execution.js";
|
|
2
3
|
export function hasConfiguredRetention(internals) {
|
|
3
4
|
if (internals.options.retention !== null)
|
|
4
5
|
return !0;
|
|
5
6
|
for (const registration of internals.registrations.values())
|
|
6
7
|
if (registration.retention !== void 0 && registration.retention !== null)
|
|
7
8
|
return !0;
|
|
9
|
+
for (const revisions of internals.sources.resolved.values())
|
|
10
|
+
for (const resolved of revisions.values())
|
|
11
|
+
if (resolved.definition.retention !== void 0 && resolved.definition.retention !== null)
|
|
12
|
+
return !0;
|
|
8
13
|
return !1;
|
|
9
14
|
}
|
|
10
15
|
export function setNextRetentionSweepAt(internals) {
|
|
@@ -49,7 +54,7 @@ export async function runRetentionSweep(internals, handleCleanupError, cleanupWa
|
|
|
49
54
|
}
|
|
50
55
|
}
|
|
51
56
|
export function resolveWorkflowTypeRetention(internals, type) {
|
|
52
|
-
const registration = internals
|
|
57
|
+
const registration = resolveLastKnownDynamicRegistration(internals, type);
|
|
53
58
|
if (registration?.retention)
|
|
54
59
|
return {
|
|
55
60
|
type,
|
|
@@ -69,7 +74,9 @@ export function resolveWorkflowTypeRetention(internals, type) {
|
|
|
69
74
|
};
|
|
70
75
|
}
|
|
71
76
|
export function getRetentionOverview(internals, resolveRetentionForType = (type) => resolveWorkflowTypeRetention(internals, type)) {
|
|
72
|
-
const workflowTypes = [
|
|
77
|
+
const workflowTypes = [
|
|
78
|
+
...new Set([...internals.registrations.keys(), ...internals.sources.byName.keys()])
|
|
79
|
+
].toSorted().map((type) => resolveRetentionForType(type));
|
|
73
80
|
return {
|
|
74
81
|
defaultRetention: internals.options.retention,
|
|
75
82
|
sweepIntervalMs: internals.options.retentionSweepIntervalMs,
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {@link WorkflowRevisionUnavailableError} (WFT-17/WFT-18) — thrown by
|
|
3
|
+
* {@link import('./dynamic-source-execution.ts').resolveExecutableRegistrationForRevision}
|
|
4
|
+
* when a resumed run's persisted, EXACT pinned `WorkflowState.revision` cannot
|
|
5
|
+
* be resolved in this process. Distinct from
|
|
6
|
+
* {@link import('./dynamic-source-errors.ts').DynamicWorkflowSourceUnavailableError},
|
|
7
|
+
* which covers a dynamic source whose ACTIVE revision is ambiguous or fails
|
|
8
|
+
* to load — this error instead covers "the run's own pin cannot be honored",
|
|
9
|
+
* which can also happen for a legacy (pre-revision-pinning) record on a
|
|
10
|
+
* dynamic source with two or more registered candidates, where there is no
|
|
11
|
+
* pin at all and the ambiguity cannot be resolved by falling back to
|
|
12
|
+
* whichever revision happens to be active (that fallback is exactly the bug
|
|
13
|
+
* this batch closes — see `documentation/guides/recovery-and-deploys.md`).
|
|
14
|
+
*
|
|
15
|
+
* @module core/engine/revision-errors
|
|
16
|
+
*/
|
|
17
|
+
import { WeftError } from '../weft-error.ts';
|
|
18
|
+
/**
|
|
19
|
+
* Thrown when a workflow run's pinned {@link import('../types/state.ts').WorkflowState.revision}
|
|
20
|
+
* cannot be resolved to an executable registration in this process:
|
|
21
|
+
*
|
|
22
|
+
* - `reason: 'not-registered'` — the run pins a specific revision (a
|
|
23
|
+
* dynamic-source candidate this process has never `registerSource()`-registered,
|
|
24
|
+
* including the case where the pin no longer matches a dynamic source's sole
|
|
25
|
+
* remaining candidate).
|
|
26
|
+
* - `reason: 'legacy-ambiguous'` — the run predates revision pinning (no
|
|
27
|
+
* `revision` was ever persisted for it) and its type is a dynamic source
|
|
28
|
+
* with two or more registered candidates, so there is no way to tell which
|
|
29
|
+
* one it actually started against.
|
|
30
|
+
* - `reason: 'not-installed'` — thrown at commit-time ADMISSION, not
|
|
31
|
+
* recovery, for either a fresh `start()` or a checkpoint-backed failed-run
|
|
32
|
+
* `retryFailedAll()` reactivation (WFT-17/WFT-18 Codex review on PR #958):
|
|
33
|
+
* the resolved (or pinned) revision's durable catalog entry was
|
|
34
|
+
* concurrently removed — `removeWorkflowRevision()` racing a `start()` on
|
|
35
|
+
* a DIFFERENT process under a lease ownership mode, or racing a
|
|
36
|
+
* `retryFailedAll()` on ANY process/mode, since a failed run contributes no
|
|
37
|
+
* `inFlightStartsByRevision` reservation of its own — between this
|
|
38
|
+
* process resolving the revision and that commit batch actually landing.
|
|
39
|
+
* Fails the one call outright — never retried inside the engine — so the
|
|
40
|
+
* caller re-issues it, which re-resolves against whatever is actually
|
|
41
|
+
* still installed.
|
|
42
|
+
*
|
|
43
|
+
* `engine.recoverAll()` classifies the affected `(type, revision)` group
|
|
44
|
+
* `unavailable`: only the runs in that group fail (with this error as their
|
|
45
|
+
* `system` failure cause, delivered via `failWorkflow()`/`onRecoveredWorkflow`,
|
|
46
|
+
* never thrown to `recoverAll()`'s own caller); sibling groups — including
|
|
47
|
+
* OTHER revisions of the same dynamic-source type — continue recovering
|
|
48
|
+
* normally. A standalone `engine.resume(workflowId)` call has no such
|
|
49
|
+
* isolation to fall back on — there is only the one run — so it throws this
|
|
50
|
+
* error directly to its caller instead.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* import { Engine, WorkflowRevisionUnavailableError } from '@lostgradient/weft';
|
|
55
|
+
*
|
|
56
|
+
* const engine = new Engine();
|
|
57
|
+
* try {
|
|
58
|
+
* await engine.resume('workflow-id');
|
|
59
|
+
* } catch (err) {
|
|
60
|
+
* if (err instanceof WorkflowRevisionUnavailableError) {
|
|
61
|
+
* console.error(err.workflowType, err.revision, err.reason);
|
|
62
|
+
* }
|
|
63
|
+
* }
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare class WorkflowRevisionUnavailableError extends WeftError<'WorkflowRevisionUnavailableError'> {
|
|
67
|
+
readonly workflowType: string;
|
|
68
|
+
readonly revision: string | undefined;
|
|
69
|
+
readonly reason: 'not-registered' | 'legacy-ambiguous' | 'not-installed';
|
|
70
|
+
constructor(workflowType: string, revision: string | undefined, reason: 'not-registered' | 'legacy-ambiguous' | 'not-installed');
|
|
71
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { WeftError } from "../weft-error.js";
|
|
2
|
+
|
|
3
|
+
export class WorkflowRevisionUnavailableError extends WeftError {
|
|
4
|
+
workflowType;
|
|
5
|
+
revision;
|
|
6
|
+
reason;
|
|
7
|
+
constructor(workflowType, revision, reason) {
|
|
8
|
+
super("WorkflowRevisionUnavailableError", reason === "legacy-ambiguous" ? `Cannot recover workflow type "${workflowType}": this run predates revision pinning and the type is a dynamic source with multiple registered revisions, so which one it started against cannot be determined.` : reason === "not-installed" ? `Cannot admit workflow type "${workflowType}": revision${revision === void 0 ? "" : ` "${revision}"`} is no longer installed in the durable catalog (removed concurrently). Retry the operation.` : `Cannot recover workflow type "${workflowType}": its pinned revision${revision === void 0 ? "" : ` "${revision}"`} is not registered in this process. Register the exact revision this run started against before retrying.`);
|
|
9
|
+
this.workflowType = workflowType;
|
|
10
|
+
this.revision = revision;
|
|
11
|
+
this.reason = reason;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pinned-vs-active-at-fire branch point for a scheduled occurrence
|
|
3
|
+
* (WFT-20), split into its own tiny module so `schedule-run.ts` — a
|
|
4
|
+
* deliberately small, purpose-built module — has one obvious call site
|
|
5
|
+
* instead of inlining the branch.
|
|
6
|
+
*
|
|
7
|
+
* @module core/engine/schedule-revision-fire
|
|
8
|
+
*/
|
|
9
|
+
import type { ScheduleState } from '../types.ts';
|
|
10
|
+
/**
|
|
11
|
+
* The revision override `startScheduledRun` should pass to
|
|
12
|
+
* `ScheduleCallbacks.startWorkflow` for this occurrence: `state.pinnedRevision`
|
|
13
|
+
* when `state.revisionPolicy === 'pinned'`, else `undefined` (an
|
|
14
|
+
* `'active-at-fire'` schedule resolves whatever revision is active at fire
|
|
15
|
+
* time, unchanged from pre-WFT-20 behavior).
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildPinnedRevisionOverride(state: ScheduleState): string | undefined;
|
|
@@ -3,6 +3,7 @@ import { encode } from "../codec.js";
|
|
|
3
3
|
import { ScheduleFiredEvent } from "../events.js";
|
|
4
4
|
import { unavailableServicesError } from "./lifecycle/recovered-services.js";
|
|
5
5
|
import { EMPTY_STORAGE_VALUE } from "./lifecycle/shared.js";
|
|
6
|
+
import { buildPinnedRevisionOverride } from "./schedule-revision-fire.js";
|
|
6
7
|
import { encodeScheduleRunMetadata } from "./schedule-run-metadata.js";
|
|
7
8
|
export async function startScheduledRun(internals, state, callbacks, options = {}) {
|
|
8
9
|
const workflowId = options.workflowId ?? crypto.randomUUID(), occurrence = options.occurrence, metadata = encodeScheduleRunMetadata(state.id, occurrence), scheduleRunOperations = [
|
|
@@ -49,7 +50,7 @@ export async function startScheduledRun(internals, state, callbacks, options = {
|
|
|
49
50
|
internals.workflowServices.set(workflowId, resolution.services);
|
|
50
51
|
}
|
|
51
52
|
internals.workflowsNeedingTerminalCleanup.add(workflowId);
|
|
52
|
-
await callbacks.startWorkflow(state.workflowType, state.input, { id: workflowId }, scheduleRunOperations);
|
|
53
|
+
await callbacks.startWorkflow(state.workflowType, state.input, { id: workflowId }, scheduleRunOperations, buildPinnedRevisionOverride(state));
|
|
53
54
|
internals.engine.dispatchEvent(new ScheduleFiredEvent(state.id, workflowId, internals.options.getNow(), occurrence));
|
|
54
55
|
if (resolution !== null && resolution.status === "unavailable") {
|
|
55
56
|
const unavailableError = unavailableServicesError(workflowId, resolution.reason);
|
|
@@ -10,9 +10,10 @@ export type RefreshedScheduleState = {
|
|
|
10
10
|
currentWorkflowState: WorkflowState | null;
|
|
11
11
|
};
|
|
12
12
|
export type ScheduleCallbacks = {
|
|
13
|
+
/** `revisionOverride` (WFT-20) is the exact revision a `revisionPolicy: 'pinned'` occurrence must resolve against; `undefined` for an `'active-at-fire'` schedule. */
|
|
13
14
|
startWorkflow: (type: string, input: unknown, options: {
|
|
14
15
|
id: string;
|
|
15
|
-
}, additionalStartOperations?: BatchOperation[]) => Promise<void>;
|
|
16
|
+
}, additionalStartOperations?: BatchOperation[], revisionOverride?: string) => Promise<void>;
|
|
16
17
|
loadWorkflowState: (workflowId: string) => Promise<WorkflowState | null | undefined>;
|
|
17
18
|
cancelWorkflow: (workflowId: string) => Promise<void>;
|
|
18
19
|
getWorkflowResult: (workflowId: string) => Promise<unknown>;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { KEYS } from "../../storage/interface.js";
|
|
2
2
|
import { decode } from "../codec.js";
|
|
3
|
-
import { WorkflowNotRegisteredError } from "./errors.js";
|
|
4
3
|
import { commitFencedEngineWrite } from "./fenced-write.js";
|
|
4
|
+
import {
|
|
5
|
+
buildPinnedRevisionWriteOptions,
|
|
6
|
+
resolveScheduleCreationRevision,
|
|
7
|
+
resolveScheduleRevisionForPin
|
|
8
|
+
} from "./pinned-schedule-revision.js";
|
|
5
9
|
import { ScheduleHandle } from "./schedule-handle.js";
|
|
6
10
|
import { resolveEffectiveScheduleFireAt } from "./schedule-jitter.js";
|
|
7
11
|
import { getNextScheduleOccurrence } from "./schedule-occurrence.js";
|
|
@@ -31,9 +35,7 @@ import {
|
|
|
31
35
|
export { startScheduledRun } from "./schedule-run.js";
|
|
32
36
|
export { handleScheduleTimer } from "./schedule-timer.js";
|
|
33
37
|
export async function schedule(internals, type, input, spec, options) {
|
|
34
|
-
|
|
35
|
-
throw new WorkflowNotRegisteredError(type);
|
|
36
|
-
const normalizedSpec = normalizeScheduleSpec(spec), normalizedOptions = normalizeScheduleOptions(options), scheduleId = normalizedOptions.id ?? crypto.randomUUID();
|
|
38
|
+
const normalizedSpec = normalizeScheduleSpec(spec), normalizedOptions = normalizeScheduleOptions(options), scheduleId = normalizedOptions.id ?? crypto.randomUUID(), revisionPolicy = normalizedOptions.revisionPolicy ?? "active-at-fire", pinnedRevision = await resolveScheduleCreationRevision(internals, type, revisionPolicy);
|
|
37
39
|
if (internals.pendingScheduleCreations.has(scheduleId))
|
|
38
40
|
throw Error(`Schedule with id "${scheduleId}" already exists`);
|
|
39
41
|
internals.pendingScheduleCreations.add(scheduleId);
|
|
@@ -52,13 +54,15 @@ export async function schedule(internals, type, input, spec, options) {
|
|
|
52
54
|
overlap: normalizedOptions.overlap,
|
|
53
55
|
backfill: normalizedOptions.backfill,
|
|
54
56
|
...normalizedOptions.jitterMs !== void 0 && { jitterMs: normalizedOptions.jitterMs },
|
|
57
|
+
revisionPolicy,
|
|
58
|
+
...pinnedRevision !== void 0 && { pinnedRevision },
|
|
55
59
|
createdAt: now,
|
|
56
60
|
updatedAt: now,
|
|
57
61
|
nextFireAt: getNextScheduleOccurrence({ ...cadenceFields, createdAt: now }, now),
|
|
58
62
|
missedFireCount: 0,
|
|
59
63
|
queuedRuns: []
|
|
60
64
|
};
|
|
61
|
-
await writeScheduleState(internals, state);
|
|
65
|
+
await writeScheduleState(internals, state, await buildPinnedRevisionWriteOptions(internals, type, pinnedRevision));
|
|
62
66
|
return new ScheduleHandle(scheduleId, internals.engine);
|
|
63
67
|
} finally {
|
|
64
68
|
internals.pendingScheduleCreations.delete(scheduleId);
|
|
@@ -152,18 +156,33 @@ export async function updateSchedule(internals, scheduleId, newSpec, options) {
|
|
|
152
156
|
const state = await requireScheduleState(internals, normalizedScheduleId), now = internals.options.getNow(), {
|
|
153
157
|
cronExpression: _droppedCron,
|
|
154
158
|
intervalMs: _droppedInterval,
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
159
|
+
pinnedRevision: _droppedPinnedRevision,
|
|
160
|
+
...stateWithoutCadenceOrPin
|
|
161
|
+
} = state, cadenceFields = normalizedSpec.kind === "interval" ? { intervalMs: normalizedSpec.intervalMs } : { cronExpression: normalizedSpec.cronExpression }, anchorFields = normalizedSpec.kind === "interval" ? { createdAt: now } : {};
|
|
162
|
+
let pinnedRevision, revisionFields;
|
|
163
|
+
if (normalizedOptions.revisionPolicy === void 0)
|
|
164
|
+
revisionFields = {
|
|
165
|
+
revisionPolicy: state.revisionPolicy,
|
|
166
|
+
...state.pinnedRevision !== void 0 && { pinnedRevision: state.pinnedRevision }
|
|
167
|
+
};
|
|
168
|
+
else if (normalizedOptions.revisionPolicy === "pinned") {
|
|
169
|
+
pinnedRevision = await resolveScheduleRevisionForPin(internals.engine, internals, state.workflowType);
|
|
170
|
+
revisionFields = { revisionPolicy: "pinned", pinnedRevision };
|
|
171
|
+
} else
|
|
172
|
+
revisionFields = { revisionPolicy: "active-at-fire" };
|
|
173
|
+
const updatedState = {
|
|
174
|
+
...stateWithoutCadenceOrPin,
|
|
158
175
|
...normalizedOptions,
|
|
159
176
|
...cadenceFields,
|
|
160
177
|
...anchorFields,
|
|
178
|
+
...revisionFields,
|
|
161
179
|
updatedAt: now,
|
|
162
180
|
nextFireAt: state.status === "cancelled" ? null : getNextScheduleOccurrence({ ...cadenceFields, createdAt: now }, now)
|
|
163
181
|
};
|
|
164
182
|
await writeScheduleState(internals, updatedState, {
|
|
165
183
|
includeTimer: state.status === "active",
|
|
166
|
-
replaceTimerFrom: state
|
|
184
|
+
replaceTimerFrom: state,
|
|
185
|
+
...await buildPinnedRevisionWriteOptions(internals, state.workflowType, pinnedRevision)
|
|
167
186
|
});
|
|
168
187
|
});
|
|
169
188
|
}
|