@lostgradient/weft 0.24.0 → 0.24.2
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 +2 -2
- package/dist/cli/conformance.js +5 -2
- package/dist/cli/generated/operation-catalog.snapshot.json +95 -1
- package/dist/cli/generated/operation-client.generated.d.ts +28 -2
- package/dist/cli/generated/operation-client.generated.js +2 -0
- package/dist/cli/parse-schedule-arguments.js +15 -3
- package/dist/cli/schedule.js +2 -1
- package/dist/cli/types.d.ts +2 -1
- package/dist/client/http-client-requests.js +6 -9
- package/dist/client/start-body.js +1 -0
- package/dist/core/catalog/index.d.ts +2 -2
- package/dist/core/catalog/index.js +9 -2
- package/dist/core/catalog/reference-counts.d.ts +29 -14
- package/dist/core/catalog/removal.d.ts +63 -10
- package/dist/core/catalog/removal.js +18 -2
- package/dist/core/catalog/storage-io.d.ts +23 -0
- package/dist/core/catalog/storage-io.js +1 -1
- package/dist/core/engine/activity-resolution.js +17 -17
- package/dist/core/engine/bulk-operations-purge.d.ts +1 -1
- package/dist/core/engine/bulk-operations-purge.js +17 -22
- package/dist/core/engine/bulk-operations-retry.d.ts +24 -0
- package/dist/core/engine/bulk-operations-retry.js +190 -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.d.ts +3 -2
- package/dist/core/engine/bulk-operations.js +10 -169
- package/dist/core/engine/callback-creators-bundles.js +5 -3
- 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-readiness.js +2 -0
- package/dist/core/engine/catalog-removal.d.ts +107 -3
- package/dist/core/engine/catalog-removal.js +66 -13
- 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/child-workflow.d.ts +13 -1
- package/dist/core/engine/child-workflow.js +22 -4
- package/dist/core/engine/constraints.js +5 -1
- package/dist/core/engine/construction.d.ts +1 -1
- 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 +24 -10
- 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 +10 -0
- package/dist/core/engine/engine-workflows-namespace.js +3 -1
- package/dist/core/engine/generation-codec.d.ts +22 -0
- package/dist/core/engine/generation-codec.js +2 -0
- package/dist/core/engine/index.d.ts +18 -10
- package/dist/core/engine/index.js +22 -11
- package/dist/core/engine/inline-launch-queue.js +1 -1
- package/dist/core/engine/internals.d.ts +26 -30
- 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-isolation.d.ts +20 -0
- package/dist/core/engine/lifecycle/recovery-isolation.js +26 -0
- 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-body.d.ts +44 -0
- package/dist/core/engine/lifecycle/resume-body.js +211 -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.d.ts +46 -3
- package/dist/core/engine/lifecycle/resume.js +21 -201
- package/dist/core/engine/lifecycle/shared.d.ts +43 -0
- package/dist/core/engine/lifecycle/standalone-claim-acquire.d.ts +80 -2
- package/dist/core/engine/lifecycle/standalone-claim-acquire.js +20 -4
- 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 +24 -7
- package/dist/core/engine/lifecycle/start-commit.js +57 -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-resolution.d.ts +8 -2
- package/dist/core/engine/lifecycle/start-or-signal-resolution.js +11 -3
- package/dist/core/engine/lifecycle/start-or-signal.js +1 -1
- package/dist/core/engine/lifecycle/start-precondition-attribution.d.ts +55 -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-schedule-timing.d.ts +11 -0
- package/dist/core/engine/lifecycle/start-schedule-timing.js +21 -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 +146 -4
- package/dist/core/engine/lifecycle/start-terminal-conflict-purge.js +33 -4
- package/dist/core/engine/lifecycle/start.d.ts +54 -7
- package/dist/core/engine/lifecycle/start.js +53 -90
- package/dist/core/engine/lifecycle/transition.d.ts +12 -4
- package/dist/core/engine/lifecycle/transition.js +40 -95
- package/dist/core/engine/lifecycle.d.ts +5 -2
- package/dist/core/engine/lifecycle.js +7 -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 +30 -0
- package/dist/core/engine/registration.js +17 -2
- 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-overlap.js +2 -1
- 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.d.ts +10 -0
- package/dist/core/engine/schedule-run.js +2 -1
- package/dist/core/engine/schedules.d.ts +11 -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.js +4 -2
- package/dist/core/engine/source-resolution.d.ts +25 -9
- package/dist/core/engine/source-resolution.js +49 -14
- 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/complete.js +1 -1
- 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/termination/suspend.js +3 -0
- 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 +29 -4
- package/dist/core/engine/validation/schedule.js +19 -36
- package/dist/core/engine/validation.js +13 -17
- package/dist/core/engine/workflow-claim-reclaim-target.d.ts +1 -1
- package/dist/core/engine/workflow-claim-reclaim-target.js +22 -8
- package/dist/core/engine/workflow-claim-registry.d.ts +79 -75
- package/dist/core/engine/workflow-claim-registry.js +15 -2
- package/dist/core/engine/workflow-generation-fence.d.ts +74 -0
- package/dist/core/engine/workflow-generation-fence.js +19 -0
- 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/event-map.d.ts +5 -0
- package/dist/core/events/index.d.ts +1 -0
- package/dist/core/events/index.js +1 -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/start-workflow-validation.d.ts +15 -0
- package/dist/core/start-workflow-validation.js +11 -1
- 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/weft-error.d.ts +1 -1
- package/dist/core/weft-error.js +4 -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/core/workflow-identifiers.d.ts +37 -0
- package/dist/core/workflow-identifiers.js +19 -1
- 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 +3 -3
- package/dist/index.js +7 -0
- package/dist/indexeddb.js +1 -1
- package/dist/json-schema.js +3 -3
- package/dist/server/fault-to-json-rpc.js +2 -1
- package/dist/server/fleet-event-feed.js +6 -6
- package/dist/server/index.d.ts +11 -0
- package/dist/server/operation-fault.d.ts +2 -0
- package/dist/server/operation-fault.js +2 -1
- package/dist/server/operations/create-schedule.d.ts +2 -0
- package/dist/server/operations/create-schedule.js +10 -6
- package/dist/server/operations/get-catalog-diagnostics.d.ts +28 -0
- package/dist/server/operations/get-catalog-diagnostics.js +10 -2
- 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/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/static-registrations.js +6 -0
- 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.js +27 -0
- package/dist/server/rest-binding.d.ts +11 -0
- package/dist/server/runtime/task-dispatch-envelope.d.ts +41 -0
- package/dist/server/runtime/task-dispatch-envelope.js +54 -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.d.ts +3 -1
- package/dist/server/runtime/task-dispatch.js +20 -44
- 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-worker.js +9 -0
- package/dist/server/task-ledger-codec.d.ts +28 -0
- package/dist/server/task-ledger-codec.js +7 -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 +3 -1
- package/dist/server/task-queue-types.d.ts +2 -0
- package/dist/storage/bun-sql.js +135 -100
- package/dist/storage/catalog-keys.d.ts +19 -0
- package/dist/storage/catalog-keys.js +3 -1
- package/dist/storage/compressed-storage.js +1 -1
- package/dist/storage/generation-keys.d.ts +52 -0
- package/dist/storage/generation-keys.js +4 -0
- package/dist/storage/index.d.ts +76 -63
- package/dist/storage/interface.d.ts +24 -230
- package/dist/storage/interface.js +1 -1
- package/dist/storage/key-prefixes.d.ts +1 -1
- package/dist/storage/key-prefixes.js +2 -0
- package/dist/storage/lease-keys.d.ts +48 -0
- package/dist/storage/lease-keys.js +8 -0
- package/dist/storage/lmdb.d.ts +30 -2
- package/dist/storage/lmdb.js +1 -1
- package/dist/storage/memory.js +1 -1
- package/dist/storage/neon.js +3 -3
- package/dist/storage/node-sqlite.js +135 -100
- package/dist/storage/postgres.js +3 -3
- package/dist/storage/resolve.js +1 -1
- package/dist/storage/scoped-storage.js +1 -1
- package/dist/storage/signal-keys.d.ts +23 -0
- package/dist/storage/signal-keys.js +9 -0
- package/dist/storage/testing.js +1 -1
- package/dist/storage/turso.js +2 -2
- package/dist/storage/workflow-lifecycle-keys.d.ts +128 -0
- package/dist/storage/workflow-lifecycle-keys.js +46 -0
- package/dist/storage/workflow-record-keys.d.ts +98 -0
- package/dist/storage/workflow-record-keys.js +47 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/web-extension.js +1 -1
- 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
|
@@ -1,13 +1,60 @@
|
|
|
1
1
|
import type { BatchOperation } from '../../../storage/interface.ts';
|
|
2
|
-
import type {
|
|
3
|
-
import { type WorkflowVersionTuple } from '../../workflow-version-tuple.ts';
|
|
2
|
+
import type { StartWorkflowOptions } from '../../types.ts';
|
|
4
3
|
import { type WorkflowHandle } from '../handles.ts';
|
|
5
4
|
import type { EngineInternals } from '../internals.ts';
|
|
6
5
|
import { type LifecycleCallbacks } from './shared.ts';
|
|
7
6
|
import { type BuildIdempotentStartOperations } from './start-commit.ts';
|
|
8
7
|
export declare function start(internals: EngineInternals, type: string, input: unknown, options: StartWorkflowOptions | undefined, callbacks: LifecycleCallbacks): Promise<WorkflowHandle>;
|
|
9
|
-
export declare function startWorkflow(internals: EngineInternals, type: string, input: unknown, options: StartWorkflowOptions | undefined, additionalStartOperations: BatchOperation[] | undefined, callbacks: LifecycleCallbacks, buildIdempotentStartOperations?: BuildIdempotentStartOperations
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
export declare function startWorkflow(internals: EngineInternals, type: string, input: unknown, options: StartWorkflowOptions | undefined, additionalStartOperations: BatchOperation[] | undefined, callbacks: LifecycleCallbacks, buildIdempotentStartOperations?: BuildIdempotentStartOperations,
|
|
9
|
+
/**
|
|
10
|
+
* A pinned schedule's forward-looking revision commitment (WFT-20),
|
|
11
|
+
* threaded from `ScheduleCallbacks.startWorkflow`'s own `revisionOverride`
|
|
12
|
+
* parameter. When supplied, this call resolves and reserves EXACTLY this
|
|
13
|
+
* revision (via {@link resolveAndReservePinnedExecutableRegistration},
|
|
14
|
+
* which enforces an exact-match check for an eager type rather than
|
|
15
|
+
* silently falling back to whatever is active) instead of the ordinary
|
|
16
|
+
* "whatever `resolveExecutableRegistration` currently resolves"
|
|
17
|
+
* admission path, and the persisted `WorkflowState.revision` is this
|
|
18
|
+
* value verbatim — never re-derived from `registeredCatalogRevisions`.
|
|
19
|
+
* `undefined` (the default, every non-schedule start) is byte-for-byte
|
|
20
|
+
* the pre-WFT-20 admission path.
|
|
21
|
+
*/
|
|
22
|
+
revisionOverride?: string,
|
|
23
|
+
/**
|
|
24
|
+
* Internal-only, never part of the public `StartOptions` type (WFT-95).
|
|
25
|
+
* When truthy, `options.id` skips strict fresh-admission validation
|
|
26
|
+
* (`assertValidWorkflowId`'s `.`/`..` rejection) and is instead validated
|
|
27
|
+
* with the decode-compatible `assertDecodableWorkflowId`. This exists
|
|
28
|
+
* ONLY to replay an id that was already durably accepted before strict
|
|
29
|
+
* admission existed — never to let a genuinely fresh caller admit `.`/`..`.
|
|
30
|
+
*
|
|
31
|
+
* Set from exactly three internal call sites, all replaying an
|
|
32
|
+
* already-persisted id rather than admitting a new one:
|
|
33
|
+
* - `drainQueuedScheduleRun()` (via `ScheduledRunStartOptions.skipAdmissionIdCheck`,
|
|
34
|
+
* threaded through `startScheduledRun()`), which restarts a schedule's
|
|
35
|
+
* persisted `queuedRuns[].workflowId` — safe unconditionally (`true`),
|
|
36
|
+
* since a queued run created after this fix was already validated as
|
|
37
|
+
* non-`.`/`..` at schedule-admission time, so relaxing the check here
|
|
38
|
+
* is a no-op for it and only matters for a historical pre-WFT-95 queued run.
|
|
39
|
+
* - `retryFailedWorkflow()`'s checkpoint-absent fallback (`bulk-operations-retry.ts`),
|
|
40
|
+
* which rebuilds an already-persisted, already-validated-at-the-time
|
|
41
|
+
* `workflowId` from its stored input via `onTerminalConflict: 'start-new'`.
|
|
42
|
+
* Passes the literal `'bulk-retry-only'` rather than `true` — see
|
|
43
|
+
* {@link enforceReplayOnlyIdFence}'s doc comment for the TOCTOU race that
|
|
44
|
+
* value fences: the retry's own confirmation read and
|
|
45
|
+
* `resolveTerminalConflictForRestart`'s atomic read are not the same
|
|
46
|
+
* read, so a concurrent purge under `ownership: 'workflow-lease'` can
|
|
47
|
+
* leave nothing to purge-and-replace by the time this runs.
|
|
48
|
+
* - `dispatchChildWorkflowStart()`'s crash-reattach retry, which passes
|
|
49
|
+
* the literal `'reattach-only'` rather than `true` — see
|
|
50
|
+
* {@link enforceReplayOnlyIdFence}'s doc comment for the same TOCTOU
|
|
51
|
+
* race (this one only *speculatively* matched an existing record
|
|
52
|
+
* before this call, unlike the schedule-drain site above).
|
|
53
|
+
*
|
|
54
|
+
* Every other caller (REST, JSON-RPC, direct `engine.start()`,
|
|
55
|
+
* `engine.startOrSignal()`, a fresh `ctx.startChild()`) omits this
|
|
56
|
+
* parameter and gets the strict check, because it is not part of
|
|
57
|
+
* `StartOptions`/`StartWorkflowOptions` and therefore cannot be set from
|
|
58
|
+
* any public surface.
|
|
59
|
+
*/
|
|
60
|
+
skipAdmissionIdCheck?: boolean | 'reattach-only' | 'bulk-retry-only'): Promise<WorkflowHandle>;
|
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
import { createCheckpoint } from "../../checkpoint.js";
|
|
2
1
|
import { assertPayloadWithinLimit } from "../../payload-size.js";
|
|
3
|
-
import { normalizeStorageTimestamp } from "../../scheduler.js";
|
|
4
2
|
import {
|
|
5
|
-
StartWorkflowValidationError,
|
|
6
|
-
assertExclusiveStartWorkflowOptions,
|
|
7
3
|
assertValidOnTerminalConflict,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
parseStartWorkflowDuration
|
|
4
|
+
coerceReplayWorkflowId,
|
|
5
|
+
coerceStartWorkflowId
|
|
11
6
|
} from "../../start-workflow-validation.js";
|
|
12
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
releaseInFlightStart,
|
|
9
|
+
resolveAndReserveExecutableRegistration
|
|
10
|
+
} from "../catalog-removal.js";
|
|
13
11
|
import { forgetCommittedCheckpointBytes } from "../checkpoint-commit-snapshots.js";
|
|
14
|
-
import { WorkflowAlreadyExistsError
|
|
12
|
+
import { WorkflowAlreadyExistsError } from "../errors.js";
|
|
15
13
|
import { createDelayedStartTimerEntry } from "../operations-time.js";
|
|
14
|
+
import { resolveAndReservePinnedExecutableRegistration } from "../pinned-schedule-revision.js";
|
|
16
15
|
import { selectPersistedWorkflowStartHeaders } from "../state-utilities.js";
|
|
17
16
|
import { buildWorkflowConcurrencyStartOperations } from "../workflow-concurrency.js";
|
|
18
17
|
import { createWorkflowVersionTuple } from "./persist.js";
|
|
@@ -28,14 +27,27 @@ import {
|
|
|
28
27
|
runWorkflowStartInterceptor
|
|
29
28
|
} from "./start-exec.js";
|
|
30
29
|
import {
|
|
30
|
+
resolveCachedStartRevision,
|
|
31
|
+
resolveStartRevisionUncached
|
|
32
|
+
} from "./start-revision-resolution.js";
|
|
33
|
+
import { resolveScheduledStartAt } from "./start-schedule-timing.js";
|
|
34
|
+
import {
|
|
35
|
+
applyRestartLineage,
|
|
36
|
+
createInitialCheckpoint,
|
|
37
|
+
createInitialWorkflowState,
|
|
38
|
+
parseStartOptionDuration
|
|
39
|
+
} from "./start-state.js";
|
|
40
|
+
import {
|
|
41
|
+
enforceReplayOnlyIdFence,
|
|
42
|
+
GENERATED_ID_START_DECISION,
|
|
31
43
|
prepareTerminalRunPurge,
|
|
32
44
|
resolveTerminalConflictForRestart
|
|
33
45
|
} from "./start-terminal-conflict-purge.js";
|
|
34
46
|
export async function start(internals, type, input, options, callbacks) {
|
|
35
47
|
return startWorkflow(internals, type, input, options, void 0, callbacks);
|
|
36
48
|
}
|
|
37
|
-
function prepareStartWorkflow(internals, options, callbacks) {
|
|
38
|
-
const callerProvidedId = options?.id !== void 0, workflowId = options?.id !== void 0 ? coerceStartWorkflowId(options.id, "options.id") : crypto.randomUUID(), parentHeaders = internals.pendingParentHeaders;
|
|
49
|
+
function prepareStartWorkflow(internals, options, callbacks, skipAdmissionIdCheck) {
|
|
50
|
+
const callerProvidedId = options?.id !== void 0, workflowId = options?.id !== void 0 ? skipAdmissionIdCheck ? coerceReplayWorkflowId(options.id, "options.id") : coerceStartWorkflowId(options.id, "options.id") : crypto.randomUUID(), parentHeaders = internals.pendingParentHeaders;
|
|
39
51
|
internals.pendingParentHeaders = void 0;
|
|
40
52
|
const pendingExecutionStateOwnerId = internals.pendingExecutionStateOwnerId, executionStateOwnerId = pendingExecutionStateOwnerId === null ? void 0 : pendingExecutionStateOwnerId ?? workflowId;
|
|
41
53
|
internals.pendingExecutionStateOwnerId = void 0;
|
|
@@ -70,14 +82,19 @@ function assertServicesSupportedForMode(internals, options) {
|
|
|
70
82
|
if (options?.services !== void 0 && internals.inlineStrategy === null)
|
|
71
83
|
throw Error('options.services is only supported in inline execution mode; it cannot be serialized to a Worker. Remove services or use workflowExecutionMode: "inline".');
|
|
72
84
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
85
|
+
function resolveAndReserveStartRegistration(internals, type, revisionOverride, callbacks) {
|
|
86
|
+
if (revisionOverride === void 0)
|
|
87
|
+
return resolveAndReserveExecutableRegistration(internals, type, callbacks.resolveExecutableRegistration);
|
|
88
|
+
return resolveAndReservePinnedExecutableRegistration(internals.engine, internals, type, revisionOverride).then(({ registration, inFlightRevision }) => ({
|
|
89
|
+
registration,
|
|
90
|
+
inFlightRevision,
|
|
91
|
+
resolvedRevision: revisionOverride
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
export async function startWorkflow(internals, type, input, options, additionalStartOperations, callbacks, buildIdempotentStartOperations, revisionOverride, skipAdmissionIdCheck) {
|
|
78
95
|
assertServicesSupportedForMode(internals, options);
|
|
79
96
|
assertValidOnTerminalConflict(options);
|
|
80
|
-
const preparation = prepareStartWorkflow(internals, options, callbacks), {
|
|
97
|
+
const preparation = prepareStartWorkflow(internals, options, callbacks, Boolean(skipAdmissionIdCheck)), {
|
|
81
98
|
workflowId,
|
|
82
99
|
callerProvidedId,
|
|
83
100
|
parentHeaders,
|
|
@@ -90,14 +107,25 @@ export async function startWorkflow(internals, type, input, options, additionalS
|
|
|
90
107
|
if (internals.pendingStarts.has(workflowId))
|
|
91
108
|
throw new WorkflowAlreadyExistsError(workflowId);
|
|
92
109
|
internals.pendingStarts.add(workflowId);
|
|
93
|
-
let startSucceeded = !1;
|
|
94
|
-
const inFlightRevision = reserveInFlightStart(internals, type);
|
|
110
|
+
let startSucceeded = !1, inFlightRevision;
|
|
95
111
|
try {
|
|
96
|
-
const terminalRunToPurge = callerProvidedId ? await resolveTerminalConflictForRestart(internals, workflowId, options) : null;
|
|
97
112
|
assertPayloadWithinLimit(input, internals.options.payloadSizePolicy.maxBytes, "workflow input");
|
|
98
|
-
const
|
|
113
|
+
const {
|
|
114
|
+
registration,
|
|
115
|
+
inFlightRevision: reservedRevision,
|
|
116
|
+
resolvedRevision
|
|
117
|
+
} = await resolveAndReserveStartRegistration(internals, type, revisionOverride, callbacks);
|
|
118
|
+
inFlightRevision = reservedRevision;
|
|
119
|
+
const workflowConcurrency = registration.concurrency, revision = resolveCachedStartRevision(internals, type, resolvedRevision) ?? await resolveStartRevisionUncached(internals, type), {
|
|
120
|
+
terminalRunToPurge,
|
|
121
|
+
duplicateIdCondition,
|
|
122
|
+
duplicateIdGenerationCondition,
|
|
123
|
+
observedGenerationBytes
|
|
124
|
+
} = callerProvidedId ? await resolveTerminalConflictForRestart(internals, workflowId, options) : GENERATED_ID_START_DECISION;
|
|
125
|
+
enforceReplayOnlyIdFence(skipAdmissionIdCheck, workflowId, terminalRunToPurge);
|
|
126
|
+
const versionTuple = createWorkflowVersionTuple(internals, registration, callbacks), state = createInitialWorkflowState(internals, workflowId, type, input, versionTuple, revision, options, preparation.normalizedTags, executionStateOwnerId, parentWorkflowId, parentWorkflowExecutionToken, delayedStartTimer, callbacks);
|
|
99
127
|
applyRestartLineage(state, terminalRunToPurge);
|
|
100
|
-
const checkpoint = createInitialCheckpoint(internals, workflowId, versionTuple.workflowVersion, options, callbacks), workflowStartHeaders = runWorkflowStartInterceptor(internals, workflowId, type, input, parentHeaders, callbacks), persistedWorkflowStartHeaders = selectPersistedWorkflowStartHeaders(workflowStartHeaders), purgeDeleteOperations = terminalRunToPurge !== null ? await prepareTerminalRunPurge(internals, terminalRunToPurge, callbacks) : void 0;
|
|
128
|
+
const checkpoint = createInitialCheckpoint(internals, workflowId, versionTuple.workflowVersion, options, callbacks), workflowStartHeaders = runWorkflowStartInterceptor(internals, workflowId, type, input, parentHeaders, callbacks), persistedWorkflowStartHeaders = selectPersistedWorkflowStartHeaders(workflowStartHeaders), purgeDeleteOperations = terminalRunToPurge !== null ? await prepareTerminalRunPurge(internals, terminalRunToPurge, callbacks, observedGenerationBytes) : void 0;
|
|
101
129
|
internals.checkpoints.set(workflowId, checkpoint);
|
|
102
130
|
setWorkflowStartHeaders(internals, workflowId, workflowStartHeaders, callbacks);
|
|
103
131
|
internals.workflowVersionTuples.set(workflowId, versionTuple);
|
|
@@ -113,7 +141,9 @@ export async function startWorkflow(internals, type, input, options, additionalS
|
|
|
113
141
|
additionalStartOperations,
|
|
114
142
|
buildWorkflowConcurrencyStartOperations: workflowConcurrency === void 0 ? void 0 : () => buildWorkflowConcurrencyStartOperations(internals, type, workflowId, input, workflowConcurrency),
|
|
115
143
|
callbacks,
|
|
116
|
-
purgeDeleteOperations
|
|
144
|
+
purgeDeleteOperations,
|
|
145
|
+
duplicateIdCondition,
|
|
146
|
+
duplicateIdGenerationCondition
|
|
117
147
|
}, buildIdempotentStartOperations);
|
|
118
148
|
if (options?.services !== void 0) {
|
|
119
149
|
internals.workflowServices.set(workflowId, options.services);
|
|
@@ -140,70 +170,3 @@ export async function startWorkflow(internals, type, input, options, additionalS
|
|
|
140
170
|
rollbackTransientStartState(internals, workflowId);
|
|
141
171
|
}
|
|
142
172
|
}
|
|
143
|
-
function applyRestartLineage(state, displacedState) {
|
|
144
|
-
if (displacedState === null)
|
|
145
|
-
return;
|
|
146
|
-
state.restartedFrom = {
|
|
147
|
-
workflowId: displacedState.id,
|
|
148
|
-
...displacedState.workflowExecutionToken !== void 0 && {
|
|
149
|
-
workflowExecutionToken: displacedState.workflowExecutionToken
|
|
150
|
-
},
|
|
151
|
-
replacedAt: state.createdAt
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
export function resolveScheduledStartAt(internals, options, submissionTime, callbacks) {
|
|
155
|
-
assertExclusiveStartWorkflowOptions(options?.startAt, options?.startAfter);
|
|
156
|
-
if (options?.startAt !== void 0)
|
|
157
|
-
return coerceStartWorkflowTimestamp(options.startAt, "options.startAt");
|
|
158
|
-
if (options?.startAfter !== void 0) {
|
|
159
|
-
const startAfterMilliseconds = parseStartOptionDuration(internals, options.startAfter, "options.startAfter", callbacks);
|
|
160
|
-
try {
|
|
161
|
-
return normalizeStorageTimestamp(submissionTime + startAfterMilliseconds, "options.startAfter");
|
|
162
|
-
} catch {
|
|
163
|
-
throw new StartWorkflowValidationError("options.startAfter must resolve to a finite, non-negative start time");
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
export function parseStartOptionDuration(_internals, duration, fieldName, _callbacks) {
|
|
169
|
-
return parseStartWorkflowDuration(duration, fieldName);
|
|
170
|
-
}
|
|
171
|
-
function buildInitialIdentitySlice(workflowId, type, input, versionTuple, executionStateOwnerId, parentWorkflowId, parentWorkflowExecutionToken, delayedStartTimer, now, tags) {
|
|
172
|
-
return {
|
|
173
|
-
id: workflowId,
|
|
174
|
-
type,
|
|
175
|
-
status: delayedStartTimer ? "pending" : "running",
|
|
176
|
-
input,
|
|
177
|
-
versionTuple,
|
|
178
|
-
workflowExecutionToken: crypto.randomUUID(),
|
|
179
|
-
...executionStateOwnerId !== void 0 && { executionStateOwnerId },
|
|
180
|
-
...parentWorkflowId !== void 0 && { parentWorkflowId },
|
|
181
|
-
...parentWorkflowExecutionToken !== void 0 && { parentWorkflowExecutionToken },
|
|
182
|
-
createdAt: now,
|
|
183
|
-
...!delayedStartTimer && { startedAt: now },
|
|
184
|
-
updatedAt: now,
|
|
185
|
-
...tags !== void 0 && { tags }
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
function resolveInitialExecutionDeadline(internals, options, delayedStartTimer, now, callbacks) {
|
|
189
|
-
if (options?.executionTimeout === void 0 || delayedStartTimer)
|
|
190
|
-
return;
|
|
191
|
-
const executionTimeoutMilliseconds = parseStartOptionDuration(internals, options.executionTimeout, "options.executionTimeout", callbacks);
|
|
192
|
-
try {
|
|
193
|
-
return normalizeStorageTimestamp(now + executionTimeoutMilliseconds, "options.executionTimeout");
|
|
194
|
-
} catch {
|
|
195
|
-
throw new StartWorkflowValidationError("options.executionTimeout must resolve to a finite, non-negative deadline");
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
export function createInitialWorkflowState(internals, workflowId, type, input, versionTuple, options, tags, executionStateOwnerId, parentWorkflowId, parentWorkflowExecutionToken, delayedStartTimer, callbacks) {
|
|
199
|
-
const now = internals.options.getNow(), state = buildInitialIdentitySlice(workflowId, type, input, versionTuple, executionStateOwnerId, parentWorkflowId, parentWorkflowExecutionToken, delayedStartTimer, now, tags), executionDeadline = resolveInitialExecutionDeadline(internals, options, delayedStartTimer, now, callbacks);
|
|
200
|
-
if (executionDeadline !== void 0)
|
|
201
|
-
state.executionDeadline = executionDeadline;
|
|
202
|
-
return state;
|
|
203
|
-
}
|
|
204
|
-
export function createInitialCheckpoint(internals, workflowId, workflowVersion, options, _callbacks) {
|
|
205
|
-
const checkpoint = createCheckpoint(workflowId, workflowVersion, internals.options.getNow());
|
|
206
|
-
if (options?.searchAttributes)
|
|
207
|
-
checkpoint.searchAttributes = { ...options.searchAttributes };
|
|
208
|
-
return checkpoint;
|
|
209
|
-
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
1
|
+
import type { ForkOptions } from '../../types.ts';
|
|
2
|
+
import type { WorkflowHandle } from '../handles.ts';
|
|
3
3
|
import type { EngineInternals } from '../internals.ts';
|
|
4
|
-
import { type
|
|
4
|
+
import { type FreshResumeClaimTracker } from './resume.ts';
|
|
5
|
+
import { type LifecycleCallbacks, type RecoverAllOptions } from './shared.ts';
|
|
5
6
|
export declare function recoverAll(internals: EngineInternals, callbacks: LifecycleCallbacks, options?: RecoverAllOptions): Promise<WorkflowHandle[]>;
|
|
6
7
|
/** Options for {@link resume}. */
|
|
7
8
|
export type ResumeOptions = {
|
|
@@ -16,7 +17,14 @@ export type ResumeOptions = {
|
|
|
16
17
|
* `engine.resume()` leaves it `false` — nothing was deposed there.
|
|
17
18
|
*/
|
|
18
19
|
readonly forceReplayFromStorage?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Forwarded to `resumeWorkflowFromStorage()`'s matching options — see
|
|
22
|
+
* `ResumeFromStorageOptions` (WFT-134 issue D). Set by
|
|
23
|
+
* `recoverEntryOrIsolateFailure` only; unset for the local-ownership fast
|
|
24
|
+
* path above, which never reaches that function.
|
|
25
|
+
*/
|
|
26
|
+
readonly deferClaimReleaseOnRejection?: boolean;
|
|
27
|
+
readonly freshClaimTracker?: FreshResumeClaimTracker;
|
|
19
28
|
};
|
|
20
29
|
export declare function resume(internals: EngineInternals, workflowId: string, callbacks: LifecycleCallbacks, onRecoveredWorkflow?: RecoverAllOptions['onRecoveredWorkflow'], options?: ResumeOptions): Promise<WorkflowHandle>;
|
|
21
30
|
export declare function fork(internals: EngineInternals, sourceWorkflowId: string, options: ForkOptions | undefined, callbacks: LifecycleCallbacks): Promise<WorkflowHandle>;
|
|
22
|
-
export declare function launchWorkflowFromCheckpoint(internals: EngineInternals, workflowId: string, state: WorkflowState, checkpoint: Checkpoint, registration: RegistrationEntry, callbacks: LifecycleCallbacks): WorkflowHandle;
|
|
@@ -1,35 +1,36 @@
|
|
|
1
1
|
import { KEYS } from "../../../storage/interface.js";
|
|
2
2
|
import { deserializeCheckpoint, serializeCheckpoint } from "../../checkpoint.js";
|
|
3
|
-
import { RegExpExtensionDecodeError } from "../../codec/extension-codec.js";
|
|
4
|
-
import { Context, setContextWorkflowInterceptor } from "../../context.js";
|
|
5
3
|
import { EMPTY_EVENT_HEAD } from "../../event-log.js";
|
|
6
|
-
import { WorkflowRecoverySkippedEvent
|
|
7
|
-
import { VersionMismatchError } from "../../versioning.js";
|
|
8
|
-
import { createCancelHandlerRegistration, resetCancelHandlers } from "../cancel-handlers.js";
|
|
4
|
+
import { WorkflowRecoverySkippedEvent } from "../../events.js";
|
|
9
5
|
import { forgetCommittedCheckpointBytes } from "../checkpoint-commit-snapshots.js";
|
|
10
6
|
import { hydrateCheckpointReplayState } from "../checkpoint-replay.js";
|
|
7
|
+
import { resolveExecutableRegistrationOrRenamedNotFound } from "../dynamic-source-execution.js";
|
|
11
8
|
import { WorkflowTypeNotRegisteredForRecoveryError } from "../errors.js";
|
|
12
9
|
import { commitFencedEngineWrite } from "../fenced-write.js";
|
|
13
|
-
import { getWorkflowExecutionStartedAt } from "../handles.js";
|
|
14
|
-
import { WorkflowClaimUnavailableError } from "../lease-errors.js";
|
|
15
10
|
import { normalizeForkStep, selectPersistedWorkflowStartHeaders } from "../state-utilities.js";
|
|
16
11
|
import { loadWorkflowState } from "../storage-io.js";
|
|
17
|
-
import { getComposedWorkflowInterceptor } from "../strategy-helpers.js";
|
|
18
12
|
import { decodeWorkflowState } from "../validation.js";
|
|
13
|
+
import { launchWorkflowFromCheckpoint } from "./checkpoint-launch.js";
|
|
19
14
|
import {
|
|
20
15
|
buildForkBatchOperations,
|
|
21
16
|
buildForkSearchAttributes,
|
|
22
17
|
createForkLineage,
|
|
23
18
|
createForkedWorkflowState
|
|
24
19
|
} from "./fork-helpers.js";
|
|
25
|
-
import {
|
|
20
|
+
import { derivePreparedExecutionState } from "./persist.js";
|
|
21
|
+
import { isolateRecoveryFailure } from "./recovery-isolation.js";
|
|
22
|
+
import {
|
|
23
|
+
buildRecoveryRevisionGroups,
|
|
24
|
+
classifyRevisionGroups,
|
|
25
|
+
createRecoveryScopedRevisionCallbacks
|
|
26
|
+
} from "./recovery-revision-groups.js";
|
|
26
27
|
import { resumeWorkflowFromStorage } from "./resume.js";
|
|
27
28
|
import {
|
|
28
|
-
createWorkflowHandle,
|
|
29
29
|
enforceHistoryPolicyBeforeReplayById,
|
|
30
30
|
loadWorkflowStartHeaders,
|
|
31
31
|
setWorkflowStartHeaders
|
|
32
32
|
} from "./shared.js";
|
|
33
|
+
import { releaseFreshlyAcquiredResumeClaim } from "./standalone-claim-acquire.js";
|
|
33
34
|
function isWorkflowSideRecordKey(key) {
|
|
34
35
|
return key.includes(":ckpt") || key.includes(":offload") || key.includes(":archive") || key.includes(":timeline:");
|
|
35
36
|
}
|
|
@@ -39,9 +40,9 @@ function classifyRecoveryState(internals, callbacks, state) {
|
|
|
39
40
|
return { kind: "local", workflowId: state.id };
|
|
40
41
|
if (state.status !== "running")
|
|
41
42
|
return { kind: "ignored" };
|
|
42
|
-
if (!internals.registrations.has(state.type))
|
|
43
|
+
if (!internals.registrations.has(state.type) && !internals.sources.byName.has(state.type))
|
|
43
44
|
return { kind: "missing", workflow: { type: state.type, workflowId: state.id } };
|
|
44
|
-
return { kind: "recoverable", workflowId: state.id };
|
|
45
|
+
return { kind: "recoverable", workflowId: state.id, type: state.type, revision: state.revision };
|
|
45
46
|
}
|
|
46
47
|
function appendRecoveryClassification(result, classification) {
|
|
47
48
|
if (classification.kind === "ignored")
|
|
@@ -63,29 +64,32 @@ async function preflightRecoverAll(internals, callbacks) {
|
|
|
63
64
|
return result;
|
|
64
65
|
}
|
|
65
66
|
async function recoverEntryOrIsolateFailure(internals, workflowId, callbacks, options) {
|
|
67
|
+
const freshClaimTracker = { epoch: null };
|
|
66
68
|
try {
|
|
67
|
-
return await resume(internals, workflowId, callbacks, options?.onRecoveredWorkflow
|
|
69
|
+
return await resume(internals, workflowId, callbacks, options?.onRecoveredWorkflow, {
|
|
70
|
+
deferClaimReleaseOnRejection: !0,
|
|
71
|
+
freshClaimTracker
|
|
72
|
+
});
|
|
68
73
|
} catch (error) {
|
|
69
|
-
|
|
70
|
-
await
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
await callbacks.failWorkflowForVersionMismatch(workflowId, error);
|
|
75
|
-
return null;
|
|
74
|
+
try {
|
|
75
|
+
return await isolateRecoveryFailure(workflowId, callbacks, options, error);
|
|
76
|
+
} finally {
|
|
77
|
+
if (freshClaimTracker.epoch !== null)
|
|
78
|
+
await releaseFreshlyAcquiredResumeClaim(internals, workflowId, freshClaimTracker.epoch);
|
|
76
79
|
}
|
|
77
|
-
if (error instanceof WorkflowClaimUnavailableError)
|
|
78
|
-
return null;
|
|
79
|
-
throw error;
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
export async function recoverAll(internals, callbacks, options) {
|
|
83
83
|
const preflight = await preflightRecoverAll(internals, callbacks), handles = [];
|
|
84
84
|
if (preflight.missingWorkflows.length > 0 && options?.acknowledgeUnknownWorkflowTypes !== !0)
|
|
85
85
|
throw new WorkflowTypeNotRegisteredForRecoveryError({
|
|
86
|
-
registeredTypes:
|
|
86
|
+
registeredTypes: new Set([
|
|
87
|
+
...internals.registrations.keys(),
|
|
88
|
+
...internals.sources.byName.keys()
|
|
89
|
+
]),
|
|
87
90
|
missingWorkflows: preflight.missingWorkflows
|
|
88
91
|
});
|
|
92
|
+
const recoverableEntries = preflight.entries.filter((entry) => entry.kind === "recoverable"), revisionGroups = buildRecoveryRevisionGroups(recoverableEntries), revisionClassifications = await classifyRevisionGroups(internals, callbacks, revisionGroups), recoveryScopedCallbacks = createRecoveryScopedRevisionCallbacks(callbacks, revisionClassifications);
|
|
89
93
|
for (const entry of preflight.entries) {
|
|
90
94
|
if (entry.kind === "local") {
|
|
91
95
|
handles.push(callbacks.getHandle(entry.workflowId));
|
|
@@ -95,7 +99,7 @@ export async function recoverAll(internals, callbacks, options) {
|
|
|
95
99
|
callbacks.dispatchEvent(new WorkflowRecoverySkippedEvent(entry.workflow.workflowId, entry.workflow.type, "type-not-registered"));
|
|
96
100
|
continue;
|
|
97
101
|
}
|
|
98
|
-
const handle = await recoverEntryOrIsolateFailure(internals, entry.workflowId,
|
|
102
|
+
const handle = await recoverEntryOrIsolateFailure(internals, entry.workflowId, recoveryScopedCallbacks, options);
|
|
99
103
|
if (handle !== null)
|
|
100
104
|
handles.push(handle);
|
|
101
105
|
}
|
|
@@ -109,16 +113,20 @@ export async function resume(internals, workflowId, callbacks, onRecoveredWorkfl
|
|
|
109
113
|
return callbacks.getHandle(workflowId);
|
|
110
114
|
}
|
|
111
115
|
}
|
|
112
|
-
return resumeWorkflowFromStorage(internals, workflowId, !0, callbacks, onRecoveredWorkflow
|
|
116
|
+
return resumeWorkflowFromStorage(internals, workflowId, !0, callbacks, onRecoveredWorkflow, {
|
|
117
|
+
...options?.deferClaimReleaseOnRejection !== void 0 && {
|
|
118
|
+
deferClaimReleaseOnRejection: options.deferClaimReleaseOnRejection
|
|
119
|
+
},
|
|
120
|
+
...options?.freshClaimTracker !== void 0 && {
|
|
121
|
+
freshClaimTracker: options.freshClaimTracker
|
|
122
|
+
}
|
|
123
|
+
});
|
|
113
124
|
}
|
|
114
125
|
export async function fork(internals, sourceWorkflowId, options, callbacks) {
|
|
115
126
|
const sourceState = await loadWorkflowState(internals, sourceWorkflowId);
|
|
116
127
|
if (!sourceState)
|
|
117
128
|
throw Error(`Workflow "${sourceWorkflowId}" not found`);
|
|
118
|
-
const registration =
|
|
119
|
-
if (!registration)
|
|
120
|
-
throw Error(`No workflow registered with name "${sourceState.type}" (needed to fork "${sourceWorkflowId}")`);
|
|
121
|
-
const fromStep = options?.fromStep !== void 0 ? normalizeForkStep(options.fromStep) : void 0, checkpointKey = fromStep !== void 0 ? KEYS.checkpointHistory(sourceWorkflowId, fromStep) : KEYS.checkpoint(sourceWorkflowId), checkpointBytes = await internals.storage.get(checkpointKey);
|
|
129
|
+
const { entry: registration, revision: resolvedRevision } = await resolveExecutableRegistrationOrRenamedNotFound((type) => callbacks.resolveExecutableRegistrationForRevision(type, sourceState.revision), sourceState.type, () => Error(`No workflow registered with name "${sourceState.type}" (needed to fork "${sourceWorkflowId}")`)), fromStep = options?.fromStep !== void 0 ? normalizeForkStep(options.fromStep) : void 0, checkpointKey = fromStep !== void 0 ? KEYS.checkpointHistory(sourceWorkflowId, fromStep) : KEYS.checkpoint(sourceWorkflowId), checkpointBytes = await internals.storage.get(checkpointKey);
|
|
122
130
|
if (!checkpointBytes) {
|
|
123
131
|
if (fromStep !== void 0)
|
|
124
132
|
throw Error(`Checkpoint not found at step ${String(fromStep)} for workflow "${sourceWorkflowId}"`);
|
|
@@ -129,14 +137,14 @@ export async function fork(internals, sourceWorkflowId, options, callbacks) {
|
|
|
129
137
|
createdAt: forkedAt,
|
|
130
138
|
workflowId,
|
|
131
139
|
searchAttributes: buildForkSearchAttributes(internals, preparedExecutionState.checkpoint, lineage, callbacks)
|
|
132
|
-
}, forkState = createForkedWorkflowState(internals, workflowId, preparedExecutionState.state, preparedExecutionState.versionTuple, lineage, forkedAt, callbacks);
|
|
140
|
+
}, forkState = createForkedWorkflowState(internals, workflowId, preparedExecutionState.state, preparedExecutionState.versionTuple, lineage, forkedAt, callbacks, resolvedRevision);
|
|
133
141
|
let forkStarted = !1;
|
|
134
142
|
try {
|
|
135
143
|
const forkCheckpointBytes = serializeCheckpoint(forkCheckpoint);
|
|
136
144
|
await commitFencedEngineWrite(internals, workflowId, buildForkBatchOperations(internals, workflowId, forkState, forkCheckpoint, forkCheckpointBytes, persistedWorkflowStartHeaders, callbacks), [], () => Error(`Fork of workflow "${workflowId}" lost its CAS race.`));
|
|
137
145
|
internals.eventLogHeads.set(workflowId, EMPTY_EVENT_HEAD);
|
|
138
146
|
setWorkflowStartHeaders(internals, workflowId, persistedWorkflowStartHeaders, callbacks);
|
|
139
|
-
const handle = launchWorkflowFromCheckpoint(internals, workflowId, forkState, forkCheckpoint, registration, callbacks);
|
|
147
|
+
const handle = launchWorkflowFromCheckpoint(internals, workflowId, forkState, forkCheckpoint, registration, resolvedRevision, callbacks);
|
|
140
148
|
forkStarted = !0;
|
|
141
149
|
return handle;
|
|
142
150
|
} finally {
|
|
@@ -149,66 +157,3 @@ export async function fork(internals, sourceWorkflowId, options, callbacks) {
|
|
|
149
157
|
}
|
|
150
158
|
}
|
|
151
159
|
}
|
|
152
|
-
function launchInlineWorkflowFromCheckpoint(internals, workflowId, state, checkpoint, registration, callbacks) {
|
|
153
|
-
const inlineStrategy = internals.inlineStrategy;
|
|
154
|
-
if (!inlineStrategy)
|
|
155
|
-
throw Error("Inline workflow launch requested without an inline strategy.");
|
|
156
|
-
const accumulatedResults = new Map(checkpoint.accumulatedResults), workflowAbort = new AbortController;
|
|
157
|
-
resetCancelHandlers(internals, workflowId);
|
|
158
|
-
const context = new Context({
|
|
159
|
-
workflowId,
|
|
160
|
-
...state.workflowExecutionToken !== void 0 && {
|
|
161
|
-
workflowExecutionToken: state.workflowExecutionToken
|
|
162
|
-
},
|
|
163
|
-
workflowType: state.type,
|
|
164
|
-
startedAt: getWorkflowExecutionStartedAt(state),
|
|
165
|
-
abortController: workflowAbort,
|
|
166
|
-
getNow: internals.options.getNow,
|
|
167
|
-
resolveWorkflowType: callbacks.resolveWorkflowTypeTarget,
|
|
168
|
-
executionStateOwnerId: state.executionStateOwnerId ?? workflowId,
|
|
169
|
-
accumulatedResults,
|
|
170
|
-
searchAttributes: checkpoint.searchAttributes,
|
|
171
|
-
registerCancelHandler: createCancelHandlerRegistration(internals, workflowId),
|
|
172
|
-
...registration.searchAttributes && {
|
|
173
|
-
searchAttributeSchema: registration.searchAttributes
|
|
174
|
-
},
|
|
175
|
-
sleepReferenceTime: checkpoint.createdAt,
|
|
176
|
-
...state.executionDeadline !== void 0 && { deadline: state.executionDeadline },
|
|
177
|
-
...internals.options.onLog != null && { logSink: internals.options.onLog }
|
|
178
|
-
});
|
|
179
|
-
setContextWorkflowInterceptor(context, getComposedWorkflowInterceptor(internals));
|
|
180
|
-
if (internals.options.development)
|
|
181
|
-
context.explain(!0);
|
|
182
|
-
const generator = registration.handler(context, state.input);
|
|
183
|
-
inlineStrategy.adoptWorkflow(workflowId, generator, context, workflowAbort);
|
|
184
|
-
inlineStrategy.continueWorkflow(workflowId, void 0);
|
|
185
|
-
callbacks.swallowPromiseRejection(callbacks.processPendingUpdatesAfterInlineAdvance(workflowId));
|
|
186
|
-
}
|
|
187
|
-
function launchWorkerWorkflowFromCheckpoint(internals, workflowId, state, checkpoint) {
|
|
188
|
-
const serialized = serializeCheckpoint(checkpoint);
|
|
189
|
-
internals.strategy.startWorkflow({
|
|
190
|
-
workflowId,
|
|
191
|
-
...state.workflowExecutionToken !== void 0 && {
|
|
192
|
-
workflowExecutionToken: state.workflowExecutionToken
|
|
193
|
-
},
|
|
194
|
-
workflowType: state.type,
|
|
195
|
-
input: state.input,
|
|
196
|
-
checkpoint: serialized,
|
|
197
|
-
executionStateOwnerId: state.executionStateOwnerId ?? workflowId,
|
|
198
|
-
...state.executionDeadline !== void 0 && { deadline: state.executionDeadline },
|
|
199
|
-
...internals.workflowHeaders.has(workflowId) && {
|
|
200
|
-
headers: [...internals.workflowHeaders.get(workflowId)]
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
export function launchWorkflowFromCheckpoint(internals, workflowId, state, checkpoint, registration, callbacks) {
|
|
205
|
-
internals.checkpoints.set(workflowId, checkpoint);
|
|
206
|
-
internals.workflowVersionTuples.set(workflowId, createWorkflowVersionTuple(internals, registration, callbacks));
|
|
207
|
-
const handle = createWorkflowHandle(internals, workflowId, callbacks);
|
|
208
|
-
callbacks.dispatchEvent(new WorkflowStartedEvent(workflowId, state.type, state.input));
|
|
209
|
-
if (internals.inlineStrategy)
|
|
210
|
-
launchInlineWorkflowFromCheckpoint(internals, workflowId, state, checkpoint, registration, callbacks);
|
|
211
|
-
else
|
|
212
|
-
launchWorkerWorkflowFromCheckpoint(internals, workflowId, state, checkpoint);
|
|
213
|
-
return handle;
|
|
214
|
-
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
export { EMPTY_STORAGE_VALUE, createWorkflowHandle, loadTerminalCleanupTrackedState, loadWorkflowStartHeaders, normalizeStartWorkflowTags, processPendingUpdatesAfterReplay, setWorkflowStartHeaders, type LifecycleCallbacks, type RecoverAllOptions, type RecoveredWorkflowInfo, } from './lifecycle/shared.ts';
|
|
2
2
|
export { createWorkflowVersionTuple, derivePreparedExecutionState, prepareResumeState, throwVersionMismatch, workflowStateWithVersionTuple, workflowVersionTupleFromState, } from './lifecycle/persist.ts';
|
|
3
|
-
export {
|
|
3
|
+
export { resolveScheduledStartAt } from './lifecycle/start-schedule-timing.ts';
|
|
4
|
+
export { start, startWorkflow } from './lifecycle/start.ts';
|
|
5
|
+
export { applyRestartLineage, createInitialCheckpoint, createInitialWorkflowState, parseStartOptionDuration, } from './lifecycle/start-state.ts';
|
|
4
6
|
export { startOrSignal, startWithIdempotency, type StartOrSignalCallbacks, type StartOrSignalResult, } from './lifecycle/start-or-signal.ts';
|
|
5
7
|
export { buildInitialSearchAttributeOperations, buildStartBatchOperations, validateSearchAttributes, } from './lifecycle/start-batch.ts';
|
|
6
8
|
export { beginWorkflowExecution, runWorkflowStartInterceptor, startWorkflowExecution, } from './lifecycle/start-exec.ts';
|
|
7
9
|
export { buildForkBatchOperations, buildForkSearchAttributes, createForkLineage, createForkedWorkflowState, } from './lifecycle/fork-helpers.ts';
|
|
8
|
-
export {
|
|
10
|
+
export { launchWorkflowFromCheckpoint } from './lifecycle/checkpoint-launch.ts';
|
|
11
|
+
export { fork, recoverAll, resume } from './lifecycle/transition.ts';
|
|
9
12
|
export { resumeWorkflowFromStorage } from './lifecycle/resume.ts';
|
|
@@ -15,14 +15,14 @@ export {
|
|
|
15
15
|
workflowStateWithVersionTuple,
|
|
16
16
|
workflowVersionTupleFromState
|
|
17
17
|
} from "./lifecycle/persist.js";
|
|
18
|
+
export { resolveScheduledStartAt } from "./lifecycle/start-schedule-timing.js";
|
|
19
|
+
export { start, startWorkflow } from "./lifecycle/start.js";
|
|
18
20
|
export {
|
|
21
|
+
applyRestartLineage,
|
|
19
22
|
createInitialCheckpoint,
|
|
20
23
|
createInitialWorkflowState,
|
|
21
|
-
parseStartOptionDuration
|
|
22
|
-
|
|
23
|
-
start,
|
|
24
|
-
startWorkflow
|
|
25
|
-
} from "./lifecycle/start.js";
|
|
24
|
+
parseStartOptionDuration
|
|
25
|
+
} from "./lifecycle/start-state.js";
|
|
26
26
|
export {
|
|
27
27
|
startOrSignal,
|
|
28
28
|
startWithIdempotency
|
|
@@ -43,5 +43,6 @@ export {
|
|
|
43
43
|
createForkLineage,
|
|
44
44
|
createForkedWorkflowState
|
|
45
45
|
} from "./lifecycle/fork-helpers.js";
|
|
46
|
-
export {
|
|
46
|
+
export { launchWorkflowFromCheckpoint } from "./lifecycle/checkpoint-launch.js";
|
|
47
|
+
export { fork, recoverAll, resume } from "./lifecycle/transition.js";
|
|
47
48
|
export { resumeWorkflowFromStorage } from "./lifecycle/resume.js";
|
|
@@ -6,6 +6,10 @@ import { buildIndexOperations, validateAttributeType } from "../search-attribute
|
|
|
6
6
|
import { normalizeWorkflowTags } from "../workflow-tags.js";
|
|
7
7
|
import { mutateWorkflowTags, validateAttributeValueSizes } from "./attributes-tags.js";
|
|
8
8
|
import { CONSTRAINED_ID_CHUNK_SIZE } from "./candidate-read-batching.js";
|
|
9
|
+
import {
|
|
10
|
+
getResolvedDynamicRegistration,
|
|
11
|
+
resolveExecutableRegistrationForRevision
|
|
12
|
+
} from "./dynamic-source-execution.js";
|
|
9
13
|
import { resolveListCandidateIds } from "./list-candidate-resolution.js";
|
|
10
14
|
import {
|
|
11
15
|
readSearchAttributesForFilter,
|
|
@@ -95,6 +99,7 @@ function summaryFromState(state, attributeFailureCategory) {
|
|
|
95
99
|
status: state.status,
|
|
96
100
|
...state.tags !== void 0 && { tags: state.tags },
|
|
97
101
|
version: state.versionTuple.workflowVersion,
|
|
102
|
+
...state.revision !== void 0 && { revision: state.revision },
|
|
98
103
|
createdAt: state.createdAt,
|
|
99
104
|
updatedAt: state.updatedAt,
|
|
100
105
|
...state.executionDeadline !== void 0 && { executionDeadline: state.executionDeadline },
|
|
@@ -164,10 +169,19 @@ export async function getAttributes(internals, workflowId) {
|
|
|
164
169
|
return null;
|
|
165
170
|
return decoded;
|
|
166
171
|
}
|
|
172
|
+
async function resolveAttributeSchemaRegistration(internals, state) {
|
|
173
|
+
const eagerOrAlreadyResolved = getResolvedDynamicRegistration(internals, state.type, state.revision);
|
|
174
|
+
if (eagerOrAlreadyResolved !== void 0)
|
|
175
|
+
return eagerOrAlreadyResolved;
|
|
176
|
+
if (!internals.sources.byName.has(state.type))
|
|
177
|
+
return;
|
|
178
|
+
const { entry } = await resolveExecutableRegistrationForRevision(internals.engine, internals, state.type, state.revision);
|
|
179
|
+
return entry;
|
|
180
|
+
}
|
|
167
181
|
export async function setAttributes(internals, workflowId, attributes) {
|
|
168
182
|
const stateBytes = await internals.storage.get(KEYS.workflow(workflowId));
|
|
169
183
|
if (stateBytes) {
|
|
170
|
-
const state = decodeWorkflowState(stateBytes), registration = internals
|
|
184
|
+
const state = decodeWorkflowState(stateBytes), registration = await resolveAttributeSchemaRegistration(internals, state);
|
|
171
185
|
if (registration?.searchAttributes) {
|
|
172
186
|
const schema = registration.searchAttributes;
|
|
173
187
|
for (const [key, value] of Object.entries(attributes)) {
|
|
@@ -45,7 +45,10 @@ class MemoDurableActivityScope {
|
|
|
45
45
|
this.#activityCallbacks = activityCallbacks;
|
|
46
46
|
this.#persistCheckpoint = persistCheckpoint;
|
|
47
47
|
this.#identityPrefix = `memo:${operation.step}:${hashString(operation.key)}`;
|
|
48
|
-
this.#internals.workflowTypeByWorkflowId.set(workflowId,
|
|
48
|
+
this.#internals.workflowTypeByWorkflowId.set(workflowId, {
|
|
49
|
+
type: context.workflowType,
|
|
50
|
+
revision: this.#internals.workflowTypeByWorkflowId.get(workflowId)?.revision
|
|
51
|
+
});
|
|
49
52
|
}
|
|
50
53
|
async run(execute) {
|
|
51
54
|
const cleanupAbortForwarding = this.#forwardAbortSignals();
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Count non-terminal (`running`, `pending`, or `suspended`) workflow runs
|
|
3
|
+
* pinned to an exact `(type, revision)` (WFT-17). Wired into
|
|
4
|
+
* `catalog-removal.ts`'s `countWorkflowRevisionReferences()`, replacing the
|
|
5
|
+
* `nonTerminalRuns: 0` stub WFT-12 left in place pending this batch (see
|
|
6
|
+
* that changelog entry: "stays 0 until run-level revision pinning (WFT-17)
|
|
7
|
+
* exists to count against").
|
|
8
|
+
*
|
|
9
|
+
* Mirrors `diagnostics/version-check.ts`'s `groupActiveWorkflowsByType()`
|
|
10
|
+
* bounded-scan shape: only top-level `wf:{id}` records are workflow states
|
|
11
|
+
* (`wf:{id}:ckpt`, `:offload`, `:archive`, `:timeline:`, and index keys all
|
|
12
|
+
* share the `wf:` prefix but are not).
|
|
13
|
+
*
|
|
14
|
+
* @module core/engine/nonterminal-revision-count
|
|
15
|
+
*/
|
|
16
|
+
import type { Storage } from '../../storage/interface.ts';
|
|
17
|
+
/**
|
|
18
|
+
* Scan `storage` for non-terminal workflow states whose `type` and
|
|
19
|
+
* `revision` match exactly, returning the count. A legacy record with no
|
|
20
|
+
* persisted `revision` never matches (a defined `revision` argument cannot
|
|
21
|
+
* equal `undefined`), consistent with recovery's own "a legacy record is a
|
|
22
|
+
* distinct, unresolved pin" treatment — it is not silently folded into
|
|
23
|
+
* whichever revision happens to be active.
|
|
24
|
+
*/
|
|
25
|
+
export declare function countNonTerminalRunsForRevision(storage: Storage, type: string, revision: string): Promise<number>;
|