@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
|
@@ -3,6 +3,20 @@ import type { ConstraintDefinition } from '../constraint.ts';
|
|
|
3
3
|
import type { ExecutionStrategy } from '../execution-strategy.ts';
|
|
4
4
|
import type { InlineExecutionStrategy } from '../inline-execution-strategy.ts';
|
|
5
5
|
import type { AnyActivityDefinition, ArchiveAdapter, Checkpoint, DefinitionSchema, EngineOptions, NormalizedHistoryPolicy, NormalizedPayloadSizePolicy, NormalizedRetentionPolicy, QueryDefinition, SearchAttributeSchema, SignalDefinition, UpdateDefinition, WorkflowConcurrencyOptions, WorkflowFunction, WorkflowTimelineEntry } from '../types.ts';
|
|
6
|
+
/**
|
|
7
|
+
* The identity a running workflow instance was launched under, cached by
|
|
8
|
+
* `EngineInternals.workflowTypeByWorkflowId` for the lifetime of its
|
|
9
|
+
* execution (WFT-19). `revision` is the exact `WorkflowState.revision` this
|
|
10
|
+
* instance is pinned to (WFT-17) — `undefined` for an eager registration or
|
|
11
|
+
* a legacy (pre-pinning) record — so a process-local lookup keyed by
|
|
12
|
+
* `workflowId` can resolve THIS instance's own dynamic-source revision
|
|
13
|
+
* rather than falling back to whichever revision this process resolved
|
|
14
|
+
* last.
|
|
15
|
+
*/
|
|
16
|
+
export type WorkflowExecutionIdentity = {
|
|
17
|
+
type: string;
|
|
18
|
+
revision: string | undefined;
|
|
19
|
+
};
|
|
6
20
|
export interface RegistrationEntry {
|
|
7
21
|
handler: WorkflowFunction;
|
|
8
22
|
version: string;
|
|
@@ -103,6 +117,8 @@ export type QueuedInlineWorkflowExecutionStart = {
|
|
|
103
117
|
nestingDepth: number;
|
|
104
118
|
executionDeadline: number | undefined;
|
|
105
119
|
executionStateOwnerId: string;
|
|
120
|
+
/** The exact revision this queued start is pinned to (WFT-17/WFT-19). */
|
|
121
|
+
revision: string | undefined;
|
|
106
122
|
/**
|
|
107
123
|
* Liveness callback invoked once this queued start has actually begun
|
|
108
124
|
* executing (its generator has been driven). Set only for `defer: false`
|
|
@@ -33,6 +33,7 @@ import { type WorkflowCatalogActivationResult, type WorkflowCatalogActivePointer
|
|
|
33
33
|
import type { WorkflowCompatibilityPolicy } from '../contract/compatibility.ts';
|
|
34
34
|
import type { WorkflowRevisionManifest } from '../contract/types.ts';
|
|
35
35
|
import type { Engine } from './index.ts';
|
|
36
|
+
import { type ResolveWorkflowSourceOptions } from './source-resolution.ts';
|
|
36
37
|
/**
|
|
37
38
|
* Options accepted by {@link EngineWorkflowsNamespace.activate}.
|
|
38
39
|
*
|
|
@@ -125,6 +126,15 @@ export interface EngineWorkflowsNamespace {
|
|
|
125
126
|
getRevision(name: string, revision: string): Promise<WorkflowRevisionRecord | null>;
|
|
126
127
|
/** Every installed revision of `name`, sorted deterministically by revision. */
|
|
127
128
|
listRevisions(name: string): Promise<readonly WorkflowRevisionRecord[]>;
|
|
129
|
+
/**
|
|
130
|
+
* Load, validate, and install one dynamic workflow source revision
|
|
131
|
+
* previously recorded via `engine.registerSource()` (WFT-15/16). A thin,
|
|
132
|
+
* documented alias for `engine.resolveWorkflowSource()` — identical
|
|
133
|
+
* single-flight, cancellation, and error contract — offered here so
|
|
134
|
+
* deployment tooling that already reaches for `engine.workflows.*` for
|
|
135
|
+
* every other catalog operation does not need a second entry point.
|
|
136
|
+
*/
|
|
137
|
+
preload(name: string, revision: string, options?: ResolveWorkflowSourceOptions): Promise<WorkflowRevisionRecord>;
|
|
128
138
|
}
|
|
129
139
|
/** Build the `engine.workflows` namespace object for `engine`. */
|
|
130
140
|
export declare function createEngineWorkflowsNamespace(engine: Engine): EngineWorkflowsNamespace;
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
isWorkflowCatalogReady
|
|
9
9
|
} from "./catalog-readiness.js";
|
|
10
10
|
import { WorkflowNotRegisteredError } from "./errors.js";
|
|
11
|
+
import { resolveWorkflowSource } from "./source-resolution.js";
|
|
11
12
|
async function ensureCatalogReady(engine) {
|
|
12
13
|
if (!isWorkflowCatalogReady(engine))
|
|
13
14
|
await ensureWorkflowCatalogReady(engine);
|
|
@@ -44,6 +45,7 @@ export function createEngineWorkflowsNamespace(engine) {
|
|
|
44
45
|
activate: (name, revision, options) => activateWorkflowRevision(engine, name, revision, options),
|
|
45
46
|
getActive: (name) => getActiveWorkflowRevision(engine, name),
|
|
46
47
|
getRevision: (name, revision) => getInstalledWorkflowRevision(engine, name, revision),
|
|
47
|
-
listRevisions: (name) => listInstalledWorkflowRevisions(engine, name)
|
|
48
|
+
listRevisions: (name) => listInstalledWorkflowRevisions(engine, name),
|
|
49
|
+
preload: (name, revision, options) => resolveWorkflowSource(engine, name, revision, options)
|
|
48
50
|
};
|
|
49
51
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure codec for the durable per-workflow-id generation counter
|
|
3
|
+
* (`wf-gen:<id>`, WFT-153).
|
|
4
|
+
*
|
|
5
|
+
* Reuses `lease-codec.ts`'s `encodeEpoch`/`decodeEpoch` under
|
|
6
|
+
* generation-specific names rather than reimplementing them: both are
|
|
7
|
+
* permanently-retained monotonic uint64 counters minted the same way
|
|
8
|
+
* (`(observed ?? 0) + 1`, never a literal), so sharing one encoder/decoder
|
|
9
|
+
* keeps their on-disk representation byte-identical and their validity range
|
|
10
|
+
* ([1, MAX_SAFE_INTEGER)) — fail-closed on corruption — in lockstep by
|
|
11
|
+
* construction rather than by convention.
|
|
12
|
+
*
|
|
13
|
+
* @module core/engine/generation-codec
|
|
14
|
+
*/
|
|
15
|
+
import { decodeEpoch, encodeEpoch } from './lease-codec.ts';
|
|
16
|
+
/** Encode an 8-byte big-endian uint64 generation. See `lease-codec.ts#encodeEpoch`. */
|
|
17
|
+
export declare const encodeGeneration: typeof encodeEpoch;
|
|
18
|
+
/**
|
|
19
|
+
* Decode an 8-byte big-endian uint64 generation, or `null` when the stored
|
|
20
|
+
* value is not a usable generation. See `lease-codec.ts#decodeEpoch`.
|
|
21
|
+
*/
|
|
22
|
+
export declare const decodeGeneration: typeof decodeEpoch;
|
|
@@ -30,6 +30,7 @@ export { ActivityReconciliationCapabilityError, ActivityReconciliationConflictEr
|
|
|
30
30
|
export { AsyncActivityTokenNotFoundError } from './async-activity-completion.ts';
|
|
31
31
|
export type { PendingAsyncActivity } from './async-activity-records.ts';
|
|
32
32
|
export { getWorkflowRevisionDiagnostics, removeWorkflowRevision, type WorkflowCatalogRemovalResult, type WorkflowRevisionDiagnostics, } from './catalog-removal.ts';
|
|
33
|
+
export { DynamicWorkflowSourceUnavailableError, WorkflowSourceNotRegisteredError, } from './dynamic-source-errors.ts';
|
|
33
34
|
export type { PendingTimelineEntry, RegistrationEntry, ResolvedOptions, TrackedWaiterKeys, WorkflowResultWaiter, } from './engine-internal-types.ts';
|
|
34
35
|
export { ActivityResolutionError, BulkDeleteRequiresTerminalWorkflowsError, BulkOperationConfirmationError, EngineCreateNameMismatchError, EngineDisposalError, EngineDisposedError, IdempotencyKeyPurgedError, PersistedDataCorruptError, PersistedDataIncompatibleError, StartOrSignalConflictError, WorkflowAlreadyExistsError, WorkflowConcurrencyLimitExceededError, WorkflowNotFoundError, WorkflowNotRegisteredError, WorkflowSuspendNotSupportedError, WorkflowTeardownPendingError, WorkflowTypeNotRegisteredForRecoveryError, } from './errors.ts';
|
|
35
36
|
export { HANDLE_RESULT_PROMISE, WorkflowHandle } from './handles.ts';
|
|
@@ -39,6 +40,7 @@ export type { WorkflowWakeKind } from './lease-deposition.ts';
|
|
|
39
40
|
export { EngineLeaseAcquisitionTimeoutError, EngineLeaseCorruptedError, EngineLeaseNotHeldError, OwnershipModeMismatchError, WorkflowClaimUnavailableError, } from './lease-errors.ts';
|
|
40
41
|
export type { EngineLeaseHealth, LeaseLostReason } from './lease-health.ts';
|
|
41
42
|
export type { RecoverAllOptions, RecoveredWorkflowInfo } from './lifecycle.ts';
|
|
43
|
+
export { WorkflowRevisionUnavailableError } from './revision-errors.ts';
|
|
42
44
|
export { ScheduleHandle } from './schedule-handle.ts';
|
|
43
45
|
export type { ResolveWorkflowSourceOptions } from './source-resolution.ts';
|
|
44
46
|
export type { WorkflowFeedListener, WorkflowFeedRecord, WorkflowFeedSelector, } from './workflow-feed.ts';
|
|
@@ -299,11 +301,15 @@ export declare class Engine<TWorkflows extends object = DefaultWorkflowRegistry,
|
|
|
299
301
|
getActivityDefinition(name: string): ActivityMetadata | undefined;
|
|
300
302
|
listActivityDefinitions(): ActivityMetadata[];
|
|
301
303
|
/**
|
|
302
|
-
* Resolve one activity's catalog metadata the
|
|
303
|
-
*
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
*
|
|
304
|
+
* Resolve one activity's catalog metadata against the EAGER per-workflow
|
|
305
|
+
* `.activities({...})` registry only, falling back to the global registry
|
|
306
|
+
* — never a `registerSource()`-registered type's dynamic-source revision,
|
|
307
|
+
* resolved or not (WFT-19: `internals.activityRegistriesByWorkflow` is
|
|
308
|
+
* eager-only as of this batch; a dynamic-source workflow's own activity
|
|
309
|
+
* dispatch resolves via the running instance's exact `(type, revision)`
|
|
310
|
+
* pin instead, in `activity-resolution.ts`, which this synchronous,
|
|
311
|
+
* type-only accessor has no instance to pin against). Build tooling
|
|
312
|
+
* (`buildWorkerManifestFromRegistry`) uses this so a workflow-scoped
|
|
307
313
|
* activity's schema, not a same-named global activity's, feeds its
|
|
308
314
|
* `contractHash` when both are registered.
|
|
309
315
|
*/
|
|
@@ -318,11 +324,13 @@ export declare class Engine<TWorkflows extends object = DefaultWorkflowRegistry,
|
|
|
318
324
|
*
|
|
319
325
|
* Companion to {@link getWorkflowActivityDefinition}: that resolves one
|
|
320
326
|
* activity by name with the per-workflow-first, global-fallback dispatch
|
|
321
|
-
* order; this enumerates only the names the per-workflow registry
|
|
322
|
-
* declares — activities a workflow reaches solely through the
|
|
323
|
-
* registry are deliberately excluded,
|
|
324
|
-
*
|
|
325
|
-
*
|
|
327
|
+
* order; this enumerates only the names the EAGER per-workflow registry
|
|
328
|
+
* itself declares — activities a workflow reaches solely through the
|
|
329
|
+
* global registry are deliberately excluded, and so (as of WFT-19) is
|
|
330
|
+
* every `registerSource()`-registered type regardless of whether a
|
|
331
|
+
* revision has been resolved (see {@link getWorkflowActivityDefinition}'s
|
|
332
|
+
* doc). Build tooling that needs a workflow's full scoped-activity
|
|
333
|
+
* contract set (`buildRegistrySnapshot`,
|
|
326
334
|
* `worker/manifest/registry-contract-builder.ts`) uses this instead of
|
|
327
335
|
* reaching into engine internals directly.
|
|
328
336
|
*/
|
|
@@ -66,6 +66,10 @@ import {
|
|
|
66
66
|
typedEngineView
|
|
67
67
|
} from "./construction.js";
|
|
68
68
|
import { disposeEngine } from "./disposal.js";
|
|
69
|
+
import {
|
|
70
|
+
canResolveRevisionLocally,
|
|
71
|
+
getResolvedDynamicRegistration
|
|
72
|
+
} from "./dynamic-source-execution.js";
|
|
69
73
|
import {
|
|
70
74
|
consumeNextEngineLeakWarningTokenForTesting,
|
|
71
75
|
engineCleanupIntervalFinalizer
|
|
@@ -175,6 +179,7 @@ import { registerSource as registerWorkflowSource } from "./source-registration.
|
|
|
175
179
|
import {
|
|
176
180
|
resolveWorkflowSource as resolveWorkflowSourceImpl
|
|
177
181
|
} from "./source-resolution.js";
|
|
182
|
+
import { createWorkflowSourceRuntimeState } from "./source-runtime-state.js";
|
|
178
183
|
import {
|
|
179
184
|
loadScheduleState,
|
|
180
185
|
loadWorkflowState,
|
|
@@ -216,6 +221,10 @@ export {
|
|
|
216
221
|
getWorkflowRevisionDiagnostics,
|
|
217
222
|
removeWorkflowRevision
|
|
218
223
|
} from "./catalog-removal.js";
|
|
224
|
+
export {
|
|
225
|
+
DynamicWorkflowSourceUnavailableError,
|
|
226
|
+
WorkflowSourceNotRegisteredError
|
|
227
|
+
} from "./dynamic-source-errors.js";
|
|
219
228
|
export {
|
|
220
229
|
ActivityResolutionError,
|
|
221
230
|
BulkDeleteRequiresTerminalWorkflowsError,
|
|
@@ -250,6 +259,7 @@ export {
|
|
|
250
259
|
OwnershipModeMismatchError,
|
|
251
260
|
WorkflowClaimUnavailableError
|
|
252
261
|
} from "./lease-errors.js";
|
|
262
|
+
export { WorkflowRevisionUnavailableError } from "./revision-errors.js";
|
|
253
263
|
export { ScheduleHandle } from "./schedule-handle.js";
|
|
254
264
|
export {
|
|
255
265
|
clearEngineLeakWarningTokenForTesting,
|
|
@@ -270,7 +280,8 @@ function scheduleDefinitionFromInternals(internals, definition) {
|
|
|
270
280
|
...definition.description !== void 0 && { description: definition.description },
|
|
271
281
|
...definition.overlapPolicy !== void 0 && { overlap: definition.overlapPolicy },
|
|
272
282
|
...definition.backfill !== void 0 && { backfill: definition.backfill },
|
|
273
|
-
...definition.jitter !== void 0 && { jitter: definition.jitter }
|
|
283
|
+
...definition.jitter !== void 0 && { jitter: definition.jitter },
|
|
284
|
+
...definition.revisionPolicy !== void 0 && { revisionPolicy: definition.revisionPolicy }
|
|
274
285
|
});
|
|
275
286
|
}
|
|
276
287
|
|
|
@@ -318,8 +329,11 @@ export class Engine extends EventTarget {
|
|
|
318
329
|
maxNestingDepth: resolvedOptions.maxNestingDepth,
|
|
319
330
|
development: resolvedOptions.development,
|
|
320
331
|
broadcastEvents: resolvedOptions.broadcastEvents,
|
|
321
|
-
getRegistration: getInternals(this)
|
|
322
|
-
listRegisteredWorkflowTypes: () =>
|
|
332
|
+
getRegistration: (workflowType, workflowId) => getResolvedDynamicRegistration(getInternals(this), workflowType, getInternals(this).workflowTypeByWorkflowId.get(workflowId)?.revision),
|
|
333
|
+
listRegisteredWorkflowTypes: () => new Set([
|
|
334
|
+
...getInternals(this).registrations.keys(),
|
|
335
|
+
...getInternals(this).sources.lastResolvedRevisionByName.keys()
|
|
336
|
+
]).values(),
|
|
323
337
|
getComposedWorkflowInterceptor: () => getComposedWorkflowInterceptor(getInternals(this)),
|
|
324
338
|
resolveWorkflowType: this.#resolveWorkflowTypeTarget.bind(this),
|
|
325
339
|
registerCancelHandler: (workflowId, handler) => registerCancelHandler(getInternals(this), workflowId, handler),
|
|
@@ -445,10 +459,7 @@ export class Engine extends EventTarget {
|
|
|
445
459
|
getInternals(this).catalogDrainPromise = null;
|
|
446
460
|
getInternals(this).registeredCatalogRevisions = new Map;
|
|
447
461
|
getInternals(this).inFlightStartsByRevision = new Map;
|
|
448
|
-
getInternals(this).
|
|
449
|
-
getInternals(this).sourceResolutionsInFlight = new Map;
|
|
450
|
-
getInternals(this).sourceResolutionWaiterControllers = new Set;
|
|
451
|
-
getInternals(this).resolvedWorkflowSources = new Map;
|
|
462
|
+
getInternals(this).sources = createWorkflowSourceRuntimeState();
|
|
452
463
|
this.#ensureRetentionSweepInterval();
|
|
453
464
|
this.#startSecondInstanceDetection();
|
|
454
465
|
}
|
|
@@ -539,7 +550,7 @@ export class Engine extends EventTarget {
|
|
|
539
550
|
getNow: internals.options.getNow,
|
|
540
551
|
claimTtlMs: internals.options.workflowClaimTtlMs,
|
|
541
552
|
claimRenewIntervalMs: internals.options.workflowClaimRenewIntervalMs,
|
|
542
|
-
isWorkflowTypeRegistered: (workflowType) => internals
|
|
553
|
+
isWorkflowTypeRegistered: (workflowType, revision) => canResolveRevisionLocally(internals, workflowType, revision),
|
|
543
554
|
onWorkflowClaimReclaimed: async (workflowId) => {
|
|
544
555
|
internals.inlineStrategy?.evictContextForReclaim(workflowId);
|
|
545
556
|
internals.deliveredPendingUpdateIds.delete(workflowId);
|
|
@@ -836,7 +847,7 @@ export class Engine extends EventTarget {
|
|
|
836
847
|
return cancelAllWorkflows(getInternals(this), filter, options);
|
|
837
848
|
}
|
|
838
849
|
async retryFailedAll(filter, options) {
|
|
839
|
-
return retryFailedAllWorkflows(getInternals(this), filter, options);
|
|
850
|
+
return retryFailedAllWorkflows(getInternals(this), filter, options, this.#createLifecycleCallbacks());
|
|
840
851
|
}
|
|
841
852
|
async signalAll(filter, name, payloadOrOptions, options) {
|
|
842
853
|
if (options === void 0)
|
|
@@ -1143,7 +1154,7 @@ export class Engine extends EventTarget {
|
|
|
1143
1154
|
if (leaseManager !== null && leaseManager.currentEpochBytes() !== null)
|
|
1144
1155
|
process.emitWarning("engine ownership lease disposed synchronously; lease release is fire-and-forget, so exiting before the release completes can make the next instance wait for leaseTtl. Use await engine.shutdown(), await using, or await engine[Symbol.asyncDispose]() for prompt rolling-deploy handoff.", ENGINE_LEASE_SYNCHRONOUS_DISPOSE_WARNING_NAME);
|
|
1145
1156
|
const { registry: workflowClaimRegistry } = this.#detachWorkflowClaimOwnership();
|
|
1146
|
-
disposeEngine(getInternals(this));
|
|
1157
|
+
disposeEngine(getInternals(this), (event) => this.dispatchEvent(event));
|
|
1147
1158
|
if (this.#synchronousDisposeResult === null)
|
|
1148
1159
|
this.#synchronousDisposeResult = leaseManager?.release() ?? Promise.resolve(!0);
|
|
1149
1160
|
this.#synchronousDisposeResult;
|
|
@@ -1161,7 +1172,7 @@ export class Engine extends EventTarget {
|
|
|
1161
1172
|
drainFailure = { error };
|
|
1162
1173
|
} finally {
|
|
1163
1174
|
const { registry: workflowClaimRegistry } = this.#detachWorkflowClaimOwnership();
|
|
1164
|
-
disposeEngine(getInternals(this));
|
|
1175
|
+
disposeEngine(getInternals(this), (event) => this.dispatchEvent(event));
|
|
1165
1176
|
await getInternals(this).inFlightLeaseAcquire?.catch(() => {});
|
|
1166
1177
|
leaseReleased = await (this.#synchronousDisposeResult ?? leaseManager?.release() ?? Promise.resolve(!0));
|
|
1167
1178
|
await this.#releaseWorkflowClaimsBestEffort(workflowClaimRegistry);
|
|
@@ -99,7 +99,7 @@ async function startQueuedInlineWorkflowExecution(internals, start, callbacks, o
|
|
|
99
99
|
return;
|
|
100
100
|
internals.queuedInlineWorkflowStartIds.delete(start.workflowId);
|
|
101
101
|
internals.engine.dispatchEvent(new WorkflowStartedEvent(start.workflowId, start.workflowType, start.input));
|
|
102
|
-
startWorkflowExecution(internals, start.workflowId, state.workflowExecutionToken, start.workflowType, start.input, start.checkpoint, start.nestingDepth, start.executionDeadline, start.executionStateOwnerId);
|
|
102
|
+
startWorkflowExecution(internals, start.workflowId, state.workflowExecutionToken, start.workflowType, state.revision, start.input, start.checkpoint, start.nestingDepth, start.executionDeadline, start.executionStateOwnerId);
|
|
103
103
|
if (options?.abortStartedWorkflows === !0)
|
|
104
104
|
internals.inlineStrategy?.abortWorkflowAdvanceForShutdown(start.workflowId);
|
|
105
105
|
else
|
|
@@ -29,18 +29,19 @@ import type { InlineExecutionStrategy } from '../inline-execution-strategy.ts';
|
|
|
29
29
|
import type { ComposedActivityInterceptor, ComposedWorkflowInterceptor, Interceptor } from '../interceptor.ts';
|
|
30
30
|
import type { HumanReviewResult, ReviewCoordinator } from '../review/index.ts';
|
|
31
31
|
import type { Scheduler } from '../scheduler.ts';
|
|
32
|
-
import type { Checkpoint, StartWorkflowOptions
|
|
32
|
+
import type { Checkpoint, StartWorkflowOptions } from '../types.ts';
|
|
33
33
|
import type { UpdateCoordinator } from '../updates.ts';
|
|
34
34
|
import type { WorkflowVersionTuple } from '../workflow-version-tuple.ts';
|
|
35
35
|
import type { RecoveredWorkflowInfo } from './lifecycle/shared.ts';
|
|
36
36
|
import type { ActivityHeartbeatKey } from './activity-heartbeat-tracking.ts';
|
|
37
|
-
import type { PendingTimelineEntry, QueuedInlineWorkflowExecutionStart, RegistrationEntry, ResolvedOptions, TrackedWaiterKeys, WorkflowResultWaiter } from './engine-internal-types.ts';
|
|
37
|
+
import type { PendingTimelineEntry, QueuedInlineWorkflowExecutionStart, RegistrationEntry, ResolvedOptions, TrackedWaiterKeys, WorkflowExecutionIdentity, WorkflowResultWaiter } from './engine-internal-types.ts';
|
|
38
38
|
import type { EngineCleanupIntervalDisposalTracker } from './engine-leak-warnings.ts';
|
|
39
39
|
import type { WorkflowHandle, WorkflowHandleEngine } from './handles.ts';
|
|
40
40
|
import type { WorkflowFeedListener } from './index.ts';
|
|
41
41
|
import type { LeaseManager } from './lease-manager.ts';
|
|
42
42
|
import type { ScheduleHandleEngine } from './schedule-handle.ts';
|
|
43
43
|
import type { SecondInstanceDetector } from './second-instance-detector.ts';
|
|
44
|
+
import type { WorkflowSourceRuntimeState } from './source-runtime-state.ts';
|
|
44
45
|
import type { WorkflowClaimMetricsRecorder } from './workflow-claim-metrics.ts';
|
|
45
46
|
import type { WorkflowClaimRegistry } from './workflow-claim-registry.ts';
|
|
46
47
|
import type { WorkflowClaimRenewalTask } from './workflow-claim-renewal-task.ts';
|
|
@@ -58,12 +59,6 @@ export type DurableInlineOperation = {
|
|
|
58
59
|
type EngineRuntime = WorkflowHandleEngine & ScheduleHandleEngine & {
|
|
59
60
|
start(type: string, input: unknown, options?: StartWorkflowOptions): Promise<WorkflowHandle>;
|
|
60
61
|
};
|
|
61
|
-
type SourceHandle = import('../source/index.ts').WorkflowSourceHandle;
|
|
62
|
-
type CatalogRevisionRecord = import('../catalog/index.ts').WorkflowRevisionRecord;
|
|
63
|
-
type ResolvedSource = {
|
|
64
|
-
definition: WorkflowDefinition;
|
|
65
|
-
activityRegistry: ActivityRegistry;
|
|
66
|
-
};
|
|
67
62
|
export interface EngineInternals {
|
|
68
63
|
engine: EngineRuntime;
|
|
69
64
|
storage: WeftStorage;
|
|
@@ -155,15 +150,15 @@ export interface EngineInternals {
|
|
|
155
150
|
/**
|
|
156
151
|
* Per-workflow activity registries built from
|
|
157
152
|
* `workflow({ name }).activities({ ... }).execute(...)`, indexed by workflow
|
|
158
|
-
* type.
|
|
159
|
-
*
|
|
160
|
-
* that registry
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
153
|
+
* type. Lookup consults `activityRegistriesByWorkflow.get(type)` first,
|
|
154
|
+
* falling back to {@link EngineInternals.activityRegistry} for any activity
|
|
155
|
+
* that registry lacks. Each entry is a defensive deep clone+freeze of the
|
|
156
|
+
* workflow's `activities` map. EAGER-ONLY as of WFT-19: only `registration.ts`
|
|
157
|
+
* writes here (never a `registerSource()` load), so a dynamic-source type's
|
|
158
|
+
* per-revision activities resolve instead via
|
|
159
|
+
* `internals.sources.resolved.get(type)?.get(revision)?.activityRegistry`
|
|
160
|
+
* (`activity-resolution.ts`), keyed by the running instance's own pin —
|
|
161
|
+
* never this type-only map, which would clobber across revisions.
|
|
167
162
|
*/
|
|
168
163
|
activityRegistriesByWorkflow: Map<string, ActivityRegistry>;
|
|
169
164
|
/**
|
|
@@ -175,12 +170,13 @@ export interface EngineInternals {
|
|
|
175
170
|
*/
|
|
176
171
|
workflowDefinitionsByName: Map<string, object>;
|
|
177
172
|
/**
|
|
178
|
-
* In-memory cache of `workflowId ->
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
173
|
+
* In-memory cache of `workflowId -> {type, revision}`, populated whenever a
|
|
174
|
+
* workflow begins executing in THIS process (fresh start, delayed-start
|
|
175
|
+
* fire, resume, recovery, workflow-lease reclaim redrive — WFT-19) and
|
|
176
|
+
* cleared on terminal cleanup. Lets the activity-dispatch hot path, and any
|
|
177
|
+
* other lookup needing an instance's own exact pin, resolve synchronously.
|
|
182
178
|
*/
|
|
183
|
-
workflowTypeByWorkflowId: Map<string,
|
|
179
|
+
workflowTypeByWorkflowId: Map<string, WorkflowExecutionIdentity>;
|
|
184
180
|
activityWorkerDispatcher: ActivityWorkerDispatcher | null;
|
|
185
181
|
checkpoints: Map<string, Checkpoint>;
|
|
186
182
|
broadcastChannel: BroadcastChannel | null;
|
|
@@ -409,14 +405,14 @@ export interface EngineInternals {
|
|
|
409
405
|
registeredCatalogRevisions: Map<string, string>;
|
|
410
406
|
/** Name -> revision -> in-flight `startWorkflow` count (WFT-12, `lifecycle/start.ts`). Process-local, never persisted. */
|
|
411
407
|
inFlightStartsByRevision: Map<string, Map<string, number>>;
|
|
412
|
-
/**
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
408
|
+
/**
|
|
409
|
+
* Dynamic workflow sources (WFT-13/14, WFT-15/16): candidates, in-flight
|
|
410
|
+
* single-flight loads, per-caller waiter controllers, locally-resolved
|
|
411
|
+
* definitions, and bounded per-`(name, revision)` diagnostics — see
|
|
412
|
+
* {@link import('./source-runtime-state.ts').WorkflowSourceRuntimeState}
|
|
413
|
+
* for the full field-by-field breakdown. Process-local, never persisted.
|
|
414
|
+
*/
|
|
415
|
+
sources: WorkflowSourceRuntimeState;
|
|
420
416
|
}
|
|
421
417
|
/**
|
|
422
418
|
* Set up an empty `EngineInternals` skeleton in the WeakMap. The Engine
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Launch a workflow run from an already-built `WorkflowState`/`Checkpoint`
|
|
3
|
+
* pair — the shared tail `fork()` (`transition.ts`) drives after planting a
|
|
4
|
+
* new run's durable records. Split out of `transition.ts`, which has no
|
|
5
|
+
* headroom under the repository's 500-line implementation-file ceiling for
|
|
6
|
+
* this logic inline.
|
|
7
|
+
*
|
|
8
|
+
* @module core/engine/lifecycle/checkpoint-launch
|
|
9
|
+
*/
|
|
10
|
+
import type { Checkpoint, WorkflowState } from '../../types.ts';
|
|
11
|
+
import { type WorkflowHandle } from '../handles.ts';
|
|
12
|
+
import type { EngineInternals } from '../internals.ts';
|
|
13
|
+
import { type LifecycleCallbacks, type RegistrationEntry } from './shared.ts';
|
|
14
|
+
export declare function launchWorkflowFromCheckpoint(internals: EngineInternals, workflowId: string, state: WorkflowState, checkpoint: Checkpoint, registration: RegistrationEntry,
|
|
15
|
+
/**
|
|
16
|
+
* The EXACT revision `registration` was resolved against — from the same
|
|
17
|
+
* `resolveExecutableRegistrationForRevision()` call that produced
|
|
18
|
+
* `registration`, threaded through explicitly rather than re-read off
|
|
19
|
+
* `state.revision` (WFT-19 review round 5, Codex, mirroring the identical
|
|
20
|
+
* fix in `lifecycle/resume.ts`). `fork()`'s own `forkState.revision` is
|
|
21
|
+
* now stamped with this same resolved value too (WFT-19 review round 6,
|
|
22
|
+
* Codex — `createForkedWorkflowState()`'s matching fix, so a legacy
|
|
23
|
+
* fork's durable pin agrees with this in-memory one), so `state.revision`
|
|
24
|
+
* and `resolvedRevision` coincide for every current caller; kept as an
|
|
25
|
+
* explicit parameter regardless, since this function's identity-cache
|
|
26
|
+
* write must never depend on that invariant holding at a future call
|
|
27
|
+
* site.
|
|
28
|
+
*/
|
|
29
|
+
resolvedRevision: string | undefined, callbacks: LifecycleCallbacks): WorkflowHandle;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { serializeCheckpoint } from "../../checkpoint.js";
|
|
2
|
+
import { Context, setContextWorkflowInterceptor } from "../../context.js";
|
|
3
|
+
import { WorkflowStartedEvent } from "../../events.js";
|
|
4
|
+
import { createCancelHandlerRegistration, resetCancelHandlers } from "../cancel-handlers.js";
|
|
5
|
+
import { getWorkflowExecutionStartedAt } from "../handles.js";
|
|
6
|
+
import { getComposedWorkflowInterceptor } from "../strategy-helpers.js";
|
|
7
|
+
import { createWorkflowVersionTuple } from "./persist.js";
|
|
8
|
+
import { createWorkflowHandle } from "./shared.js";
|
|
9
|
+
function launchInlineWorkflowFromCheckpoint(internals, workflowId, state, checkpoint, registration, callbacks) {
|
|
10
|
+
const inlineStrategy = internals.inlineStrategy;
|
|
11
|
+
if (!inlineStrategy)
|
|
12
|
+
throw Error("Inline workflow launch requested without an inline strategy.");
|
|
13
|
+
const accumulatedResults = new Map(checkpoint.accumulatedResults), workflowAbort = new AbortController;
|
|
14
|
+
resetCancelHandlers(internals, workflowId);
|
|
15
|
+
const context = new Context({
|
|
16
|
+
workflowId,
|
|
17
|
+
...state.workflowExecutionToken !== void 0 && {
|
|
18
|
+
workflowExecutionToken: state.workflowExecutionToken
|
|
19
|
+
},
|
|
20
|
+
workflowType: state.type,
|
|
21
|
+
startedAt: getWorkflowExecutionStartedAt(state),
|
|
22
|
+
abortController: workflowAbort,
|
|
23
|
+
getNow: internals.options.getNow,
|
|
24
|
+
resolveWorkflowType: callbacks.resolveWorkflowTypeTarget,
|
|
25
|
+
executionStateOwnerId: state.executionStateOwnerId ?? workflowId,
|
|
26
|
+
accumulatedResults,
|
|
27
|
+
searchAttributes: checkpoint.searchAttributes,
|
|
28
|
+
registerCancelHandler: createCancelHandlerRegistration(internals, workflowId),
|
|
29
|
+
...registration.searchAttributes && {
|
|
30
|
+
searchAttributeSchema: registration.searchAttributes
|
|
31
|
+
},
|
|
32
|
+
sleepReferenceTime: checkpoint.createdAt,
|
|
33
|
+
...state.executionDeadline !== void 0 && { deadline: state.executionDeadline },
|
|
34
|
+
...internals.options.onLog != null && { logSink: internals.options.onLog }
|
|
35
|
+
});
|
|
36
|
+
setContextWorkflowInterceptor(context, getComposedWorkflowInterceptor(internals));
|
|
37
|
+
if (internals.options.development)
|
|
38
|
+
context.explain(!0);
|
|
39
|
+
const generator = registration.handler(context, state.input);
|
|
40
|
+
inlineStrategy.adoptWorkflow(workflowId, generator, context, workflowAbort);
|
|
41
|
+
inlineStrategy.continueWorkflow(workflowId, void 0);
|
|
42
|
+
callbacks.swallowPromiseRejection(callbacks.processPendingUpdatesAfterInlineAdvance(workflowId));
|
|
43
|
+
}
|
|
44
|
+
function launchWorkerWorkflowFromCheckpoint(internals, workflowId, state, checkpoint) {
|
|
45
|
+
const serialized = serializeCheckpoint(checkpoint);
|
|
46
|
+
internals.strategy.startWorkflow({
|
|
47
|
+
workflowId,
|
|
48
|
+
...state.workflowExecutionToken !== void 0 && {
|
|
49
|
+
workflowExecutionToken: state.workflowExecutionToken
|
|
50
|
+
},
|
|
51
|
+
workflowType: state.type,
|
|
52
|
+
input: state.input,
|
|
53
|
+
checkpoint: serialized,
|
|
54
|
+
executionStateOwnerId: state.executionStateOwnerId ?? workflowId,
|
|
55
|
+
...state.executionDeadline !== void 0 && { deadline: state.executionDeadline },
|
|
56
|
+
...internals.workflowHeaders.has(workflowId) && {
|
|
57
|
+
headers: [...internals.workflowHeaders.get(workflowId)]
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
export function launchWorkflowFromCheckpoint(internals, workflowId, state, checkpoint, registration, resolvedRevision, callbacks) {
|
|
62
|
+
internals.workflowTypeByWorkflowId.set(workflowId, {
|
|
63
|
+
type: state.type,
|
|
64
|
+
revision: resolvedRevision
|
|
65
|
+
});
|
|
66
|
+
internals.checkpoints.set(workflowId, checkpoint);
|
|
67
|
+
internals.workflowVersionTuples.set(workflowId, createWorkflowVersionTuple(internals, registration, callbacks));
|
|
68
|
+
const handle = createWorkflowHandle(internals, workflowId, callbacks);
|
|
69
|
+
callbacks.dispatchEvent(new WorkflowStartedEvent(workflowId, state.type, state.input));
|
|
70
|
+
if (internals.inlineStrategy)
|
|
71
|
+
launchInlineWorkflowFromCheckpoint(internals, workflowId, state, checkpoint, registration, callbacks);
|
|
72
|
+
else
|
|
73
|
+
launchWorkerWorkflowFromCheckpoint(internals, workflowId, state, checkpoint);
|
|
74
|
+
return handle;
|
|
75
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { TimerEntry } from '../../types.ts';
|
|
2
|
+
import type { ExecutableRegistration } from '../dynamic-source-execution.ts';
|
|
3
|
+
import type { EngineInternals } from '../internals.ts';
|
|
4
|
+
import type { TimeOperationCallbacks } from '../operations-time.ts';
|
|
5
|
+
/**
|
|
6
|
+
* Resolve `type`'s registration for a delayed-start fire, failing the
|
|
7
|
+
* workflow (via `callbacks.failWorkflow`) and returning `null` on any
|
|
8
|
+
* resolution error instead of throwing. ADR 0002: acquires this workflow's
|
|
9
|
+
* claim standalone + hydrates cleanup tracking BEFORE failing — the
|
|
10
|
+
* happy-path pending→running fold later in `startDelayedWorkflow` would
|
|
11
|
+
* otherwise establish both.
|
|
12
|
+
*
|
|
13
|
+
* Resolved against `revision` — the pending run's own persisted
|
|
14
|
+
* `WorkflowState.revision` (WFT-17), `undefined` for a legacy record —
|
|
15
|
+
* never the catalog's active pointer, so a delayed-start fire honors the
|
|
16
|
+
* exact revision this run was created against, matching
|
|
17
|
+
* `resumeWorkflowFromStorage()`'s use of the same resolver.
|
|
18
|
+
*
|
|
19
|
+
* Returns the FULL `{ entry, revision }` pair, not just `entry` — mirroring
|
|
20
|
+
* `resolveExecutableRegistrationOrRenamedNotFound()`'s shape used by
|
|
21
|
+
* `resume.ts`/`transition.ts`. For a legacy, pre-revision-pinning pending
|
|
22
|
+
* record with exactly one registered `registerSource()` candidate, the
|
|
23
|
+
* resolver can unambiguously resolve that candidate even though the input
|
|
24
|
+
* `revision` was `undefined` — the caller MUST thread this returned
|
|
25
|
+
* `revision` (not the input `revision` or the persisted state's own,
|
|
26
|
+
* still-`undefined` `revision`) through the pending→running transition and
|
|
27
|
+
* into `beginWorkflowExecution`, or the per-instance identity cache ends up
|
|
28
|
+
* stamped with the wrong (missing) revision (WFT-19 review round 7).
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolveDelayedStartRegistrationOrFail(internals: EngineInternals, entry: TimerEntry, type: string, revision: string | undefined, callbacks: Pick<TimeOperationCallbacks, 'failWorkflow' | 'resolveExecutableRegistrationForRevision'>): Promise<ExecutableRegistration | null>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ensureDelayedStartClaimAndCleanupBeforeFailure } from "./standalone-claim-acquire.js";
|
|
2
|
+
export async function resolveDelayedStartRegistrationOrFail(internals, entry, type, revision, callbacks) {
|
|
3
|
+
try {
|
|
4
|
+
return await callbacks.resolveExecutableRegistrationForRevision(type, revision);
|
|
5
|
+
} catch (error) {
|
|
6
|
+
await ensureDelayedStartClaimAndCleanupBeforeFailure(internals, entry.workflowId);
|
|
7
|
+
const asError = error instanceof Error ? error : Error(String(error));
|
|
8
|
+
await callbacks.failWorkflow(entry.workflowId, asError);
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -5,5 +5,37 @@ import type { EngineInternals } from '../internals.ts';
|
|
|
5
5
|
import { type LifecycleCallbacks } from './shared.ts';
|
|
6
6
|
export declare function createForkLineage(_internals: EngineInternals, sourceWorkflowId: string, checkpoint: Checkpoint, _callbacks: LifecycleCallbacks): ForkLineage;
|
|
7
7
|
export declare function buildForkSearchAttributes(_internals: EngineInternals, checkpoint: Checkpoint, lineage: ForkLineage, _callbacks: LifecycleCallbacks): Record<string, SearchAttributeValue>;
|
|
8
|
-
export declare function createForkedWorkflowState(_internals: EngineInternals, workflowId: string, sourceState: WorkflowState, versionTuple: WorkflowVersionTuple, lineage: ForkLineage, forkedAt: number, _callbacks: LifecycleCallbacks
|
|
8
|
+
export declare function createForkedWorkflowState(_internals: EngineInternals, workflowId: string, sourceState: WorkflowState, versionTuple: WorkflowVersionTuple, lineage: ForkLineage, forkedAt: number, _callbacks: LifecycleCallbacks,
|
|
9
|
+
/**
|
|
10
|
+
* `fork()`'s own resolver-returned revision — used to fill in the fork's
|
|
11
|
+
* persisted `revision` ONLY when `sourceState.revision` is itself
|
|
12
|
+
* `undefined` (WFT-19 review round 6, Codex, P1). Never overrides an
|
|
13
|
+
* already-defined `sourceState.revision`: `resolveExecutableRegistrationForRevision()`
|
|
14
|
+
* ALWAYS returns `revision: undefined` for an eager registration (eager
|
|
15
|
+
* has no ambiguity to resolve against — see `canResolveRevisionLocally`'s
|
|
16
|
+
* doc), even though the eager source run's own `sourceState.revision` is
|
|
17
|
+
* a real, independently-meaningful value (`resolveCachedStartRevision()`'s
|
|
18
|
+
* `registeredCatalogRevisions` fallback stamps it at ordinary start time,
|
|
19
|
+
* for every registration kind). Blindly preferring `resolvedRevision`
|
|
20
|
+
* here would have dropped that real value for every eager-type fork —
|
|
21
|
+
* caught by `tests/replay-fixtures/fork-from-checkpoint.json`'s golden
|
|
22
|
+
* byte comparison. For a legacy (pre-revision-pinning) source run on a
|
|
23
|
+
* dynamic-source type with exactly one registered candidate,
|
|
24
|
+
* `sourceState.revision` genuinely IS `undefined` even though the
|
|
25
|
+
* resolver resolved — and the fork launches against — that sole
|
|
26
|
+
* candidate's code; `sourceState.revision ?? resolvedRevision` falls
|
|
27
|
+
* through to the resolver's answer only in that case. Stamping the fork's
|
|
28
|
+
* persisted `revision` with the raw `undefined` legacy pin (as this
|
|
29
|
+
* function did before this fix existed) left the fork durably unpinned:
|
|
30
|
+
* it would run correctly until the next restart, but a fresh-process
|
|
31
|
+
* `recoverAll()` after a second candidate is later registered would
|
|
32
|
+
* classify the fork `legacy-ambiguous` and refuse to resume it, even
|
|
33
|
+
* though the fork's own resolver already knew exactly which revision it
|
|
34
|
+
* belonged to at creation time. Mirrors the identical fix already applied
|
|
35
|
+
* to the process-local identity cache in `checkpoint-launch.ts`'s
|
|
36
|
+
* `launchWorkflowFromCheckpoint()` (WFT-19 review round 5) — that fix
|
|
37
|
+
* closed the in-memory gap; this one closes the matching durable-state
|
|
38
|
+
* gap the same bug left behind, for the one case it actually applies to.
|
|
39
|
+
*/
|
|
40
|
+
resolvedRevision: string | undefined): WorkflowState;
|
|
9
41
|
export declare function buildForkBatchOperations(_internals: EngineInternals, workflowId: string, state: WorkflowState, checkpoint: Checkpoint, serializedCheckpoint: Uint8Array, workflowStartHeaders: Map<string, string> | undefined, _callbacks: LifecycleCallbacks): BatchOperation[];
|
|
@@ -16,7 +16,8 @@ export function buildForkSearchAttributes(_internals, checkpoint, lineage, _call
|
|
|
16
16
|
[FORK_LINEAGE_ATTRIBUTE]: lineage.workflowId
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
|
-
export function createForkedWorkflowState(_internals, workflowId, sourceState, versionTuple, lineage, forkedAt, _callbacks) {
|
|
19
|
+
export function createForkedWorkflowState(_internals, workflowId, sourceState, versionTuple, lineage, forkedAt, _callbacks, resolvedRevision) {
|
|
20
|
+
const forkRevision = sourceState.revision ?? resolvedRevision;
|
|
20
21
|
return {
|
|
21
22
|
id: workflowId,
|
|
22
23
|
type: sourceState.type,
|
|
@@ -24,6 +25,7 @@ export function createForkedWorkflowState(_internals, workflowId, sourceState, v
|
|
|
24
25
|
input: sourceState.input,
|
|
25
26
|
workflowExecutionToken: crypto.randomUUID(),
|
|
26
27
|
versionTuple,
|
|
28
|
+
...forkRevision !== void 0 && { revision: forkRevision },
|
|
27
29
|
executionStateOwnerId: workflowId,
|
|
28
30
|
createdAt: forkedAt,
|
|
29
31
|
startedAt: forkedAt,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `recoverAll()`'s per-entry error isolation — split out of `transition.ts`,
|
|
3
|
+
* which has no headroom under this repository's 500-line implementation-file
|
|
4
|
+
* ceiling for the WFT-134 claim-release wrapping `recoverEntryOrIsolateFailure`
|
|
5
|
+
* needed (mirrors `resume-body.ts`'s same split). This file's own job is just
|
|
6
|
+
* the branch-matching: given the error `resume()` rejected with, either
|
|
7
|
+
* isolate it to just this workflow (returning `null`) or rethrow it.
|
|
8
|
+
*
|
|
9
|
+
* @module core/engine/lifecycle/recovery-isolation
|
|
10
|
+
*/
|
|
11
|
+
import type { WorkflowHandle } from '../handles.ts';
|
|
12
|
+
import type { LifecycleCallbacks, RecoverAllOptions } from './shared.ts';
|
|
13
|
+
/**
|
|
14
|
+
* Isolate one `recoverAll()` entry's failure to just this workflow when it
|
|
15
|
+
* matches a known-recoverable error, committing the matching `failWorkflowForXxx`
|
|
16
|
+
* fenced write; rethrows anything else, including an opted-in
|
|
17
|
+
* `VersionMismatchError` throw. See `transition.ts`'s `recoverEntryOrIsolateFailure`
|
|
18
|
+
* for the caller-side claim-release wrapping around this.
|
|
19
|
+
*/
|
|
20
|
+
export declare function isolateRecoveryFailure(workflowId: string, callbacks: LifecycleCallbacks, options: RecoverAllOptions | undefined, error: unknown): Promise<WorkflowHandle | null>;
|