@effect-app/infra 4.0.0-beta.257 → 4.0.0-beta.258

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.
@@ -0,0 +1,550 @@
1
+ /**
2
+ * SQLite backed {@link WorkflowEngine} implementation.
3
+ *
4
+ * Persists workflow state across four tables:
5
+ * - `workflow_exec` — one row per execution; tracks status, lease, etag
6
+ * - `workflow_activity` — recorded activity results keyed by (exec, name, attempt)
7
+ * - `workflow_deferred` — durable deferred completions keyed by (exec, name)
8
+ * - `workflow_clock` — scheduled clocks with `fire_at`
9
+ *
10
+ * Atomicity: multi-statement operations are wrapped in `sql.withTransaction`
11
+ * (BEGIN/COMMIT) so concurrent writers do not observe partial state.
12
+ *
13
+ * Optimistic concurrency:
14
+ * - exec state transitions use `UPDATE ... WHERE etag = ? RETURNING etag`;
15
+ * a zero-row result is an `OptimisticConcurrencyException`.
16
+ * - activity / deferred / clock inserts use `INSERT ... ON CONFLICT DO
17
+ * NOTHING RETURNING ...` for first-writer-wins semantics across drivers.
18
+ *
19
+ * Durability — everything that crosses the storage boundary is round-tripped
20
+ * through schema codecs (`S.fromJsonString(S.toCodecJson(...))`), exactly like
21
+ * the cluster engine:
22
+ *
23
+ * - The workflow payload and the top-level `Workflow.Result` are encoded with
24
+ * the workflow's own `payloadSchema` / `successSchema` / `errorSchema`, so
25
+ * typed values (dates, branded ids, schema classes) survive a restart.
26
+ * - Activity results flow through the engine already encoded, so they are
27
+ * persisted with an opaque `Workflow.Result({ success: AnyOrVoid, error:
28
+ * AnyOrVoid })` codec — same trick the cluster `ActivityRpc` uses.
29
+ * - Durable-deferred exits use an opaque `Exit` codec.
30
+ *
31
+ * Crash recovery: each driver holds a time-bound lease on the exec row,
32
+ * renewed by a heartbeat fiber. A scope-bound recovery poller re-drives any
33
+ * exec whose lease has lapsed. A clock poller fires due clocks even when
34
+ * the in-process timer is missing (e.g. after a restart).
35
+ */
36
+ import * as Effect from "effect-app/Effect";
37
+ import * as Layer from "effect-app/Layer";
38
+ import * as Option from "effect-app/Option";
39
+ import * as S from "effect-app/Schema";
40
+ import * as Duration from "effect/Duration";
41
+ import * as Exit from "effect/Exit";
42
+ import * as Fiber from "effect/Fiber";
43
+ import * as FiberMap from "effect/FiberMap";
44
+ import * as Schedule from "effect/Schedule";
45
+ import { SqlClient } from "effect/unstable/sql";
46
+ import * as Workflow from "effect/unstable/workflow/Workflow";
47
+ import { makeUnsafe, WorkflowEngine, WorkflowInstance } from "effect/unstable/workflow/WorkflowEngine";
48
+ import { randomUUID } from "node:crypto";
49
+ import { OptimisticConcurrencyException } from "./errors.js";
50
+ import { annotateDb } from "./otel.js";
51
+ const parseExec = (row) => ({
52
+ executionId: row.execution_id,
53
+ workflowName: row.workflow_name,
54
+ payload: row.payload,
55
+ parent: row.parent ?? undefined,
56
+ status: row.status,
57
+ suspended: row.suspended !== 0,
58
+ interrupted: row.interrupted !== 0,
59
+ completedResult: row.completed_result ?? undefined,
60
+ worker: row.worker ?? undefined,
61
+ leaseExpiresAt: row.lease_expires_at ?? undefined,
62
+ etag: row.etag
63
+ });
64
+ // --- Storage codecs ---------------------------------------------------------
65
+ // Values flowing through the engine's activity / deferred boundary are already
66
+ // schema-encoded, so the structure is round-tripped while the payload stays
67
+ // opaque (mirrors the cluster engine's `AnyOrVoid` usage).
68
+ const AnyOrVoid = S.Union([S.Any, S.Void]);
69
+ const ActivityResultCodec = S.fromJsonString(S.toCodecJson(Workflow.Result({ success: AnyOrVoid, error: AnyOrVoid })));
70
+ const DeferredExitCodec = S.fromJsonString(S.toCodecJson(S.Exit(AnyOrVoid, AnyOrVoid, S.Defect)));
71
+ const encodeActivityResult = (r) => Effect.orDie(S.encodeEffect(ActivityResultCodec)(r));
72
+ const decodeActivityResult = (s) => Effect.orDie(S.decodeEffect(ActivityResultCodec)(s));
73
+ const encodeDeferredExit = (e) => Effect.orDie(S.encodeEffect(DeferredExitCodec)(e));
74
+ const decodeDeferredExit = (s) => Effect.orDie(S.decodeEffect(DeferredExitCodec)(s));
75
+ const makeSqliteWorkflowEngine = Effect.fnUntraced(function* (cfg) {
76
+ const sql = yield* SqlClient.SqlClient;
77
+ const scope = yield* Effect.scope;
78
+ const prefix = cfg.prefix ?? "";
79
+ const execTable = `${prefix}workflow_exec`;
80
+ const activityTable = `${prefix}workflow_activity`;
81
+ const deferredTable = `${prefix}workflow_deferred`;
82
+ const clockTable = `${prefix}workflow_clock`;
83
+ const workerId = cfg.workerId ?? randomUUID();
84
+ const leaseTtl = cfg.leaseTtl ?? Duration.seconds(30);
85
+ const heartbeatInterval = cfg.heartbeatInterval ?? Duration.seconds(10);
86
+ const recoveryInterval = cfg.recoveryInterval ?? Duration.seconds(15);
87
+ const clockPollInterval = cfg.clockPollInterval ?? Duration.seconds(5);
88
+ const annotate = (operation, executionId) => annotateDb({
89
+ operation,
90
+ system: "sqlite",
91
+ collection: execTable,
92
+ entity: "workflow",
93
+ extra: executionId !== undefined ? { "app.entity.id": executionId } : undefined
94
+ });
95
+ const exec = (query, params = []) => sql.unsafe(query, params).pipe(Effect.orDie);
96
+ // --- Schema -----------------------------------------------------------
97
+ yield* exec(`CREATE TABLE IF NOT EXISTS "${execTable}" (
98
+ execution_id TEXT PRIMARY KEY,
99
+ workflow_name TEXT NOT NULL,
100
+ payload TEXT NOT NULL,
101
+ parent TEXT,
102
+ status TEXT NOT NULL,
103
+ suspended INTEGER NOT NULL DEFAULT 0,
104
+ interrupted INTEGER NOT NULL DEFAULT 0,
105
+ completed_result TEXT,
106
+ worker TEXT,
107
+ lease_expires_at INTEGER,
108
+ etag TEXT NOT NULL
109
+ )`);
110
+ yield* exec(`CREATE INDEX IF NOT EXISTS "${execTable}_recovery" ON "${execTable}" (status, lease_expires_at)`);
111
+ yield* exec(`CREATE TABLE IF NOT EXISTS "${activityTable}" (
112
+ execution_id TEXT NOT NULL,
113
+ name TEXT NOT NULL,
114
+ attempt INTEGER NOT NULL,
115
+ result TEXT NOT NULL,
116
+ PRIMARY KEY (execution_id, name, attempt)
117
+ )`);
118
+ yield* exec(`CREATE TABLE IF NOT EXISTS "${deferredTable}" (
119
+ execution_id TEXT NOT NULL,
120
+ name TEXT NOT NULL,
121
+ exit TEXT NOT NULL,
122
+ PRIMARY KEY (execution_id, name)
123
+ )`);
124
+ yield* exec(`CREATE TABLE IF NOT EXISTS "${clockTable}" (
125
+ execution_id TEXT NOT NULL,
126
+ name TEXT NOT NULL,
127
+ workflow_name TEXT NOT NULL,
128
+ deferred_name TEXT NOT NULL,
129
+ fire_at INTEGER NOT NULL,
130
+ PRIMARY KEY (execution_id, name)
131
+ )`);
132
+ yield* exec(`CREATE INDEX IF NOT EXISTS "${clockTable}_due" ON "${clockTable}" (fire_at)`);
133
+ const workflows = new Map();
134
+ const locals = new Map();
135
+ const clocks = yield* FiberMap.make();
136
+ // Per-workflow codecs for the typed payload + top-level result. Cached by
137
+ // workflow name; derived from the workflow's own schemas so typed values
138
+ // (dates, branded ids, schema classes) survive the storage round-trip.
139
+ const makePayloadCodec = (workflow) => S.fromJsonString(S.toCodecJson(workflow.payloadSchema));
140
+ const payloadCodecCache = new Map();
141
+ const payloadCodecFor = (workflow) => {
142
+ let c = payloadCodecCache.get(workflow.name);
143
+ if (!c) {
144
+ c = makePayloadCodec(workflow);
145
+ payloadCodecCache.set(workflow.name, c);
146
+ }
147
+ return c;
148
+ };
149
+ const makeResultCodec = (workflow) => S.fromJsonString(S.toCodecJson(Workflow.Result({ success: workflow.successSchema, error: workflow.errorSchema })));
150
+ const resultCodecCache = new Map();
151
+ const resultCodecFor = (workflow) => {
152
+ let c = resultCodecCache.get(workflow.name);
153
+ if (!c) {
154
+ c = makeResultCodec(workflow);
155
+ resultCodecCache.set(workflow.name, c);
156
+ }
157
+ return c;
158
+ };
159
+ const encodePayload = (workflow, payload) => Effect.orDie(S.encodeEffect(payloadCodecFor(workflow))(payload));
160
+ const decodePayload = (workflow, s) => Effect.orDie(S.decodeEffect(payloadCodecFor(workflow))(s));
161
+ const encodeResult = (workflow, r) => Effect.orDie(S.encodeEffect(resultCodecFor(workflow))(r));
162
+ const decodeResult = (workflow, s) => Effect.orDie(S.decodeEffect(resultCodecFor(workflow))(s));
163
+ // --- Core SQL operations ----------------------------------------------
164
+ const readExec = (executionId) => exec(`SELECT * FROM "${execTable}" WHERE execution_id = ?`, [executionId])
165
+ .pipe(Effect.map((rows) => {
166
+ const r = rows[0];
167
+ return r ? Option.some(parseExec(r)) : Option.none();
168
+ }), annotate("readExec", executionId));
169
+ /**
170
+ * OCC-guarded write. Generates a fresh etag on success; returns
171
+ * `OptimisticConcurrencyException` when no row matches the prior etag.
172
+ */
173
+ const replaceExec = (state, next) => Effect
174
+ .gen(function* () {
175
+ const newEtag = randomUUID();
176
+ const merged = { ...state, ...next, etag: newEtag };
177
+ const rows = yield* exec(`UPDATE "${execTable}"
178
+ SET status = ?,
179
+ suspended = ?,
180
+ interrupted = ?,
181
+ completed_result = ?,
182
+ worker = ?,
183
+ lease_expires_at = ?,
184
+ etag = ?
185
+ WHERE execution_id = ? AND etag = ?
186
+ RETURNING etag`, [
187
+ merged.status,
188
+ merged.suspended ? 1 : 0,
189
+ merged.interrupted ? 1 : 0,
190
+ merged.completedResult ?? null,
191
+ merged.worker ?? null,
192
+ merged.leaseExpiresAt ?? null,
193
+ newEtag,
194
+ state.executionId,
195
+ state.etag
196
+ ]);
197
+ if (rows.length === 0) {
198
+ return yield* new OptimisticConcurrencyException({
199
+ type: "workflow.exec",
200
+ id: state.executionId,
201
+ code: 412
202
+ });
203
+ }
204
+ return merged;
205
+ })
206
+ .pipe(annotate("replaceExec", state.executionId));
207
+ const createExec = (initial) => exec(`INSERT INTO "${execTable}"
208
+ (execution_id, workflow_name, payload, parent, status, suspended, interrupted, etag)
209
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
210
+ ON CONFLICT DO NOTHING
211
+ RETURNING execution_id`, [
212
+ initial.executionId,
213
+ initial.workflowName,
214
+ initial.payload,
215
+ initial.parent ?? null,
216
+ initial.status,
217
+ initial.suspended ? 1 : 0,
218
+ initial.interrupted ? 1 : 0,
219
+ initial.etag
220
+ ])
221
+ .pipe(Effect.map((rows) => rows.length > 0), annotate("createExec", initial.executionId));
222
+ // First-writer-wins persistence of an activity result; returns true if this
223
+ // call won, false if another writer beat us to the (exec, name, attempt) row.
224
+ const createActivity = (executionId, name, attempt, encoded) => exec(`INSERT INTO "${activityTable}" (execution_id, name, attempt, result)
225
+ VALUES (?, ?, ?, ?)
226
+ ON CONFLICT DO NOTHING
227
+ RETURNING execution_id`, [executionId, name, attempt, encoded])
228
+ .pipe(Effect.map((rows) => rows.length > 0));
229
+ // Overwrites a previously persisted *suspended* activity result so the next
230
+ // attempt can record its real outcome.
231
+ const upsertActivity = (executionId, name, attempt, encoded) => exec(`INSERT INTO "${activityTable}" (execution_id, name, attempt, result)
232
+ VALUES (?, ?, ?, ?)
233
+ ON CONFLICT(execution_id, name, attempt) DO UPDATE SET result = excluded.result`, [executionId, name, attempt, encoded])
234
+ .pipe(Effect.asVoid);
235
+ const readActivity = (executionId, name, attempt) => exec(`SELECT result FROM "${activityTable}" WHERE execution_id = ? AND name = ? AND attempt = ?`, [executionId, name, attempt])
236
+ .pipe(Effect.map((rows) => {
237
+ const r = rows[0];
238
+ return r ? Option.some(r.result) : Option.none();
239
+ }));
240
+ const createDeferred = (executionId, name, encoded) => exec(`INSERT INTO "${deferredTable}" (execution_id, name, exit)
241
+ VALUES (?, ?, ?)
242
+ ON CONFLICT DO NOTHING
243
+ RETURNING execution_id`, [executionId, name, encoded])
244
+ .pipe(Effect.map((rows) => rows.length > 0));
245
+ const readDeferred = (executionId, name) => exec(`SELECT exit FROM "${deferredTable}" WHERE execution_id = ? AND name = ?`, [executionId, name])
246
+ .pipe(Effect.map((rows) => {
247
+ const r = rows[0];
248
+ return r ? Option.some(r.exit) : Option.none();
249
+ }));
250
+ const insertClock = (executionId, name, workflowName, deferredName, fireAt) => exec(`INSERT INTO "${clockTable}" (execution_id, name, workflow_name, deferred_name, fire_at)
251
+ VALUES (?, ?, ?, ?, ?)
252
+ ON CONFLICT DO NOTHING
253
+ RETURNING execution_id`, [executionId, name, workflowName, deferredName, fireAt])
254
+ .pipe(Effect.map((rows) => rows.length > 0));
255
+ const deleteClock = (executionId, name) => exec(`DELETE FROM "${clockTable}" WHERE execution_id = ? AND name = ?`, [executionId, name]);
256
+ // --- Workflow result helpers ------------------------------------------
257
+ const completeResult = (workflow, state) => state.status === "complete" && state.completedResult
258
+ ? Effect.map(decodeResult(workflow, state.completedResult), Option.some)
259
+ : Effect.succeedNone;
260
+ // --- Lease / claim ----------------------------------------------------
261
+ const leaseActive = (state, now) => state.worker !== undefined
262
+ && state.worker !== workerId
263
+ && state.leaseExpiresAt !== undefined
264
+ && state.leaseExpiresAt > now;
265
+ const tryClaim = (state) => Effect.gen(function* () {
266
+ const now = Date.now();
267
+ if (leaseActive(state, now))
268
+ return Option.none();
269
+ return yield* replaceExec(state, {
270
+ worker: workerId,
271
+ leaseExpiresAt: now + Duration.toMillis(leaseTtl)
272
+ })
273
+ .pipe(Effect.map(Option.some), Effect.catchTag("OptimisticConcurrencyException", () => Effect.succeed(Option.none())));
274
+ });
275
+ const heartbeat = (executionId) => Effect.gen(function* () {
276
+ while (true) {
277
+ yield* Effect.sleep(heartbeatInterval);
278
+ const local = locals.get(executionId);
279
+ const polled = local?.fiber?.pollUnsafe();
280
+ if (!local?.fiber || polled)
281
+ return;
282
+ const cur = yield* readExec(executionId).pipe(Effect.catchCause(() => Effect.succeed(Option.none())));
283
+ if (Option.isNone(cur))
284
+ continue;
285
+ const state = cur.value;
286
+ if (state.status === "complete" || state.worker !== workerId)
287
+ return;
288
+ yield* replaceExec(state, {
289
+ leaseExpiresAt: Date.now() + Duration.toMillis(leaseTtl)
290
+ })
291
+ .pipe(Effect.catchTag("OptimisticConcurrencyException", () => Effect.void), Effect.catchCause(() => Effect.void));
292
+ }
293
+ });
294
+ // --- Drive logic ------------------------------------------------------
295
+ const drive = (executionId, payload, parent, entry) => Effect.gen(function* () {
296
+ let local = locals.get(executionId);
297
+ if (local?.fiber) {
298
+ const polled = local.fiber.pollUnsafe();
299
+ const stillRunning = !polled;
300
+ const completedNotResume = polled && polled._tag === "Success" && polled.value._tag === "Complete";
301
+ if (stillRunning || completedNotResume)
302
+ return;
303
+ }
304
+ const stateOpt = yield* readExec(executionId);
305
+ if (Option.isNone(stateOpt) || stateOpt.value.status === "complete")
306
+ return;
307
+ const claimed = yield* tryClaim(stateOpt.value);
308
+ const state = Option.isSome(claimed) ? claimed.value : stateOpt.value;
309
+ const instance = WorkflowInstance.initial(entry.workflow, executionId);
310
+ instance.interrupted = state.interrupted;
311
+ if (!local) {
312
+ local = { instance, fiber: undefined, parent };
313
+ locals.set(executionId, local);
314
+ }
315
+ else {
316
+ local.instance = instance;
317
+ }
318
+ const onComplete = Effect.fnUntraced(function* (result) {
319
+ const current = yield* readExec(executionId);
320
+ if (Option.isNone(current) || current.value.status === "complete")
321
+ return;
322
+ const isComplete = result._tag === "Complete";
323
+ const completedResult = isComplete ? yield* encodeResult(entry.workflow, result) : undefined;
324
+ yield* replaceExec(current.value, {
325
+ status: isComplete ? "complete" : current.value.status,
326
+ suspended: result._tag === "Suspended",
327
+ interrupted: instance.interrupted,
328
+ completedResult,
329
+ worker: isComplete ? undefined : current.value.worker,
330
+ leaseExpiresAt: isComplete ? undefined : current.value.leaseExpiresAt
331
+ })
332
+ .pipe(Effect.catchTag("OptimisticConcurrencyException", () => Effect.void));
333
+ if (parent && isComplete) {
334
+ yield* Effect.forkIn(driveById(parent), scope);
335
+ }
336
+ });
337
+ local.fiber = yield* entry.execute(payload, executionId).pipe(Effect.onExit(() => {
338
+ if (!instance.interrupted)
339
+ return Effect.void;
340
+ instance.suspended = false;
341
+ return Effect.withFiber((fiber) => Effect.interruptible(Fiber.interrupt(fiber)));
342
+ }), Workflow.intoResult, Effect.provideService(WorkflowInstance, instance), Effect.provideService(WorkflowEngine, engine), Effect.tap(onComplete), Effect.forkIn(entry.scope));
343
+ if (Option.isSome(claimed)) {
344
+ yield* Effect.forkIn(heartbeat(executionId), scope);
345
+ }
346
+ });
347
+ const driveById = (executionId) => Effect.gen(function* () {
348
+ const stateOpt = yield* readExec(executionId);
349
+ if (Option.isNone(stateOpt))
350
+ return;
351
+ const state = stateOpt.value;
352
+ const entry = workflows.get(state.workflowName);
353
+ if (!entry)
354
+ return;
355
+ const payload = yield* decodePayload(entry.workflow, state.payload);
356
+ yield* drive(executionId, payload, state.parent, entry);
357
+ });
358
+ // --- Clock firing -----------------------------------------------------
359
+ const fireClock = (executionId, name, deferredName) => Effect
360
+ .gen(function* () {
361
+ const encoded = yield* encodeDeferredExit(Exit.void);
362
+ const inserted = yield* sql
363
+ .withTransaction(Effect.gen(function* () {
364
+ const got = yield* createDeferred(executionId, deferredName, encoded);
365
+ yield* deleteClock(executionId, name);
366
+ return got;
367
+ }))
368
+ .pipe(Effect.orDie);
369
+ if (inserted)
370
+ yield* driveById(executionId);
371
+ })
372
+ .pipe(annotate("clockFire", executionId));
373
+ // --- Encoded engine ---------------------------------------------------
374
+ const encoded = {
375
+ register: Effect.fnUntraced(function* (workflow, execute) {
376
+ workflows.set(workflow.name, {
377
+ workflow,
378
+ execute,
379
+ scope: yield* Effect.scope
380
+ });
381
+ }),
382
+ execute: Effect.fnUntraced(function* (workflow, options) {
383
+ const entry = workflows.get(workflow.name);
384
+ if (!entry) {
385
+ return yield* Effect.orDie(Effect.fail(`Workflow ${workflow.name} is not registered`));
386
+ }
387
+ const initial = {
388
+ executionId: options.executionId,
389
+ workflowName: workflow.name,
390
+ payload: yield* encodePayload(workflow, options.payload),
391
+ parent: options.parent?.executionId,
392
+ status: "running",
393
+ suspended: false,
394
+ interrupted: false,
395
+ completedResult: undefined,
396
+ worker: undefined,
397
+ leaseExpiresAt: undefined,
398
+ etag: randomUUID()
399
+ };
400
+ yield* createExec(initial);
401
+ yield* drive(options.executionId, options.payload, options.parent?.executionId, entry);
402
+ if (options.discard)
403
+ return undefined;
404
+ const local = locals.get(options.executionId);
405
+ if (local?.fiber) {
406
+ return (yield* Fiber.join(local.fiber));
407
+ }
408
+ // Foreign-driver fallback: poll the persisted result until completion.
409
+ while (true) {
410
+ const cur = yield* readExec(options.executionId);
411
+ if (Option.isSome(cur)) {
412
+ const r = yield* completeResult(workflow, cur.value);
413
+ if (Option.isSome(r))
414
+ return r.value;
415
+ }
416
+ yield* Effect.sleep(Duration.millis(500));
417
+ }
418
+ }),
419
+ poll: (workflow, executionId) => Effect.gen(function* () {
420
+ const local = locals.get(executionId);
421
+ if (local?.fiber) {
422
+ const exitVal = local.fiber.pollUnsafe();
423
+ if (!exitVal)
424
+ return Option.none();
425
+ if (exitVal._tag !== "Success")
426
+ return yield* Effect.die(exitVal.cause);
427
+ return Option.some(exitVal.value);
428
+ }
429
+ const state = yield* readExec(executionId);
430
+ if (Option.isNone(state))
431
+ return Option.none();
432
+ return yield* completeResult(workflow, state.value);
433
+ }),
434
+ interrupt: Effect.fnUntraced(function* (_workflow, executionId) {
435
+ const local = locals.get(executionId);
436
+ if (local)
437
+ local.instance.interrupted = true;
438
+ const current = yield* readExec(executionId);
439
+ if (Option.isNone(current) || current.value.status === "complete")
440
+ return;
441
+ yield* replaceExec(current.value, { interrupted: true }).pipe(Effect.catchTag("OptimisticConcurrencyException", () => Effect.void));
442
+ yield* driveById(executionId);
443
+ }),
444
+ interruptUnsafe: Effect.fnUntraced(function* (_workflow, executionId) {
445
+ const local = locals.get(executionId);
446
+ if (local)
447
+ local.instance.interrupted = true;
448
+ const current = yield* readExec(executionId);
449
+ if (Option.isSome(current) && current.value.status !== "complete") {
450
+ yield* replaceExec(current.value, { interrupted: true }).pipe(Effect.catchTag("OptimisticConcurrencyException", () => Effect.void));
451
+ }
452
+ if (local?.fiber)
453
+ yield* Fiber.interrupt(local.fiber);
454
+ }),
455
+ resume: (_workflow, executionId) => driveById(executionId),
456
+ activityExecute: Effect.fnUntraced(function* (activity, attempt) {
457
+ const instance = yield* WorkflowInstance;
458
+ const existing = yield* readActivity(instance.executionId, activity.name, attempt);
459
+ if (Option.isSome(existing)) {
460
+ const prev = yield* decodeActivityResult(existing.value);
461
+ // A completed activity is replayed from its persisted result; a
462
+ // suspended one must re-run (it parked on a clock/deferred).
463
+ if (prev._tag === "Complete")
464
+ return prev;
465
+ }
466
+ const activityInstance = WorkflowInstance.initial(instance.workflow, instance.executionId);
467
+ activityInstance.interrupted = instance.interrupted;
468
+ const result = yield* activity.executeEncoded.pipe(Workflow.intoResult, Effect.provideService(WorkflowInstance, activityInstance));
469
+ const encodedResult = yield* encodeActivityResult(result);
470
+ if (Option.isSome(existing)) {
471
+ // Overwrite the previously persisted *suspended* result.
472
+ yield* upsertActivity(instance.executionId, activity.name, attempt, encodedResult);
473
+ return result;
474
+ }
475
+ // First-writer-wins: if persistence loses the race, use the persisted result.
476
+ const persisted = yield* createActivity(instance.executionId, activity.name, attempt, encodedResult);
477
+ if (persisted)
478
+ return result;
479
+ const winner = yield* readActivity(instance.executionId, activity.name, attempt);
480
+ if (Option.isSome(winner)) {
481
+ const w = yield* decodeActivityResult(winner.value);
482
+ if (w._tag === "Complete")
483
+ return w;
484
+ }
485
+ return result;
486
+ }),
487
+ deferredResult: Effect.fnUntraced(function* (deferred) {
488
+ const instance = yield* WorkflowInstance;
489
+ const got = yield* readDeferred(instance.executionId, deferred.name);
490
+ if (Option.isNone(got))
491
+ return Option.none();
492
+ return Option.some(yield* decodeDeferredExit(got.value));
493
+ }),
494
+ deferredDone: Effect.fnUntraced(function* (options) {
495
+ const encoded = yield* encodeDeferredExit(options.exit);
496
+ const inserted = yield* createDeferred(options.executionId, options.deferredName, encoded);
497
+ if (!inserted)
498
+ return;
499
+ yield* driveById(options.executionId);
500
+ }),
501
+ scheduleClock: (workflow, options) => {
502
+ const fireAt = Date.now() + Duration.toMillis(options.clock.duration);
503
+ return Effect.gen(function* () {
504
+ yield* insertClock(options.executionId, options.clock.name, workflow.name, options.clock.deferred.name, fireAt);
505
+ yield* fireClock(options.executionId, options.clock.name, options.clock.deferred.name).pipe(Effect.delay(options.clock.duration), FiberMap.run(clocks, `${options.executionId}/${options.clock.name}`, { onlyIfMissing: true }), Effect.asVoid);
506
+ });
507
+ }
508
+ };
509
+ const engine = makeUnsafe(encoded);
510
+ // --- Recovery poller --------------------------------------------------
511
+ if (Duration.toMillis(recoveryInterval) > 0) {
512
+ const recoverStep = Effect
513
+ .gen(function* () {
514
+ const rows = yield* exec(`SELECT execution_id, workflow_name FROM "${execTable}"
515
+ WHERE status = 'running' AND (lease_expires_at IS NULL OR lease_expires_at <= ?)
516
+ LIMIT 100`, [Date.now()]);
517
+ for (const row of rows) {
518
+ if (!workflows.has(row.workflow_name))
519
+ continue;
520
+ const local = locals.get(row.execution_id);
521
+ if (local?.fiber && !local.fiber.pollUnsafe())
522
+ continue;
523
+ yield* Effect.forkIn(driveById(row.execution_id), scope);
524
+ }
525
+ })
526
+ .pipe(annotate("recoveryScan"), Effect.catchCause(() => Effect.void));
527
+ yield* recoverStep.pipe(Effect.repeat(Schedule.spaced(recoveryInterval)), Effect.forkIn(scope));
528
+ }
529
+ // --- Clock poller -----------------------------------------------------
530
+ if (Duration.toMillis(clockPollInterval) > 0) {
531
+ const clockStep = Effect
532
+ .gen(function* () {
533
+ const rows = yield* exec(`SELECT execution_id, name, deferred_name FROM "${clockTable}"
534
+ WHERE fire_at <= ?
535
+ LIMIT 100`, [Date.now()]);
536
+ for (const row of rows) {
537
+ yield* Effect.forkIn(fireClock(row.execution_id, row.name, row.deferred_name), scope);
538
+ }
539
+ })
540
+ .pipe(annotate("clockScan"), Effect.catchCause(() => Effect.void));
541
+ yield* clockStep.pipe(Effect.repeat(Schedule.spaced(clockPollInterval)), Effect.forkIn(scope));
542
+ }
543
+ return engine;
544
+ });
545
+ /**
546
+ * SQLite backed `WorkflowEngine` layer. Requires an ambient `SqlClient`
547
+ * (`@effect/sql-sqlite-node` or a compatible client).
548
+ */
549
+ export const layerSqlite = (cfg = {}) => Layer.effect(WorkflowEngine)(makeSqliteWorkflowEngine(cfg));
550
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiV29ya2Zsb3dFbmdpbmVTcWxpdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvV29ya2Zsb3dFbmdpbmVTcWxpdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FrQ0c7QUFDSCxPQUFPLEtBQUssTUFBTSxNQUFNLG1CQUFtQixDQUFBO0FBQzNDLE9BQU8sS0FBSyxLQUFLLE1BQU0sa0JBQWtCLENBQUE7QUFDekMsT0FBTyxLQUFLLE1BQU0sTUFBTSxtQkFBbUIsQ0FBQTtBQUMzQyxPQUFPLEtBQUssQ0FBQyxNQUFNLG1CQUFtQixDQUFBO0FBQ3RDLE9BQU8sS0FBSyxRQUFRLE1BQU0saUJBQWlCLENBQUE7QUFDM0MsT0FBTyxLQUFLLElBQUksTUFBTSxhQUFhLENBQUE7QUFDbkMsT0FBTyxLQUFLLEtBQUssTUFBTSxjQUFjLENBQUE7QUFDckMsT0FBTyxLQUFLLFFBQVEsTUFBTSxpQkFBaUIsQ0FBQTtBQUMzQyxPQUFPLEtBQUssUUFBUSxNQUFNLGlCQUFpQixDQUFBO0FBRTNDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQTtBQUMvQyxPQUFPLEtBQUssUUFBUSxNQUFNLG1DQUFtQyxDQUFBO0FBQzdELE9BQU8sRUFBZ0IsVUFBVSxFQUFFLGNBQWMsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHlDQUF5QyxDQUFBO0FBQ3BILE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFDeEMsT0FBTyxFQUFFLDhCQUE4QixFQUFFLE1BQU0sYUFBYSxDQUFBO0FBQzVELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxXQUFXLENBQUE7QUFpRHRDLE1BQU0sU0FBUyxHQUFHLENBQUMsR0FBWSxFQUFhLEVBQUUsQ0FBQyxDQUFDO0lBQzlDLFdBQVcsRUFBRSxHQUFHLENBQUMsWUFBWTtJQUM3QixZQUFZLEVBQUUsR0FBRyxDQUFDLGFBQWE7SUFD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