ai-workflows 2.1.1 → 2.3.0
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +17 -1
- package/README.md +305 -184
- package/dist/barrier.d.ts +159 -0
- package/dist/barrier.d.ts.map +1 -0
- package/dist/barrier.js +377 -0
- package/dist/barrier.js.map +1 -0
- package/dist/cascade-context.d.ts +149 -0
- package/dist/cascade-context.d.ts.map +1 -0
- package/dist/cascade-context.js +324 -0
- package/dist/cascade-context.js.map +1 -0
- package/dist/cascade-executor.d.ts +196 -0
- package/dist/cascade-executor.d.ts.map +1 -0
- package/dist/cascade-executor.js +384 -0
- package/dist/cascade-executor.js.map +1 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +27 -8
- package/dist/context.js.map +1 -1
- package/dist/cron-parser.d.ts +65 -0
- package/dist/cron-parser.d.ts.map +1 -0
- package/dist/cron-parser.js +294 -0
- package/dist/cron-parser.js.map +1 -0
- package/dist/cron-scheduler.d.ts +117 -0
- package/dist/cron-scheduler.d.ts.map +1 -0
- package/dist/cron-scheduler.js +176 -0
- package/dist/cron-scheduler.js.map +1 -0
- package/dist/database-context.d.ts +184 -0
- package/dist/database-context.d.ts.map +1 -0
- package/dist/database-context.js +428 -0
- package/dist/database-context.js.map +1 -0
- package/dist/dependency-graph.d.ts +157 -0
- package/dist/dependency-graph.d.ts.map +1 -0
- package/dist/dependency-graph.js +382 -0
- package/dist/dependency-graph.js.map +1 -0
- package/dist/digital-objects-adapter.d.ts +159 -0
- package/dist/digital-objects-adapter.d.ts.map +1 -0
- package/dist/digital-objects-adapter.js +229 -0
- package/dist/digital-objects-adapter.js.map +1 -0
- package/dist/durable-execution-cloudflare.d.ts +427 -0
- package/dist/durable-execution-cloudflare.d.ts.map +1 -0
- package/dist/durable-execution-cloudflare.js +510 -0
- package/dist/durable-execution-cloudflare.js.map +1 -0
- package/dist/durable-execution.d.ts +482 -0
- package/dist/durable-execution.d.ts.map +1 -0
- package/dist/durable-execution.js +594 -0
- package/dist/durable-execution.js.map +1 -0
- package/dist/durable-workflow.d.ts +176 -0
- package/dist/durable-workflow.d.ts.map +1 -0
- package/dist/durable-workflow.js +552 -0
- package/dist/durable-workflow.js.map +1 -0
- package/dist/every.d.ts +31 -2
- package/dist/every.d.ts.map +1 -1
- package/dist/every.js +63 -32
- package/dist/every.js.map +1 -1
- package/dist/graph/index.d.ts +8 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +8 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/topological-sort.d.ts +121 -0
- package/dist/graph/topological-sort.d.ts.map +1 -0
- package/dist/graph/topological-sort.js +292 -0
- package/dist/graph/topological-sort.js.map +1 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +101 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +115 -0
- package/dist/logger.js.map +1 -0
- package/dist/on.d.ts +35 -10
- package/dist/on.d.ts.map +1 -1
- package/dist/on.js +53 -19
- package/dist/on.js.map +1 -1
- package/dist/runtime.d.ts +169 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +275 -0
- package/dist/runtime.js.map +1 -0
- package/dist/send.d.ts.map +1 -1
- package/dist/send.js +4 -3
- package/dist/send.js.map +1 -1
- package/dist/telemetry.d.ts +150 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +388 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/timer-registry.d.ts +77 -0
- package/dist/timer-registry.d.ts.map +1 -0
- package/dist/timer-registry.js +154 -0
- package/dist/timer-registry.js.map +1 -0
- package/dist/types.d.ts +105 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +17 -1
- package/dist/types.js.map +1 -1
- package/dist/worker/durable-step.d.ts +481 -0
- package/dist/worker/durable-step.d.ts.map +1 -0
- package/dist/worker/durable-step.js +606 -0
- package/dist/worker/durable-step.js.map +1 -0
- package/dist/worker/index.d.ts +106 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/index.js +124 -0
- package/dist/worker/index.js.map +1 -0
- package/dist/worker/state-adapter.d.ts +230 -0
- package/dist/worker/state-adapter.d.ts.map +1 -0
- package/dist/worker/state-adapter.js +409 -0
- package/dist/worker/state-adapter.js.map +1 -0
- package/dist/worker/topological-executor.d.ts +282 -0
- package/dist/worker/topological-executor.d.ts.map +1 -0
- package/dist/worker/topological-executor.js +396 -0
- package/dist/worker/topological-executor.js.map +1 -0
- package/dist/worker/workflow-builder.d.ts +286 -0
- package/dist/worker/workflow-builder.d.ts.map +1 -0
- package/dist/worker/workflow-builder.js +565 -0
- package/dist/worker/workflow-builder.js.map +1 -0
- package/dist/worker.d.ts +800 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +2428 -0
- package/dist/worker.js.map +1 -0
- package/dist/workflow-builder.d.ts +287 -0
- package/dist/workflow-builder.d.ts.map +1 -0
- package/dist/workflow-builder.js +762 -0
- package/dist/workflow-builder.js.map +1 -0
- package/dist/workflow.d.ts +14 -30
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +136 -292
- package/dist/workflow.js.map +1 -1
- package/examples/01-ecommerce-order-pipeline.ts +358 -0
- package/examples/02-content-moderation-cascade.ts +454 -0
- package/examples/03-scheduled-reporting-dependencies.ts +479 -0
- package/examples/04-database-persistence.ts +518 -0
- package/examples/README.md +173 -0
- package/package.json +21 -4
- package/src/__tests__/digital-objects-adapter.test.ts +274 -0
- package/src/__tests__/durable-workflow.test.ts +297 -0
- package/src/barrier.ts +507 -0
- package/src/cascade-context.ts +495 -0
- package/src/cascade-executor.ts +588 -0
- package/src/context.ts +51 -17
- package/src/cron-parser.ts +347 -0
- package/src/cron-scheduler.ts +239 -0
- package/src/database-context.ts +658 -0
- package/src/dependency-graph.ts +518 -0
- package/src/digital-objects-adapter.ts +351 -0
- package/src/durable-execution-cloudflare.ts +855 -0
- package/src/durable-execution.ts +1042 -0
- package/src/durable-workflow.ts +717 -0
- package/src/every.ts +104 -35
- package/src/graph/index.ts +19 -0
- package/src/graph/topological-sort.ts +412 -0
- package/src/index.ts +147 -0
- package/src/logger.ts +148 -0
- package/src/on.ts +81 -26
- package/src/runtime.ts +436 -0
- package/src/send.ts +4 -5
- package/src/telemetry.ts +577 -0
- package/src/timer-registry.ts +179 -0
- package/src/types.ts +146 -10
- package/src/worker/durable-step.ts +976 -0
- package/src/worker/index.ts +216 -0
- package/src/worker/state-adapter.ts +589 -0
- package/src/worker/topological-executor.ts +625 -0
- package/src/worker/workflow-builder.ts +871 -0
- package/src/worker.ts +2906 -0
- package/src/workflow-builder.ts +1068 -0
- package/src/workflow.ts +199 -355
- package/test/barrier-join.test.ts +442 -0
- package/test/barrier-unhandled-rejections.test.ts +359 -0
- package/test/cascade-context.test.ts +390 -0
- package/test/cascade-executor.test.ts +852 -0
- package/test/cron-parser.test.ts +314 -0
- package/test/cron-scheduler.test.ts +291 -0
- package/test/database-context.test.ts +770 -0
- package/test/db-provider-adapter.test.ts +862 -0
- package/test/dependency-graph.test.ts +512 -0
- package/test/durable-execution-cloudflare.test.ts +606 -0
- package/test/durable-execution-in-process.test.ts +286 -0
- package/test/durable-execution.test.ts +247 -0
- package/test/e2e/workflow-scenarios.e2e.test.ts +1039 -0
- package/test/graph/topological-sort.test.ts +586 -0
- package/test/integration.test.ts +442 -0
- package/test/rpc-surface.test.ts +946 -0
- package/test/runtime.test.ts +262 -0
- package/test/schedule-timer-cleanup.test.ts +353 -0
- package/test/send-race-conditions.test.ts +400 -0
- package/test/type-safety-every.test.ts +303 -0
- package/test/worker/durable-cascade.test.ts +1117 -0
- package/test/worker/durable-step.test.ts +723 -0
- package/test/worker/topological-executor.test.ts +1240 -0
- package/test/worker/workflow-builder.test.ts +1067 -0
- package/test/worker.test.ts +608 -0
- package/test/workflow-builder.test.ts +1670 -0
- package/test/workflow-cron.test.ts +256 -0
- package/test/workflow-state-adapter.test.ts +923 -0
- package/test/workflow.test.ts +25 -22
- package/tsconfig.json +3 -1
- package/vitest.config.ts +38 -1
- package/vitest.workers.config.ts +44 -0
- package/wrangler.jsonc +22 -0
- package/.turbo/turbo-test.log +0 -7
- package/src/context.js +0 -83
- package/src/every.js +0 -267
- package/src/index.js +0 -71
- package/src/on.js +0 -79
- package/src/send.js +0 -111
- package/src/types.js +0 -4
- package/src/workflow.js +0 -455
- package/test/context.test.js +0 -116
- package/test/every.test.js +0 -282
- package/test/on.test.js +0 -80
- package/test/send.test.js +0 -89
- package/test/workflow.test.js +0 -224
- package/vitest.config.js +0 -7
|
@@ -0,0 +1,594 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DurableExecutionAdapter - Port for durable workflow execution backends.
|
|
3
|
+
*
|
|
4
|
+
* Defines a small, backend-agnostic interface that callers (notably
|
|
5
|
+
* `ai-database`'s cascade orchestration in ADR-0003) can program against
|
|
6
|
+
* without knowing which durable execution backend is wired underneath.
|
|
7
|
+
*
|
|
8
|
+
* ## Why this port exists
|
|
9
|
+
*
|
|
10
|
+
* `ai-workflows`'s {@link createWorkflowRuntime} owns the `$` runtime
|
|
11
|
+
* contract — handlers, dispatch, cascade-context, database-context. It runs
|
|
12
|
+
* in-process and lives only as long as the host process. For long-running
|
|
13
|
+
* cascades, scheduled jobs, and orchestration spanning hours-to-days, an
|
|
14
|
+
* external durable execution backend is required.
|
|
15
|
+
*
|
|
16
|
+
* Two production candidates (per ADR-0004):
|
|
17
|
+
*
|
|
18
|
+
* - **Cloudflare Workflows** (default backend; Workers-only). Hibernation
|
|
19
|
+
* while waiting; no per-step billing; 25K steps default; 365-day max
|
|
20
|
+
* sleep. State must flow through step returns — in-memory variables do
|
|
21
|
+
* not survive hibernation.
|
|
22
|
+
*
|
|
23
|
+
* - **Vercel Workflow Development Kit (WDK)** (alternate backend; Vercel
|
|
24
|
+
* or self-hosted). Apache-2.0; pluggable "Worlds"; per-step billing;
|
|
25
|
+
* event-sourced replay; unlimited sleep.
|
|
26
|
+
*
|
|
27
|
+
* Plus an in-process stub (this file's {@link createInMemoryDurableExecution})
|
|
28
|
+
* for tests and local development that does not need durability across
|
|
29
|
+
* process restarts. Phase 1 (bead `aip-fgq5`) will land a richer in-process
|
|
30
|
+
* adapter that bridges this port to the existing
|
|
31
|
+
* {@link createWorkflowRuntime}.
|
|
32
|
+
*
|
|
33
|
+
* The port is modeled after WDK's "Worlds" abstraction — the prior art for
|
|
34
|
+
* exactly this pattern: a small, backend-portable surface for `step`,
|
|
35
|
+
* `sleep`, `waitForEvent`, and scheduling, with each adapter translating to
|
|
36
|
+
* its native primitive (CF's hibernation, WDK's event-sourced replay,
|
|
37
|
+
* in-process's plain async).
|
|
38
|
+
*
|
|
39
|
+
* ## Programming model: Rules of Workflows
|
|
40
|
+
*
|
|
41
|
+
* These rules are universal to durable execution and are not specific to
|
|
42
|
+
* any one backend. They originate in CF's "Rules of Workflows" guidance and
|
|
43
|
+
* apply equally to WDK's deterministic replay model.
|
|
44
|
+
*
|
|
45
|
+
* 1. **Steps must be idempotent.** A step body may be re-executed across
|
|
46
|
+
* a hibernation/restart boundary or after a transient failure. Wrap
|
|
47
|
+
* external side-effects (writes, payments, emails) so a duplicate
|
|
48
|
+
* invocation is observably equivalent to a single invocation.
|
|
49
|
+
*
|
|
50
|
+
* 2. **Step names must be deterministic.** Adapters use the step name as
|
|
51
|
+
* a stable identity for memoization and event-sourced replay. Do not
|
|
52
|
+
* include random ids, timestamps, or run-specific values in the name.
|
|
53
|
+
*
|
|
54
|
+
* 3. **State flows through step returns.** Variables defined inside a
|
|
55
|
+
* workflow body but outside a step are not guaranteed to survive a
|
|
56
|
+
* hibernation boundary. Read inputs at the top of a step; return only
|
|
57
|
+
* what you need; pass results forward through subsequent steps.
|
|
58
|
+
*
|
|
59
|
+
* 4. **Workflow bodies must be deterministic.** Two replays of the same
|
|
60
|
+
* input must take the same control-flow path. Push non-determinism
|
|
61
|
+
* (clocks, randomness, network reads) into steps so the adapter can
|
|
62
|
+
* memoize the result.
|
|
63
|
+
*
|
|
64
|
+
* 5. **Sleeps and waits are first-class.** Use
|
|
65
|
+
* {@link DurableExecutionAdapter.sleep},
|
|
66
|
+
* {@link DurableExecutionAdapter.sleepUntil}, and
|
|
67
|
+
* {@link DurableExecutionAdapter.waitForEvent} rather than `setTimeout`
|
|
68
|
+
* or polling — only the adapter knows how to suspend and resume the
|
|
69
|
+
* workflow correctly.
|
|
70
|
+
*
|
|
71
|
+
* ## Error semantics
|
|
72
|
+
*
|
|
73
|
+
* - {@link DurableStepError} (and its subclasses) are thrown by step
|
|
74
|
+
* execution failures. The {@link DurableStepError.retryable} flag tells
|
|
75
|
+
* the caller whether the adapter considered the failure transient. Real
|
|
76
|
+
* adapters surface their backend's retry decisions through this flag.
|
|
77
|
+
*
|
|
78
|
+
* - {@link WaitForEventTimeoutError} is thrown by
|
|
79
|
+
* {@link DurableExecutionAdapter.waitForEvent} when a timeout elapses
|
|
80
|
+
* without the named event arriving. Callers should catch this explicitly
|
|
81
|
+
* to model "happens within N" branches.
|
|
82
|
+
*
|
|
83
|
+
* - All other thrown errors propagate as-is. Callers must classify
|
|
84
|
+
* non-retryable business errors themselves; adapters do not introspect
|
|
85
|
+
* user errors.
|
|
86
|
+
*
|
|
87
|
+
* ## Subpath export
|
|
88
|
+
*
|
|
89
|
+
* This module ships at the `ai-workflows/durable-execution` subpath so the
|
|
90
|
+
* cascade orchestrator (in `ai-database`) can depend on the port without
|
|
91
|
+
* pulling in the full `ai-workflows` runtime — keeping the static dependency
|
|
92
|
+
* graph one-way (`ai-database` → `ai-workflows/durable-execution`).
|
|
93
|
+
*
|
|
94
|
+
* @example In-memory test usage
|
|
95
|
+
* ```ts
|
|
96
|
+
* import { createInMemoryDurableExecution } from 'ai-workflows/durable-execution'
|
|
97
|
+
*
|
|
98
|
+
* const dx = createInMemoryDurableExecution()
|
|
99
|
+
* const result = await dx.run('charge-customer', async (ctx) => {
|
|
100
|
+
* const charged = await ctx.step('charge-card', async () => {
|
|
101
|
+
* return chargeStripe(ctx.input)
|
|
102
|
+
* })
|
|
103
|
+
* await ctx.sleep('1 second')
|
|
104
|
+
* return { id: charged.id }
|
|
105
|
+
* }, { customerId: 'c-1', amount: 1000 })
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* @example Wiring a real adapter (future Phase 1; bead aip-fgq5/aip-i456)
|
|
109
|
+
* ```ts
|
|
110
|
+
* import type { DurableExecutionAdapter } from 'ai-workflows/durable-execution'
|
|
111
|
+
*
|
|
112
|
+
* function makeCascadeRunner(dx: DurableExecutionAdapter) {
|
|
113
|
+
* return (input: CascadeInput) => dx.run('cascade', async (ctx) => {
|
|
114
|
+
* const plan = await ctx.step('plan', () => generatePlan(ctx.input))
|
|
115
|
+
* return ctx.step('write', () => writeAll(plan))
|
|
116
|
+
* }, input)
|
|
117
|
+
* }
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* @packageDocumentation
|
|
121
|
+
*/
|
|
122
|
+
import { recordStep } from './cascade-context.js';
|
|
123
|
+
import { getLogger } from './logger.js';
|
|
124
|
+
// =============================================================================
|
|
125
|
+
// Error types
|
|
126
|
+
// =============================================================================
|
|
127
|
+
/**
|
|
128
|
+
* Thrown when a step's body fails after all retries (or immediately, when
|
|
129
|
+
* retries are not configured).
|
|
130
|
+
*
|
|
131
|
+
* The {@link DurableStepError.retryable} flag reflects the adapter's
|
|
132
|
+
* judgement about the underlying failure: `true` means the adapter believed
|
|
133
|
+
* the failure was transient (network, rate-limit, server error) and would
|
|
134
|
+
* have retried again given more attempts; `false` means the adapter
|
|
135
|
+
* classified it as terminal (programmer error, invalid input). Callers can
|
|
136
|
+
* use this to decide whether to escalate or fall through to a different
|
|
137
|
+
* code path.
|
|
138
|
+
*/
|
|
139
|
+
export class DurableStepError extends Error {
|
|
140
|
+
/** Step name that failed. */
|
|
141
|
+
stepName;
|
|
142
|
+
/** Number of attempts the adapter actually made (>= 1). */
|
|
143
|
+
attempts;
|
|
144
|
+
/** Whether the adapter considered the cause transient. */
|
|
145
|
+
retryable;
|
|
146
|
+
/** The error that ultimately caused the failure. */
|
|
147
|
+
cause;
|
|
148
|
+
constructor(message, options) {
|
|
149
|
+
super(message);
|
|
150
|
+
this.name = 'DurableStepError';
|
|
151
|
+
this.stepName = options.stepName;
|
|
152
|
+
this.attempts = options.attempts;
|
|
153
|
+
this.retryable = options.retryable;
|
|
154
|
+
this.cause = options.cause;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Thrown when {@link DurableExecutionAdapter.waitForEvent} elapses without
|
|
159
|
+
* the named event arriving.
|
|
160
|
+
*/
|
|
161
|
+
export class WaitForEventTimeoutError extends Error {
|
|
162
|
+
eventName;
|
|
163
|
+
timeout;
|
|
164
|
+
constructor(eventName, timeout) {
|
|
165
|
+
super(`Timed out waiting for event "${eventName}" after ${String(timeout)}`);
|
|
166
|
+
this.name = 'WaitForEventTimeoutError';
|
|
167
|
+
this.eventName = eventName;
|
|
168
|
+
this.timeout = timeout;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Internal: parse human-readable durations like `'1 second'`, `'500ms'`,
|
|
173
|
+
* `'5 minutes'` into milliseconds. The supported grammar is small on
|
|
174
|
+
* purpose; real backends define their own. Numbers pass through.
|
|
175
|
+
*/
|
|
176
|
+
function parseDuration(input) {
|
|
177
|
+
if (typeof input === 'number')
|
|
178
|
+
return input;
|
|
179
|
+
const trimmed = input.trim().toLowerCase();
|
|
180
|
+
const match = trimmed.match(/^(\d+(?:\.\d+)?)\s*(ms|millisecond|milliseconds|s|sec|second|seconds|m|min|minute|minutes|h|hr|hour|hours|d|day|days)$/);
|
|
181
|
+
if (!match) {
|
|
182
|
+
throw new Error(`Unrecognised duration: "${input}"`);
|
|
183
|
+
}
|
|
184
|
+
const value = parseFloat(match[1]);
|
|
185
|
+
const unit = match[2];
|
|
186
|
+
switch (unit) {
|
|
187
|
+
case 'ms':
|
|
188
|
+
case 'millisecond':
|
|
189
|
+
case 'milliseconds':
|
|
190
|
+
return value;
|
|
191
|
+
case 's':
|
|
192
|
+
case 'sec':
|
|
193
|
+
case 'second':
|
|
194
|
+
case 'seconds':
|
|
195
|
+
return value * 1000;
|
|
196
|
+
case 'm':
|
|
197
|
+
case 'min':
|
|
198
|
+
case 'minute':
|
|
199
|
+
case 'minutes':
|
|
200
|
+
return value * 60_000;
|
|
201
|
+
case 'h':
|
|
202
|
+
case 'hr':
|
|
203
|
+
case 'hour':
|
|
204
|
+
case 'hours':
|
|
205
|
+
return value * 3_600_000;
|
|
206
|
+
case 'd':
|
|
207
|
+
case 'day':
|
|
208
|
+
case 'days':
|
|
209
|
+
return value * 86_400_000;
|
|
210
|
+
/* istanbul ignore next */
|
|
211
|
+
default:
|
|
212
|
+
throw new Error(`Unrecognised duration unit: "${unit}"`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/** Internal: compute backoff delay for retry attempt n (1-based). */
|
|
216
|
+
function computeBackoff(config, attempt) {
|
|
217
|
+
const baseMs = config.delay !== undefined ? parseDuration(config.delay) : 0;
|
|
218
|
+
const strategy = config.backoff ?? 'constant';
|
|
219
|
+
switch (strategy) {
|
|
220
|
+
case 'constant':
|
|
221
|
+
return baseMs;
|
|
222
|
+
case 'linear':
|
|
223
|
+
return baseMs * attempt;
|
|
224
|
+
case 'exponential':
|
|
225
|
+
return baseMs * Math.pow(2, attempt - 1);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* @see InMemoryDurableExecution
|
|
230
|
+
*/
|
|
231
|
+
export function createInMemoryDurableExecution(options = {}) {
|
|
232
|
+
const now = options.now ?? (() => Date.now());
|
|
233
|
+
const delay = options.delay ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
234
|
+
// Per-run memoization is keyed by the surrounding run's instanceId. Calls
|
|
235
|
+
// outside of a run get an `undefined` key (single shared bucket).
|
|
236
|
+
const runMemo = new Map();
|
|
237
|
+
// Active event waiters, FIFO per event name.
|
|
238
|
+
const waiters = new Map();
|
|
239
|
+
// Active scheduled intervals, by subscription id.
|
|
240
|
+
const schedules = new Map();
|
|
241
|
+
let scheduleSeq = 0;
|
|
242
|
+
let runSeq = 0;
|
|
243
|
+
const runStack = [];
|
|
244
|
+
const currentRun = () => runStack[runStack.length - 1];
|
|
245
|
+
async function executeStep(name, config, fn) {
|
|
246
|
+
const frame = currentRun();
|
|
247
|
+
const bucketKey = frame?.instanceId;
|
|
248
|
+
let bucket = runMemo.get(bucketKey);
|
|
249
|
+
if (!bucket) {
|
|
250
|
+
bucket = new Map();
|
|
251
|
+
runMemo.set(bucketKey, bucket);
|
|
252
|
+
}
|
|
253
|
+
if (bucket.has(name)) {
|
|
254
|
+
return bucket.get(name);
|
|
255
|
+
}
|
|
256
|
+
const retries = config?.retries;
|
|
257
|
+
const maxAttempts = retries?.limit ?? 1;
|
|
258
|
+
let lastErr;
|
|
259
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
260
|
+
try {
|
|
261
|
+
const result = await fn();
|
|
262
|
+
bucket.set(name, result);
|
|
263
|
+
return result;
|
|
264
|
+
}
|
|
265
|
+
catch (err) {
|
|
266
|
+
lastErr = err;
|
|
267
|
+
if (attempt < maxAttempts && retries) {
|
|
268
|
+
const wait = computeBackoff(retries, attempt);
|
|
269
|
+
if (wait > 0)
|
|
270
|
+
await delay(wait);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
throw new DurableStepError(`Step "${name}" failed after ${maxAttempts} attempt(s)`, {
|
|
275
|
+
stepName: name,
|
|
276
|
+
attempts: maxAttempts,
|
|
277
|
+
retryable: true,
|
|
278
|
+
cause: lastErr,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
async function sleep(duration) {
|
|
282
|
+
const ms = parseDuration(duration);
|
|
283
|
+
if (ms > 0)
|
|
284
|
+
await delay(ms);
|
|
285
|
+
}
|
|
286
|
+
async function sleepUntil(date) {
|
|
287
|
+
const ms = date.getTime() - now();
|
|
288
|
+
if (ms > 0)
|
|
289
|
+
await delay(ms);
|
|
290
|
+
}
|
|
291
|
+
function waitForEvent(name, timeout) {
|
|
292
|
+
return new Promise((resolve, reject) => {
|
|
293
|
+
const queue = waiters.get(name) ?? [];
|
|
294
|
+
const waiter = {
|
|
295
|
+
resolve: (v) => resolve(v),
|
|
296
|
+
reject,
|
|
297
|
+
};
|
|
298
|
+
queue.push(waiter);
|
|
299
|
+
waiters.set(name, queue);
|
|
300
|
+
if (timeout !== undefined) {
|
|
301
|
+
const ms = parseDuration(timeout);
|
|
302
|
+
const timer = setTimeout(() => {
|
|
303
|
+
const q = waiters.get(name);
|
|
304
|
+
if (!q)
|
|
305
|
+
return;
|
|
306
|
+
const idx = q.indexOf(waiter);
|
|
307
|
+
if (idx >= 0) {
|
|
308
|
+
q.splice(idx, 1);
|
|
309
|
+
if (q.length === 0)
|
|
310
|
+
waiters.delete(name);
|
|
311
|
+
reject(new WaitForEventTimeoutError(name, timeout));
|
|
312
|
+
}
|
|
313
|
+
}, ms);
|
|
314
|
+
// Don't keep the process alive solely for a wait timeout.
|
|
315
|
+
if (typeof timer.unref === 'function') {
|
|
316
|
+
;
|
|
317
|
+
timer.unref();
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
function emit(name, value) {
|
|
323
|
+
const queue = waiters.get(name);
|
|
324
|
+
if (!queue || queue.length === 0)
|
|
325
|
+
return false;
|
|
326
|
+
const waiter = queue.shift();
|
|
327
|
+
if (queue.length === 0)
|
|
328
|
+
waiters.delete(name);
|
|
329
|
+
waiter.resolve(value);
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
function schedule(name, cron, fn) {
|
|
333
|
+
const id = `sched-${++scheduleSeq}`;
|
|
334
|
+
// The stub does not parse cron — it fires every second. Tests that
|
|
335
|
+
// need precise timing should drive runs manually rather than rely on
|
|
336
|
+
// the stub's scheduler. Real adapters honour the cron expression.
|
|
337
|
+
void cron;
|
|
338
|
+
void name;
|
|
339
|
+
const handle = setInterval(() => {
|
|
340
|
+
void adapter.run(name, fn, undefined).catch(() => {
|
|
341
|
+
// Schedule errors are swallowed; the stub has nowhere to surface
|
|
342
|
+
// them. Real adapters log/persist failures.
|
|
343
|
+
});
|
|
344
|
+
}, 1000);
|
|
345
|
+
if (typeof handle.unref === 'function') {
|
|
346
|
+
;
|
|
347
|
+
handle.unref();
|
|
348
|
+
}
|
|
349
|
+
schedules.set(id, handle);
|
|
350
|
+
return {
|
|
351
|
+
id,
|
|
352
|
+
unsubscribe() {
|
|
353
|
+
const h = schedules.get(id);
|
|
354
|
+
if (h) {
|
|
355
|
+
clearInterval(h);
|
|
356
|
+
schedules.delete(id);
|
|
357
|
+
}
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
async function run(name, fn, input) {
|
|
362
|
+
const instanceId = `run-${++runSeq}`;
|
|
363
|
+
const frame = { instanceId };
|
|
364
|
+
runStack.push(frame);
|
|
365
|
+
const ctx = {
|
|
366
|
+
input,
|
|
367
|
+
instanceId,
|
|
368
|
+
name,
|
|
369
|
+
step: ((stepName, configOrFn, maybeFn) => {
|
|
370
|
+
if (typeof configOrFn === 'function') {
|
|
371
|
+
return executeStep(stepName, undefined, configOrFn);
|
|
372
|
+
}
|
|
373
|
+
return executeStep(stepName, configOrFn, maybeFn);
|
|
374
|
+
}),
|
|
375
|
+
sleep,
|
|
376
|
+
sleepUntil,
|
|
377
|
+
waitForEvent,
|
|
378
|
+
};
|
|
379
|
+
try {
|
|
380
|
+
return await fn(ctx);
|
|
381
|
+
}
|
|
382
|
+
finally {
|
|
383
|
+
runStack.pop();
|
|
384
|
+
runMemo.delete(instanceId);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
const adapter = {
|
|
388
|
+
kind: 'in-process',
|
|
389
|
+
run,
|
|
390
|
+
step: ((name, configOrFn, maybeFn) => {
|
|
391
|
+
if (typeof configOrFn === 'function') {
|
|
392
|
+
return executeStep(name, undefined, configOrFn);
|
|
393
|
+
}
|
|
394
|
+
return executeStep(name, configOrFn, maybeFn);
|
|
395
|
+
}),
|
|
396
|
+
sleep,
|
|
397
|
+
sleepUntil,
|
|
398
|
+
waitForEvent,
|
|
399
|
+
schedule,
|
|
400
|
+
emit,
|
|
401
|
+
};
|
|
402
|
+
return adapter;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Construct the production in-process {@link DurableExecutionAdapter}.
|
|
406
|
+
*
|
|
407
|
+
* Differs from {@link createInMemoryDurableExecution} in three ways:
|
|
408
|
+
*
|
|
409
|
+
* 1. **Runtime integration.** When a {@link WorkflowRuntime} is supplied,
|
|
410
|
+
* each run/step is reflected in the runtime's cascade context, history,
|
|
411
|
+
* and (when `runtime.$.db` is wired) database adapter — making durable
|
|
412
|
+
* runs observable through the same surfaces as event-driven dispatch.
|
|
413
|
+
*
|
|
414
|
+
* 2. **Production-shape logging.** Schedule failures and step failures with
|
|
415
|
+
* a configured runtime are routed through the package logger
|
|
416
|
+
* ({@link getLogger}). The in-memory stub silently swallows these because
|
|
417
|
+
* tests do not want noise in the console.
|
|
418
|
+
*
|
|
419
|
+
* 3. **Workflow context exposes the runtime.** Bodies receive an
|
|
420
|
+
* {@link InProcessWorkflowContext} with `ctx.runtime` set, so durable
|
|
421
|
+
* workflows can dispatch events through the same `$.on`/`$.send`
|
|
422
|
+
* registry the rest of the app uses.
|
|
423
|
+
*
|
|
424
|
+
* The adapter is *not* durable across process restarts — that is the
|
|
425
|
+
* Cloudflare Workflows adapter's job (separate bead `aip-i456`). It exists
|
|
426
|
+
* for test environments, local development, and single-process callers that
|
|
427
|
+
* want the port semantics without a real backend.
|
|
428
|
+
*
|
|
429
|
+
* @example No runtime — equivalent to the in-memory stub but production-shape
|
|
430
|
+
* ```ts
|
|
431
|
+
* const dx = createInProcessDurableExecution()
|
|
432
|
+
* await dx.run('hello', async (ctx) => ctx.input.name, { name: 'world' })
|
|
433
|
+
* ```
|
|
434
|
+
*
|
|
435
|
+
* @example With runtime — durable runs participate in the `$` ecosystem
|
|
436
|
+
* ```ts
|
|
437
|
+
* const runtime = createWorkflowRuntime({ db: myDb })
|
|
438
|
+
* const dx = createInProcessDurableExecution({ runtime })
|
|
439
|
+
*
|
|
440
|
+
* await dx.run('cascade', async (ctx) => {
|
|
441
|
+
* const plan = await ctx.step('plan', async () => generatePlan(ctx.input))
|
|
442
|
+
* // The runtime's $.send delivers to handlers registered on the same runtime.
|
|
443
|
+
* ctx.runtime!.$.send('Plan.generated', plan)
|
|
444
|
+
* return plan
|
|
445
|
+
* }, { customerId: 'c-1' })
|
|
446
|
+
*
|
|
447
|
+
* // Cascade trace, history, and db actions all reflect the run.
|
|
448
|
+
* console.log(runtime.cascade.steps.length) // >= 1 (the 'plan' step)
|
|
449
|
+
* ```
|
|
450
|
+
*/
|
|
451
|
+
export function createInProcessDurableExecution(options = {}) {
|
|
452
|
+
// The in-process adapter delegates step/sleep/wait/schedule mechanics to
|
|
453
|
+
// the in-memory factory and wraps run/step with runtime-integration hooks.
|
|
454
|
+
// This keeps the two factories from drifting in their core behaviour and
|
|
455
|
+
// lets the in-memory stub remain the canonical reference for the port's
|
|
456
|
+
// baseline semantics.
|
|
457
|
+
const inner = createInMemoryDurableExecution({
|
|
458
|
+
...(options.now !== undefined && { now: options.now }),
|
|
459
|
+
...(options.delay !== undefined && { delay: options.delay }),
|
|
460
|
+
});
|
|
461
|
+
const runtime = options.runtime;
|
|
462
|
+
function recordRunHistory(name, phase, data) {
|
|
463
|
+
if (!runtime)
|
|
464
|
+
return;
|
|
465
|
+
runtime.state.history.push({
|
|
466
|
+
timestamp: Date.now(),
|
|
467
|
+
type: 'event',
|
|
468
|
+
name: `durable-run:${phase}:${name}`,
|
|
469
|
+
...(data !== undefined && { data }),
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
async function instrumentedStep(stepName, config, fn, innerStep) {
|
|
473
|
+
if (!runtime) {
|
|
474
|
+
// No runtime — defer to the inner mechanics unchanged.
|
|
475
|
+
return config !== undefined ? innerStep(stepName, config, fn) : innerStep(stepName, fn);
|
|
476
|
+
}
|
|
477
|
+
const cascadeStep = recordStep(runtime.cascade, stepName);
|
|
478
|
+
const db = runtime.$.db;
|
|
479
|
+
let actionRecorded = false;
|
|
480
|
+
if (db) {
|
|
481
|
+
try {
|
|
482
|
+
await db.createAction({
|
|
483
|
+
actor: 'workflow',
|
|
484
|
+
object: stepName,
|
|
485
|
+
action: 'step',
|
|
486
|
+
status: 'active',
|
|
487
|
+
});
|
|
488
|
+
actionRecorded = true;
|
|
489
|
+
}
|
|
490
|
+
catch (err) {
|
|
491
|
+
// Do not fail the step because action recording failed; surface the
|
|
492
|
+
// error through the package logger so it is observable.
|
|
493
|
+
getLogger().error(`[durable-execution] Failed to record action for step "${stepName}":`, err);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
const wrapped = async () => fn();
|
|
497
|
+
try {
|
|
498
|
+
const result = await (config !== undefined
|
|
499
|
+
? innerStep(stepName, config, wrapped)
|
|
500
|
+
: innerStep(stepName, wrapped));
|
|
501
|
+
cascadeStep.complete();
|
|
502
|
+
if (actionRecorded && db) {
|
|
503
|
+
try {
|
|
504
|
+
await db.completeAction(stepName, result);
|
|
505
|
+
}
|
|
506
|
+
catch (err) {
|
|
507
|
+
getLogger().error(`[durable-execution] Failed to complete action for step "${stepName}":`, err);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
return result;
|
|
511
|
+
}
|
|
512
|
+
catch (err) {
|
|
513
|
+
cascadeStep.fail(err instanceof Error ? err : new Error(String(err)));
|
|
514
|
+
getLogger().error(`[durable-execution] Step "${stepName}" failed:`, err);
|
|
515
|
+
throw err;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
async function run(name, fn, input) {
|
|
519
|
+
recordRunHistory(name, 'start', { input });
|
|
520
|
+
try {
|
|
521
|
+
const result = await inner.run(name, async (innerCtx) => {
|
|
522
|
+
const ctx = {
|
|
523
|
+
input: innerCtx.input,
|
|
524
|
+
instanceId: innerCtx.instanceId,
|
|
525
|
+
name: innerCtx.name,
|
|
526
|
+
sleep: innerCtx.sleep,
|
|
527
|
+
sleepUntil: innerCtx.sleepUntil,
|
|
528
|
+
waitForEvent: innerCtx.waitForEvent,
|
|
529
|
+
step: ((stepName, configOrFn, maybeFn) => {
|
|
530
|
+
if (typeof configOrFn === 'function') {
|
|
531
|
+
return instrumentedStep(stepName, undefined, configOrFn, innerCtx.step);
|
|
532
|
+
}
|
|
533
|
+
return instrumentedStep(stepName, configOrFn, maybeFn, innerCtx.step);
|
|
534
|
+
}),
|
|
535
|
+
...(runtime !== undefined && { runtime }),
|
|
536
|
+
};
|
|
537
|
+
return fn(ctx);
|
|
538
|
+
}, input);
|
|
539
|
+
recordRunHistory(name, 'finish', { result });
|
|
540
|
+
return result;
|
|
541
|
+
}
|
|
542
|
+
catch (err) {
|
|
543
|
+
recordRunHistory(name, 'error', { error: err instanceof Error ? err.message : String(err) });
|
|
544
|
+
throw err;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
function topLevelStep(name, configOrFn, maybeFn) {
|
|
548
|
+
if (typeof configOrFn === 'function') {
|
|
549
|
+
return instrumentedStep(name, undefined, configOrFn, inner.step);
|
|
550
|
+
}
|
|
551
|
+
return instrumentedStep(name, configOrFn, maybeFn, inner.step);
|
|
552
|
+
}
|
|
553
|
+
function instrumentedSchedule(name, cron, fn) {
|
|
554
|
+
if (!runtime) {
|
|
555
|
+
return inner.schedule(name, cron, fn);
|
|
556
|
+
}
|
|
557
|
+
// When a runtime is wired, surface schedule failures through the logger
|
|
558
|
+
// (the in-memory stub silently swallows them). We do this by wrapping the
|
|
559
|
+
// body to log; the inner schedule itself continues to swallow rejections
|
|
560
|
+
// so the interval keeps firing.
|
|
561
|
+
const wrapped = async (ctx) => {
|
|
562
|
+
try {
|
|
563
|
+
return await fn(ctx);
|
|
564
|
+
}
|
|
565
|
+
catch (err) {
|
|
566
|
+
getLogger().error(`[durable-execution] Scheduled run "${name}" failed:`, err);
|
|
567
|
+
throw err;
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
return inner.schedule(name, cron, wrapped);
|
|
571
|
+
}
|
|
572
|
+
const adapter = {
|
|
573
|
+
kind: 'in-process',
|
|
574
|
+
run: run,
|
|
575
|
+
step: topLevelStep,
|
|
576
|
+
sleep: inner.sleep,
|
|
577
|
+
sleepUntil: inner.sleepUntil,
|
|
578
|
+
waitForEvent: inner.waitForEvent,
|
|
579
|
+
schedule: instrumentedSchedule,
|
|
580
|
+
emit: inner.emit,
|
|
581
|
+
...(runtime !== undefined && { runtime }),
|
|
582
|
+
};
|
|
583
|
+
return adapter;
|
|
584
|
+
}
|
|
585
|
+
// =============================================================================
|
|
586
|
+
// Cloudflare Workflows adapter (re-export)
|
|
587
|
+
// =============================================================================
|
|
588
|
+
// Re-export the Cloudflare Workflows adapter so callers using the
|
|
589
|
+
// `ai-workflows/durable-execution` subpath can reach both the port and its CF
|
|
590
|
+
// implementation through a single import. See `./durable-execution-cloudflare.ts`
|
|
591
|
+
// for the bridge logic and `docs/adr/0004-durable-execution-cf-workflows-default.md`
|
|
592
|
+
// for the rationale.
|
|
593
|
+
export { createCloudflareWorkflowsDurableExecution, createWorkflowEntrypoint, } from './durable-execution-cloudflare.js';
|
|
594
|
+
//# sourceMappingURL=durable-execution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable-execution.js","sourceRoot":"","sources":["../src/durable-execution.ts"],"names":[],"mappings":"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"}
|