@voltro/workflow 0.29.0 → 0.30.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1989 @@
1
+ import { C as e, E as t, T as n, w as r } from "./primitives-Bp98_F5L.js";
2
+ import { Activity as i, DurableClock as a, DurableDeferred as o, Workflow as s, WorkflowEngine as c } from "@effect/workflow";
3
+ import { Cause as l, Effect as u, Either as d, Exit as f, FiberRef as p, Layer as m, Schema as h } from "effect";
4
+ import { and as g, boolean as _, eq as v, gt as y, gte as b, id as x, integer as S, isNull as C, json as w, or as T, queryFor as E, reference as D, table as O, text as k, timestamp as A } from "@voltro/database";
5
+ import { createHash as ee } from "node:crypto";
6
+ import { WorkflowInstance as te } from "@effect/workflow/WorkflowEngine";
7
+ import { publishServerError as ne } from "@voltro/protocol";
8
+ //#region src/inMemoryLayer.ts
9
+ var j = c.layerMemory, M = O("_voltro_workflow_runs", {
10
+ id: x({ prefix: "wfrun" }),
11
+ tag: k(),
12
+ executionId: k().unique(),
13
+ status: k().oneOf([
14
+ "running",
15
+ "succeeded",
16
+ "failed",
17
+ "cancelled",
18
+ "suspended"
19
+ ]).default("running"),
20
+ payload: w(),
21
+ workflowVersion: k().nullable(),
22
+ workflowPatches: w().nullable(),
23
+ output: w().nullable(),
24
+ subject: w().nullable(),
25
+ source: k().nullable(),
26
+ errorTag: k().nullable(),
27
+ errorMessage: k().nullable(),
28
+ cancelled: _().default(!1),
29
+ discardedAt: A().nullable(),
30
+ discardedBy: k().nullable(),
31
+ startedAt: A().default("now"),
32
+ completedAt: A().nullable(),
33
+ durationMs: S().nullable(),
34
+ traceId: k().nullable(),
35
+ parentExecutionId: k().nullable(),
36
+ parentClosePolicy: k().oneOf([
37
+ "cancel",
38
+ "terminate",
39
+ "abandon"
40
+ ]).nullable()
41
+ }).index(["tag"]).index(["status"]).index(["source"]).index(["startedAt"]).index(["parentExecutionId"]).index(["parentClosePolicy"]), N = O("_voltro_workflow_run_steps", {
42
+ id: x({ prefix: "wfstep" }),
43
+ runId: D(() => M, {
44
+ index: !1,
45
+ onDelete: "cascade"
46
+ }),
47
+ stepName: k(),
48
+ attempt: S().default(1),
49
+ status: k().oneOf([
50
+ "running",
51
+ "succeeded",
52
+ "failed"
53
+ ]).default("running"),
54
+ input: w().nullable(),
55
+ retryPolicy: w().nullable(),
56
+ output: w().nullable(),
57
+ errorTag: k().nullable(),
58
+ errorMessage: k().nullable(),
59
+ errorCause: w().nullable(),
60
+ startedAt: A().default("now"),
61
+ completedAt: A().nullable(),
62
+ durationMs: S().nullable()
63
+ }).index(["runId", "stepName"]).index(["startedAt"]), re = O("_voltro_workflow_run_events", {
64
+ id: x({ prefix: "wfev" }),
65
+ runId: D(() => M, {
66
+ index: !1,
67
+ onDelete: "cascade"
68
+ }),
69
+ eventType: k(),
70
+ payload: w().nullable(),
71
+ occurredAt: A().default("now"),
72
+ stepName: k().nullable(),
73
+ attempt: S().nullable()
74
+ }).index(["runId", "occurredAt"]).index(["eventType"]), ie = O("_voltro_workflow_start_contexts", {
75
+ id: x({ prefix: "wfctx" }),
76
+ workflowName: k(),
77
+ executionId: k().unique(),
78
+ subject: w().nullable(),
79
+ traceId: k().nullable(),
80
+ source: k().nullable(),
81
+ parentExecutionId: k().nullable(),
82
+ parentClosePolicy: k().oneOf([
83
+ "cancel",
84
+ "terminate",
85
+ "abandon"
86
+ ]).nullable(),
87
+ createdAt: A().default("now")
88
+ }).index(["workflowName"]).index(["executionId"]).index(["parentExecutionId"]), ae = O("_voltro_workflow_pending", {
89
+ id: x({ prefix: "wfp" }),
90
+ tenantId: k().nullable(),
91
+ workflowName: k(),
92
+ controlKey: k(),
93
+ mode: k().oneOf([
94
+ "debounce",
95
+ "batch",
96
+ "throttle",
97
+ "concurrency",
98
+ "paused"
99
+ ]),
100
+ payload: w(),
101
+ callerContext: w().nullable(),
102
+ priority: S().default(0),
103
+ dueAt: A(),
104
+ deadlineAt: A().nullable(),
105
+ collapsed: S().default(1),
106
+ firstSeenAt: A().default("now"),
107
+ updatedAt: A().default("now"),
108
+ attempts: S().default(0),
109
+ lastError: k().nullable()
110
+ }).index(["workflowName", "controlKey"]).index(["dueAt"]).index(["workflowName", "mode"]).index(["tenantId"]), oe = O("_voltro_workflow_admissions", {
111
+ id: x({ prefix: "wfadm" }),
112
+ tenantId: k().nullable(),
113
+ workflowName: k(),
114
+ outcome: k().oneOf([
115
+ "admitted",
116
+ "dropped",
117
+ "skipped",
118
+ "evicted",
119
+ "expired",
120
+ "discarded"
121
+ ]),
122
+ mode: k().nullable(),
123
+ reason: k().nullable(),
124
+ collapsed: S().default(1),
125
+ waitedMs: S().nullable(),
126
+ executionId: k().nullable(),
127
+ runId: k().nullable(),
128
+ singletonKey: k().nullable(),
129
+ concurrencyKey: k().nullable(),
130
+ rateKey: k().nullable(),
131
+ admittedAt: A().default("now"),
132
+ expiresAt: A().nullable(),
133
+ releasedAt: A().nullable()
134
+ }).index(["workflowName", "admittedAt"]).index(["concurrencyKey", "releasedAt"]).index(["singletonKey", "releasedAt"]).index(["rateKey", "admittedAt"]).index(["executionId"]).index(["tenantId"]), se = O("_voltro_workflow_pauses", {
135
+ id: x({ prefix: "wfpause" }),
136
+ pausedAt: A().default("now"),
137
+ pausedBy: k().nullable(),
138
+ reason: k().nullable()
139
+ }), ce = class extends Error {
140
+ workflowName;
141
+ field;
142
+ constructor(e, t, n) {
143
+ super(`workflow '${e}': ${t}(payload) threw — a flow-control key function must be total over every payload the workflow accepts, because it runs before the run exists and there is nowhere to report a partial failure to. Cause: ${n instanceof Error ? n.message : String(n)}`), this.name = "FlowControlKeyError", this.workflowName = e, this.field = t, this.cause = n;
144
+ }
145
+ }, P = (e, t, n, r) => {
146
+ try {
147
+ let e = n(r);
148
+ if (typeof e != "string" || e.length === 0) throw Error(`returned ${e === "" ? "an empty string" : String(e)}; expected a non-empty string`);
149
+ return e;
150
+ } catch (n) {
151
+ throw new ce(e, t, n);
152
+ }
153
+ }, le = (e, t) => e === void 0 ? t : `pool\u0000${e}\u0000${t}`, F = (e, t) => {
154
+ let n = e.workflowName, r = 0;
155
+ if (e.priority !== void 0) try {
156
+ let n = e.priority(t);
157
+ if (!Number.isFinite(n)) throw Error(`returned ${String(n)}; expected a finite number`);
158
+ r = Math.trunc(n);
159
+ } catch (e) {
160
+ throw new ce(n, "priority", e);
161
+ }
162
+ return {
163
+ ...e.debounce === void 0 ? {} : { debounceKey: P(n, "debounce.key", e.debounce.key, t) },
164
+ ...e.singleton === void 0 ? {} : { singletonKey: P(n, "singleton.key", e.singleton.key, t) },
165
+ ...e.concurrency === void 0 ? {} : { concurrencyKey: le(e.concurrency.pool, e.concurrency.key === void 0 ? "" : P(n, "concurrency.key", e.concurrency.key, t)) },
166
+ ...e.throttle?.key === void 0 ? e.throttle === void 0 ? {} : { throttleKey: "" } : { throttleKey: P(n, "throttle.key", e.throttle.key, t) },
167
+ ...e.rateLimit?.key === void 0 ? e.rateLimit === void 0 ? {} : { rateLimitKey: "" } : { rateLimitKey: P(n, "rateLimit.key", e.rateLimit.key, t) },
168
+ ...e.batch?.key === void 0 ? e.batch === void 0 ? {} : { batchKey: "" } : { batchKey: P(n, "batch.key", e.batch.key, t) },
169
+ priority: r
170
+ };
171
+ }, ue = (e, t, n, r) => {
172
+ let i = e.filter((e) => e > r - n);
173
+ if (i.length < t) return;
174
+ let a = [...i].sort((e, t) => t - e)[t - 1];
175
+ if (a !== void 0) return a + n;
176
+ }, de = (e) => {
177
+ let { control: t, keys: n, state: r, now: i, reconsidering: a } = e;
178
+ if (r.paused === !0) return {
179
+ kind: "defer",
180
+ mode: "paused",
181
+ dueAt: i,
182
+ collapse: a ? "hold" : "append",
183
+ keys: n
184
+ };
185
+ if (t.rateLimit !== void 0) {
186
+ let e = ue(r.recentAdmissions ?? [], t.rateLimit.limit, t.rateLimit.periodMs, i);
187
+ if (e !== void 0) return {
188
+ kind: "drop",
189
+ reason: "rate-limit",
190
+ retryAfterMs: Math.max(0, e - i),
191
+ keys: n
192
+ };
193
+ }
194
+ if (t.singleton !== void 0 && t.singleton.mode === "skip" && r.singletonHolder !== void 0) return {
195
+ kind: "skip",
196
+ incumbent: r.singletonHolder,
197
+ keys: n
198
+ };
199
+ if (t.debounce !== void 0) {
200
+ let e = r.debouncePending, o = e?.firstSeenAt ?? i, s = e?.deadlineAt ?? (t.debounce.timeoutMs === void 0 ? void 0 : o + t.debounce.timeoutMs);
201
+ return a ? s !== void 0 && i >= s ? {
202
+ kind: "admit",
203
+ reason: "debounce-deadline",
204
+ keys: n,
205
+ ...I(t, r)
206
+ } : {
207
+ kind: "admit",
208
+ reason: "debounce-elapsed",
209
+ keys: n,
210
+ ...I(t, r)
211
+ } : {
212
+ kind: "defer",
213
+ mode: "debounce",
214
+ dueAt: s === void 0 ? i + t.debounce.periodMs : Math.min(i + t.debounce.periodMs, s),
215
+ ...s === void 0 ? {} : { deadlineAt: s },
216
+ collapse: "replace",
217
+ keys: n
218
+ };
219
+ }
220
+ if (t.batch !== void 0) {
221
+ let e = r.batchPending, o = (e?.count ?? 0) + +!a, s = (e?.firstSeenAt ?? i) + t.batch.timeoutMs;
222
+ return o >= t.batch.maxSize ? {
223
+ kind: "admit",
224
+ reason: "batch-full",
225
+ keys: n,
226
+ ...I(t, r)
227
+ } : a && i >= s ? {
228
+ kind: "admit",
229
+ reason: "batch-timeout",
230
+ keys: n,
231
+ ...I(t, r)
232
+ } : {
233
+ kind: "defer",
234
+ mode: "batch",
235
+ dueAt: s,
236
+ collapse: a ? "hold" : "append",
237
+ keys: n
238
+ };
239
+ }
240
+ if (t.throttle !== void 0) {
241
+ let e = ue(r.recentAdmissions ?? [], t.throttle.limit, t.throttle.periodMs, i);
242
+ if (e !== void 0) return {
243
+ kind: "defer",
244
+ mode: "throttle",
245
+ dueAt: e,
246
+ collapse: a ? "hold" : "append",
247
+ keys: n
248
+ };
249
+ }
250
+ return t.concurrency !== void 0 && (r.inFlight ?? 0) >= t.concurrency.limit ? {
251
+ kind: "defer",
252
+ mode: "concurrency",
253
+ dueAt: i,
254
+ collapse: a ? "hold" : "append",
255
+ keys: n
256
+ } : {
257
+ kind: "admit",
258
+ reason: fe(t) ? "under-limits" : "no-controls",
259
+ keys: n,
260
+ ...I(t, r)
261
+ };
262
+ }, fe = (e) => e.debounce !== void 0 || e.singleton !== void 0 || e.concurrency !== void 0 || e.throttle !== void 0 || e.rateLimit !== void 0 || e.batch !== void 0, I = (e, t) => e.singleton?.mode === "cancel" && t.singletonHolder !== void 0 ? { evict: t.singletonHolder } : {}, pe = (e, t, n) => {
263
+ let r = e.timeouts?.startMs;
264
+ return r !== void 0 && n - t.firstSeenAt >= r;
265
+ }, me = (e, t, n) => {
266
+ let r = e.timeouts?.finishMs;
267
+ return r === void 0 || t.terminal ? !1 : n - t.startedAt >= r;
268
+ }, he = (e, t) => e.priority === t.priority ? e.firstSeenAt === t.firstSeenAt ? e.id < t.id ? -1 : +(e.id > t.id) : e.firstSeenAt - t.firstSeenAt : t.priority - e.priority, L = "_voltro_workflow_pending", R = "_voltro_workflow_admissions", z = "_voltro_workflow_pauses", ge = 1440 * 60 * 1e3, _e = (e, t, n) => `wfp_${ee("sha256").update(`${e}\u0000${t}\u0000${n}`).digest("hex").slice(0, 40)}`, B = (e) => {
269
+ if (e instanceof Date) return e.getTime();
270
+ if (typeof e == "number") return e;
271
+ let t = Date.parse(String(e));
272
+ return Number.isNaN(t) ? 0 : t;
273
+ }, V = (e, t) => {
274
+ let n = typeof e == "number" ? e : Number(e);
275
+ return Number.isFinite(n) ? Math.trunc(n) : t;
276
+ }, ve = (e) => ({
277
+ id: String(e.id),
278
+ tenantId: e.tenantId === null || e.tenantId === void 0 ? null : String(e.tenantId),
279
+ workflowName: String(e.workflowName),
280
+ controlKey: String(e.controlKey ?? ""),
281
+ mode: String(e.mode),
282
+ payload: e.payload,
283
+ callerContext: e.callerContext ?? null,
284
+ priority: V(e.priority, 0),
285
+ dueAt: B(e.dueAt),
286
+ deadlineAt: e.deadlineAt === null || e.deadlineAt === void 0 ? void 0 : B(e.deadlineAt),
287
+ collapsed: V(e.collapsed, 1),
288
+ firstSeenAt: B(e.firstSeenAt),
289
+ attempts: V(e.attempts, 0),
290
+ lastError: e.lastError === null || e.lastError === void 0 ? null : String(e.lastError)
291
+ }), H = (e, t, n, r) => ({
292
+ table: e,
293
+ predicate: t,
294
+ order: n,
295
+ take: r,
296
+ skip: void 0,
297
+ projection: void 0
298
+ }), ye = async (e) => {
299
+ let t = await e.query(H(z, void 0, [], 1e3));
300
+ return new Set(t.map((e) => String(e.id)));
301
+ }, be = async (e, t, n, r) => {
302
+ await e.upsert(z, {
303
+ id: t,
304
+ pausedAt: /* @__PURE__ */ new Date(),
305
+ pausedBy: n,
306
+ reason: r
307
+ }, {
308
+ conflictColumns: ["id"],
309
+ update: [
310
+ "pausedAt",
311
+ "pausedBy",
312
+ "reason"
313
+ ]
314
+ });
315
+ }, xe = async (e, t) => e.delete(z, t), Se = async (e) => {
316
+ let { store: t, control: n, keys: r, now: i } = e, a = { paused: e.paused }, o = [];
317
+ n.debounce !== void 0 && r.debounceKey !== void 0 && o.push((async () => {
318
+ let e = (await t.query(H(L, g(v("workflowName", n.workflowName), v("controlKey", r.debounceKey), v("mode", "debounce")), [], 1)))[0];
319
+ if (e === void 0) return;
320
+ let i = e.deadlineAt === null || e.deadlineAt === void 0 ? void 0 : B(e.deadlineAt);
321
+ a.debouncePending = {
322
+ firstSeenAt: B(e.firstSeenAt),
323
+ collapsed: V(e.collapsed, 1),
324
+ ...i === void 0 ? {} : { deadlineAt: i }
325
+ };
326
+ })()), n.batch !== void 0 && r.batchKey !== void 0 && o.push((async () => {
327
+ let e = await t.query(H(L, g(v("workflowName", n.workflowName), v("controlKey", r.batchKey), v("mode", "batch")), [{
328
+ column: "firstSeenAt",
329
+ direction: "asc"
330
+ }], n.batch.maxSize + 1));
331
+ e.length !== 0 && (a.batchPending = {
332
+ count: e.length,
333
+ firstSeenAt: B(e[0].firstSeenAt)
334
+ });
335
+ })()), n.singleton !== void 0 && r.singletonKey !== void 0 && o.push((async () => {
336
+ let e = await Ce(t, n.workflowName, r.singletonKey, i);
337
+ e !== void 0 && (a.singletonHolder = e);
338
+ })()), n.concurrency !== void 0 && r.concurrencyKey !== void 0 && o.push((async () => {
339
+ let e = n.concurrency.pool === void 0 ? [v("workflowName", n.workflowName)] : [], o = await t.query(H(R, g(...e, v("concurrencyKey", r.concurrencyKey), C("releasedAt"), y("expiresAt", new Date(i))), [], n.concurrency.limit));
340
+ a.inFlight = o.length;
341
+ })());
342
+ let s = n.rateLimit ?? n.throttle, c = r.rateLimitKey ?? r.throttleKey;
343
+ return s !== void 0 && c !== void 0 && o.push((async () => {
344
+ let e = await t.query(H(R, g(v("workflowName", n.workflowName), v("rateKey", c), v("outcome", "admitted"), y("admittedAt", new Date(i - s.periodMs))), [{
345
+ column: "admittedAt",
346
+ direction: "desc"
347
+ }], s.limit));
348
+ a.recentAdmissions = e.map((e) => B(e.admittedAt));
349
+ })()), await Promise.all(o), a;
350
+ }, Ce = async (e, t, n, r) => {
351
+ let i = (await e.query(H(R, g(v("workflowName", t), v("singletonKey", n), C("releasedAt"), y("expiresAt", new Date(r))), [{
352
+ column: "admittedAt",
353
+ direction: "desc"
354
+ }], 1)))[0];
355
+ if (i === void 0) return;
356
+ let a = i.executionId;
357
+ if (a != null) return {
358
+ executionId: String(a),
359
+ runId: i.runId === null || i.runId === void 0 ? "" : String(i.runId),
360
+ admittedAt: B(i.admittedAt)
361
+ };
362
+ }, we = async (e) => {
363
+ let { store: t, control: n, decision: r, now: i } = e, a = Te(r.mode, r.keys);
364
+ if (r.collapse === "hold") {
365
+ let o = e.existingId ?? _e(n.workflowName, r.mode, a);
366
+ return await t.update(L, o, {
367
+ dueAt: new Date(r.dueAt),
368
+ updatedAt: new Date(i)
369
+ }), o;
370
+ }
371
+ if (r.collapse === "replace") {
372
+ let o = _e(n.workflowName, r.mode, a);
373
+ return await t.upsert(L, {
374
+ id: o,
375
+ tenantId: e.tenantId,
376
+ workflowName: n.workflowName,
377
+ controlKey: a,
378
+ mode: r.mode,
379
+ payload: e.payload,
380
+ callerContext: e.callerContext ?? null,
381
+ priority: r.keys.priority,
382
+ dueAt: new Date(r.dueAt),
383
+ deadlineAt: r.deadlineAt === void 0 ? null : new Date(r.deadlineAt),
384
+ collapsed: 1,
385
+ firstSeenAt: new Date(i),
386
+ updatedAt: new Date(i),
387
+ attempts: 0,
388
+ lastError: null
389
+ }, {
390
+ conflictColumns: ["id"],
391
+ update: (t) => ({
392
+ payload: e.payload,
393
+ callerContext: e.callerContext ?? null,
394
+ priority: r.keys.priority,
395
+ dueAt: new Date(r.dueAt),
396
+ deadlineAt: r.deadlineAt === void 0 ? t.deadlineAt ?? null : new Date(r.deadlineAt),
397
+ collapsed: V(t.collapsed, 1) + 1,
398
+ updatedAt: new Date(i)
399
+ })
400
+ }), o;
401
+ }
402
+ let o = await t.insert(L, {
403
+ tenantId: e.tenantId,
404
+ workflowName: n.workflowName,
405
+ controlKey: a,
406
+ mode: r.mode,
407
+ payload: e.payload,
408
+ callerContext: e.callerContext ?? null,
409
+ priority: r.keys.priority,
410
+ dueAt: new Date(r.dueAt),
411
+ deadlineAt: r.deadlineAt === void 0 ? null : new Date(r.deadlineAt),
412
+ collapsed: 1,
413
+ firstSeenAt: new Date(i),
414
+ updatedAt: new Date(i),
415
+ attempts: 0,
416
+ lastError: null
417
+ });
418
+ return String(o.id);
419
+ }, Te = (e, t) => {
420
+ switch (e) {
421
+ case "debounce": return t.debounceKey ?? "";
422
+ case "batch": return t.batchKey ?? "";
423
+ case "throttle": return t.throttleKey ?? "";
424
+ case "concurrency": return t.concurrencyKey ?? "";
425
+ default: return "";
426
+ }
427
+ }, U = async (e) => {
428
+ let { control: t, keys: n, now: r } = e, i = t.timeouts?.finishMs ?? 864e5, a = await e.store.insert(R, {
429
+ tenantId: e.tenantId,
430
+ workflowName: t.workflowName,
431
+ outcome: e.outcome,
432
+ mode: e.mode,
433
+ reason: e.reason,
434
+ collapsed: e.collapsed,
435
+ waitedMs: e.waitedMs,
436
+ executionId: e.executionId,
437
+ runId: e.runId,
438
+ singletonKey: n.singletonKey ?? null,
439
+ concurrencyKey: n.concurrencyKey ?? null,
440
+ rateKey: n.rateLimitKey ?? n.throttleKey ?? null,
441
+ admittedAt: new Date(r),
442
+ expiresAt: e.outcome === "admitted" ? new Date(r + i) : null,
443
+ releasedAt: e.outcome === "admitted" ? null : new Date(r)
444
+ });
445
+ return String(a.id);
446
+ }, Ee = async (e, t, n) => {
447
+ let r = await e.query(H(R, g(v("executionId", t), v("outcome", "admitted"), C("releasedAt")), [], 10));
448
+ return r.length === 0 ? !1 : (await Promise.all(r.map((t) => e.update(R, String(t.id), { releasedAt: new Date(n) }))), !0);
449
+ }, De = async (e, t, n) => (await e.query(H(L, void 0, [{
450
+ column: "priority",
451
+ direction: "desc"
452
+ }, {
453
+ column: "firstSeenAt",
454
+ direction: "asc"
455
+ }], n))).map(ve).filter((e) => e.dueAt <= t).sort(he), Oe = async (e, t) => (await e.query(H(L, void 0, [{
456
+ column: "firstSeenAt",
457
+ direction: "asc"
458
+ }], t))).map(ve), W = async (e, t) => e.delete(L, t), ke = async (e, t, n, r) => {
459
+ let i = (await e.query(H(L, v("id", t), [], 1)))[0];
460
+ if (i === void 0) return !1;
461
+ let a = ve(i);
462
+ try {
463
+ await e.insert(R, {
464
+ tenantId: a.tenantId,
465
+ workflowName: a.workflowName,
466
+ outcome: "discarded",
467
+ mode: a.mode,
468
+ reason: n,
469
+ collapsed: a.collapsed,
470
+ waitedMs: Math.max(0, r - a.firstSeenAt),
471
+ executionId: null,
472
+ runId: null,
473
+ singletonKey: null,
474
+ concurrencyKey: a.controlKey === "" ? null : a.controlKey,
475
+ rateKey: null,
476
+ admittedAt: new Date(r),
477
+ expiresAt: null,
478
+ releasedAt: new Date(r)
479
+ });
480
+ } catch {}
481
+ return e.delete(L, t);
482
+ }, Ae = async (e, t, n, r) => {
483
+ await e.update(L, t.id, {
484
+ attempts: t.attempts + 1,
485
+ lastError: n.slice(0, 500),
486
+ updatedAt: new Date(r)
487
+ });
488
+ }, G = async (e) => {
489
+ let t = await Se({
490
+ store: e.store,
491
+ control: e.control,
492
+ keys: e.keys,
493
+ now: e.now,
494
+ paused: e.paused
495
+ });
496
+ return de({
497
+ control: e.control,
498
+ keys: e.keys,
499
+ state: t,
500
+ now: e.now,
501
+ reconsidering: e.reconsidering
502
+ });
503
+ }, je = async (e, t, n = 1e3) => {
504
+ let r = await e.query(H(R, void 0, [{
505
+ column: "admittedAt",
506
+ direction: "asc"
507
+ }], n)), i = t.getTime(), a = r.filter((e) => e.releasedAt != null && B(e.admittedAt) < i);
508
+ return await Promise.all(a.map((t) => e.delete(R, String(t.id)))), a.length;
509
+ }, Me = async (e) => {
510
+ let { store: t, control: n, now: r } = e, i = F(n, e.payload), a = await G({
511
+ store: t,
512
+ control: n,
513
+ keys: i,
514
+ paused: e.paused,
515
+ now: r,
516
+ reconsidering: !1
517
+ });
518
+ if (a.kind === "drop") return await U({
519
+ store: t,
520
+ control: n,
521
+ keys: i,
522
+ outcome: "dropped",
523
+ mode: "rateLimit",
524
+ reason: `rate limit reached; retry after ${a.retryAfterMs}ms`,
525
+ collapsed: 1,
526
+ waitedMs: 0,
527
+ executionId: null,
528
+ runId: null,
529
+ tenantId: e.tenantId,
530
+ now: r
531
+ }), {
532
+ kind: "dropped",
533
+ retryAfterMs: a.retryAfterMs
534
+ };
535
+ if (a.kind === "skip") return await U({
536
+ store: t,
537
+ control: n,
538
+ keys: i,
539
+ outcome: "skipped",
540
+ mode: "singleton",
541
+ reason: `singleton key held by ${a.incumbent.executionId}`,
542
+ collapsed: 1,
543
+ waitedMs: 0,
544
+ executionId: a.incumbent.executionId,
545
+ runId: a.incumbent.runId || null,
546
+ tenantId: e.tenantId,
547
+ now: r
548
+ }), {
549
+ kind: "skipped",
550
+ executionId: a.incumbent.executionId,
551
+ runId: a.incumbent.runId
552
+ };
553
+ if (a.kind === "defer") return {
554
+ kind: "queued",
555
+ intentId: await we({
556
+ store: t,
557
+ control: n,
558
+ decision: a,
559
+ payload: e.payload,
560
+ callerContext: e.callerContext,
561
+ tenantId: e.tenantId,
562
+ now: r
563
+ }),
564
+ mode: a.mode,
565
+ dueAt: a.dueAt
566
+ };
567
+ let o = e.payload, s = [], c = 1;
568
+ if (n.batch !== void 0 && i.batchKey !== void 0) {
569
+ let r = await Ne(t, n.workflowName, i.batchKey, n.batch.maxSize);
570
+ o = { items: [...r.map((e) => e.payload), e.payload] }, s = r.map((e) => e.id), c = r.length + 1;
571
+ }
572
+ return {
573
+ kind: "start",
574
+ ledgerId: await U({
575
+ store: t,
576
+ control: n,
577
+ keys: i,
578
+ outcome: "admitted",
579
+ mode: e.waiting ? "immediate" : null,
580
+ reason: a.reason,
581
+ collapsed: c,
582
+ waitedMs: 0,
583
+ executionId: null,
584
+ runId: null,
585
+ tenantId: e.tenantId,
586
+ now: r
587
+ }),
588
+ keys: i,
589
+ payload: o,
590
+ consume: s,
591
+ collapsed: c,
592
+ ...a.evict === void 0 ? {} : { evict: {
593
+ executionId: a.evict.executionId,
594
+ runId: a.evict.runId
595
+ } }
596
+ };
597
+ }, Ne = async (e, t, n, r) => (await e.query({
598
+ table: "_voltro_workflow_pending",
599
+ predicate: g(v("workflowName", t), v("controlKey", n), v("mode", "batch")),
600
+ order: [{
601
+ column: "firstSeenAt",
602
+ direction: "asc"
603
+ }],
604
+ take: r,
605
+ skip: void 0,
606
+ projection: void 0
607
+ })).map((e) => ({
608
+ id: String(e.id),
609
+ payload: e.payload
610
+ })), Pe = async (e, t, n, r) => {
611
+ await e.update("_voltro_workflow_admissions", t, {
612
+ executionId: n,
613
+ runId: r
614
+ });
615
+ }, Fe = O("_voltro_workflow_watermarks", {
616
+ id: x({ prefix: "wfwm" }),
617
+ positionAt: A(),
618
+ updatedAt: A().default("now")
619
+ }), Ie = (e) => {
620
+ let t = e instanceof Error ? e.message : String(e);
621
+ return t.length > 400 ? `${t.slice(0, 400)}…` : t;
622
+ }, Le = (e) => {
623
+ let t = [], n = [], r = [], i = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set(), o = e.payloadSchema === void 0 ? (e) => d.right(e) : (t) => {
624
+ let n = h.decodeUnknownEither(e.payloadSchema)(t);
625
+ return d.isRight(n) ? d.right(n.right) : d.left(Ie(n.left));
626
+ }, s = e.runs.map((e) => ({
627
+ run: e,
628
+ decoded: o(e.payload)
629
+ })), c = e.intents.map((e) => ({
630
+ intent: e,
631
+ decoded: o(e.payload)
632
+ }));
633
+ for (let o of e.entries) for (let l of e.events) {
634
+ if (l.name !== o.event) continue;
635
+ let u = h.decodeUnknownEither(o.schema)(l.payload);
636
+ if (d.isLeft(u)) {
637
+ r.push({
638
+ kind: "event-decode",
639
+ workflowName: e.workflowName,
640
+ event: o.event,
641
+ subject: l.id,
642
+ detail: Ie(u.left)
643
+ });
644
+ continue;
645
+ }
646
+ let f = u.right, p = (e) => e.getTime() > l.occurredAt.getTime() ? !1 : o.withinMs === void 0 || l.occurredAt.getTime() - e.getTime() <= o.withinMs, m = (t, n) => {
647
+ if (d.isLeft(t)) return r.push({
648
+ kind: "payload-decode",
649
+ workflowName: e.workflowName,
650
+ event: o.event,
651
+ subject: n,
652
+ detail: t.left
653
+ }), !1;
654
+ try {
655
+ return o.match(f, t.right) === !0;
656
+ } catch (t) {
657
+ return r.push({
658
+ kind: "match-threw",
659
+ workflowName: e.workflowName,
660
+ event: o.event,
661
+ subject: n,
662
+ detail: Ie(t)
663
+ }), !1;
664
+ }
665
+ };
666
+ for (let { run: e, decoded: n } of s) i.has(e.runId) || p(e.startedAt) && m(n, e.runId) && (i.add(e.runId), t.push({
667
+ runId: e.runId,
668
+ executionId: e.executionId,
669
+ reason: o.reason,
670
+ event: o.event,
671
+ eventId: l.id
672
+ }));
673
+ for (let { intent: e, decoded: t } of c) a.has(e.intentId) || p(e.firstSeenAt) && m(t, e.intentId) && (a.add(e.intentId), n.push({
674
+ intentId: e.intentId,
675
+ reason: o.reason,
676
+ event: o.event,
677
+ eventId: l.id
678
+ }));
679
+ }
680
+ return {
681
+ cancels: t,
682
+ discards: n,
683
+ problems: r
684
+ };
685
+ }, Re = (e) => {
686
+ let t;
687
+ for (let n of e) (t === void 0 || n.occurredAt.getTime() > t.getTime()) && (t = n.occurredAt);
688
+ return t;
689
+ }, ze = "_voltro_workflow_watermarks", Be = "_voltro_workflow_events", K = "cancelOn", Ve = 3600 * 1e3, He = 500, q = (e) => {
690
+ if (e instanceof Date) return e;
691
+ if (typeof e == "number") return new Date(e);
692
+ if (typeof e == "string") {
693
+ let t = new Date(e);
694
+ if (!Number.isNaN(t.getTime())) return t;
695
+ }
696
+ }, J = (e) => e instanceof Error ? e.message : String(e), Ue = async (e, t) => q((await e.query({
697
+ table: ze,
698
+ predicate: v("id", t),
699
+ order: [],
700
+ take: 1,
701
+ skip: void 0,
702
+ projection: void 0
703
+ }))[0]?.positionAt), We = async (e, t, n) => {
704
+ await e.upsert(ze, {
705
+ id: t,
706
+ positionAt: n,
707
+ updatedAt: /* @__PURE__ */ new Date()
708
+ }, {
709
+ conflictColumns: ["id"],
710
+ update: (e) => {
711
+ let t = q(e.positionAt);
712
+ return t !== void 0 && t.getTime() >= n.getTime() ? {
713
+ positionAt: t,
714
+ updatedAt: /* @__PURE__ */ new Date()
715
+ } : {
716
+ positionAt: n,
717
+ updatedAt: /* @__PURE__ */ new Date()
718
+ };
719
+ }
720
+ });
721
+ }, Ge = async (e, t, n) => {
722
+ let r = async (r) => e.query({
723
+ table: "_voltro_workflow_runs",
724
+ predicate: g(v("tag", t), v("status", r)),
725
+ order: [{
726
+ column: "startedAt",
727
+ direction: "asc"
728
+ }],
729
+ take: n,
730
+ skip: void 0,
731
+ projection: void 0
732
+ });
733
+ return [...await r("running"), ...await r("suspended")].flatMap((e) => {
734
+ let t = e, n = q(t.startedAt);
735
+ return typeof t.id != "string" || typeof t.executionId != "string" || n === void 0 ? [] : [{
736
+ runId: t.id,
737
+ executionId: t.executionId,
738
+ payload: t.payload,
739
+ startedAt: n
740
+ }];
741
+ });
742
+ }, Ke = async (e, t, n) => (await e.query({
743
+ table: "_voltro_workflow_pending",
744
+ predicate: v("workflowName", t),
745
+ order: [{
746
+ column: "firstSeenAt",
747
+ direction: "asc"
748
+ }],
749
+ take: n,
750
+ skip: void 0,
751
+ projection: void 0
752
+ })).flatMap((e) => {
753
+ let t = e, n = q(t.firstSeenAt);
754
+ return typeof t.id != "string" || n === void 0 ? [] : [{
755
+ intentId: t.id,
756
+ payload: t.payload,
757
+ firstSeenAt: n
758
+ }];
759
+ }), qe = async (e, t) => {
760
+ let n = t.workflows.filter((e) => e.entries.length > 0);
761
+ if (n.length === 0) return {
762
+ examined: !1,
763
+ events: 0,
764
+ cancelled: 0,
765
+ discarded: 0,
766
+ catchingUp: !1,
767
+ sawFullRunPage: !1,
768
+ problems: [],
769
+ failures: [],
770
+ watermark: void 0
771
+ };
772
+ let r = e.now?.() ?? Date.now(), i = t.batch ?? 500, a = t.coldLookbackMs ?? 36e5, o = /* @__PURE__ */ new Set();
773
+ for (let e of n) for (let t of e.entries) o.add(t.event);
774
+ let s = await Ue(e.store, K), c = s ?? new Date(r - a), l = await e.store.query({
775
+ table: Be,
776
+ predicate: b("occurredAt", c),
777
+ order: [{
778
+ column: "occurredAt",
779
+ direction: "asc"
780
+ }],
781
+ take: i,
782
+ skip: void 0,
783
+ projection: void 0
784
+ }), u = [];
785
+ for (let e of l) {
786
+ let t = e, n = q(t.occurredAt);
787
+ typeof t.id != "string" || typeof t.name != "string" || n === void 0 || o.has(t.name) && u.push({
788
+ id: t.id,
789
+ name: t.name,
790
+ payload: t.payload,
791
+ occurredAt: n
792
+ });
793
+ }
794
+ let d = [], f = [], p = 0, m = 0, h = !1, g = !1, _ = t.runPage ?? 2e3;
795
+ if (u.length > 0) for (let t of n) {
796
+ let n = u.filter((e) => t.entries.some((t) => t.event === e.name));
797
+ if (n.length === 0) continue;
798
+ let r = [], i = [];
799
+ try {
800
+ r = await Ge(e.store, t.workflowName, _), i = await Ke(e.store, t.workflowName, _), (r.length >= _ || i.length >= _) && (h = !0);
801
+ } catch (e) {
802
+ f.push({
803
+ subject: t.workflowName,
804
+ detail: J(e)
805
+ }), g = !0;
806
+ continue;
807
+ }
808
+ let a = Le({
809
+ workflowName: t.workflowName,
810
+ entries: t.entries,
811
+ payloadSchema: t.payloadSchema,
812
+ events: n,
813
+ runs: r,
814
+ intents: i
815
+ });
816
+ d.push(...a.problems);
817
+ for (let n of a.cancels) try {
818
+ await e.cancelRun({
819
+ workflowName: t.workflowName,
820
+ runId: n.runId,
821
+ executionId: n.executionId,
822
+ reason: n.reason,
823
+ event: n.event
824
+ }), p += 1, e.log?.info("workflow.cancelOn: run cancelled", {
825
+ workflow: t.workflowName,
826
+ runId: n.runId,
827
+ event: n.event,
828
+ eventId: n.eventId
829
+ });
830
+ } catch (e) {
831
+ f.push({
832
+ subject: n.runId,
833
+ detail: J(e)
834
+ });
835
+ }
836
+ for (let n of a.discards) try {
837
+ await e.discardIntent({
838
+ workflowName: t.workflowName,
839
+ intentId: n.intentId,
840
+ reason: n.reason,
841
+ event: n.event
842
+ }), m += 1;
843
+ } catch (e) {
844
+ f.push({
845
+ subject: n.intentId,
846
+ detail: J(e)
847
+ });
848
+ }
849
+ }
850
+ let v = Re(u), y = s;
851
+ if (g) e.log?.warn("workflow.cancelOn: holding the watermark — some workflows could not be evaluated", { failures: f.length });
852
+ else if (v !== void 0) try {
853
+ await We(e.store, K, v), y = v;
854
+ } catch (e) {
855
+ f.push({
856
+ subject: K,
857
+ detail: J(e)
858
+ });
859
+ }
860
+ else if (s === void 0) try {
861
+ await We(e.store, K, c), y = c;
862
+ } catch (e) {
863
+ f.push({
864
+ subject: K,
865
+ detail: J(e)
866
+ });
867
+ }
868
+ return d.length > 0 && e.log?.warn("workflow.cancelOn: some events could not be evaluated", {
869
+ count: d.length,
870
+ first: d[0]
871
+ }), {
872
+ examined: !0,
873
+ events: u.length,
874
+ cancelled: p,
875
+ discarded: m,
876
+ catchingUp: l.length >= i,
877
+ sawFullRunPage: h,
878
+ problems: d,
879
+ failures: f,
880
+ watermark: y
881
+ };
882
+ }, Je = {
883
+ scanned: 0,
884
+ admitted: 0,
885
+ deferred: 0,
886
+ dropped: 0,
887
+ skipped: 0,
888
+ expired: 0,
889
+ evicted: 0,
890
+ failed: 0,
891
+ timedOut: 0,
892
+ examined: !1
893
+ }, Ye = 200, Xe = async (e, t = {}) => {
894
+ let n = e.now ?? (() => Date.now()), r = e.log, i = t.batchSize ?? 200, a, o;
895
+ try {
896
+ a = await ye(e.store), o = await De(e.store, n(), i);
897
+ } catch (e) {
898
+ return r?.warn?.("workflow flow control: could not read the admission queue", { cause: String(e) }), Je;
899
+ }
900
+ let s = {
901
+ scanned: o.length,
902
+ admitted: 0,
903
+ deferred: 0,
904
+ dropped: 0,
905
+ skipped: 0,
906
+ expired: 0,
907
+ evicted: 0,
908
+ failed: 0,
909
+ timedOut: 0
910
+ }, c = /* @__PURE__ */ new Map(), l = [];
911
+ for (let e of o) {
912
+ if (e.mode === "batch") {
913
+ let t = `${e.workflowName}\u0000${e.controlKey}`, n = c.get(t);
914
+ n === void 0 ? c.set(t, [e]) : n.push(e);
915
+ continue;
916
+ }
917
+ l.push(e);
918
+ }
919
+ for (let t of l) try {
920
+ await Ze(e, t, a, s, n());
921
+ } catch (i) {
922
+ s.failed++, r?.warn?.("workflow flow control: an intent failed to drain", {
923
+ workflow: t.workflowName,
924
+ intent: t.id,
925
+ cause: String(i)
926
+ }), await Ae(e.store, t, String(i), n()).catch(() => {});
927
+ }
928
+ for (let t of c.values()) try {
929
+ await Qe(e, t, a, s, n());
930
+ } catch (i) {
931
+ s.failed++;
932
+ let a = t[0];
933
+ r?.warn?.("workflow flow control: a batch failed to drain", {
934
+ workflow: a?.workflowName,
935
+ size: t.length,
936
+ cause: String(i)
937
+ }), a !== void 0 && await Ae(e.store, a, String(i), n()).catch(() => {});
938
+ }
939
+ return s.timedOut = await et(e, n()).catch(() => 0), {
940
+ ...s,
941
+ examined: !0
942
+ };
943
+ }, Ze = async (e, t, n, r, i) => {
944
+ let a = e.controls.get(t.workflowName);
945
+ if (a === void 0) {
946
+ await e.onAbandoned({
947
+ workflowName: t.workflowName,
948
+ payload: t.payload,
949
+ callerContext: t.callerContext,
950
+ reason: `workflow '${t.workflowName}' is no longer registered — it was renamed or removed while this start was waiting in the admission queue`
951
+ }), await W(e.store, t.id), r.expired++;
952
+ return;
953
+ }
954
+ if (pe(a, t, i)) {
955
+ await U({
956
+ store: e.store,
957
+ control: a,
958
+ keys: F(a, t.payload),
959
+ outcome: "expired",
960
+ mode: t.mode,
961
+ reason: `timeouts.start elapsed after ${i - t.firstSeenAt}ms`,
962
+ collapsed: t.collapsed,
963
+ waitedMs: i - t.firstSeenAt,
964
+ executionId: null,
965
+ runId: null,
966
+ tenantId: t.tenantId,
967
+ now: i
968
+ }), await e.onAbandoned({
969
+ workflowName: t.workflowName,
970
+ payload: t.payload,
971
+ callerContext: t.callerContext,
972
+ reason: `timeouts.start (${a.timeouts?.startMs}ms) elapsed while this start waited in the admission queue; ${t.collapsed} start(s) had collapsed into it`
973
+ }), await W(e.store, t.id), r.expired++;
974
+ return;
975
+ }
976
+ let o = F(a, t.payload);
977
+ await $e(e, {
978
+ control: a,
979
+ intent: t,
980
+ decision: await G({
981
+ store: e.store,
982
+ control: a,
983
+ keys: o,
984
+ paused: n.has(t.workflowName),
985
+ now: i,
986
+ reconsidering: !0
987
+ }),
988
+ keys: o,
989
+ counters: r,
990
+ now: i,
991
+ items: void 0
992
+ });
993
+ }, Qe = async (e, t, n, r, i) => {
994
+ let a = t[0];
995
+ if (a === void 0) return;
996
+ let o = e.controls.get(a.workflowName);
997
+ if (o === void 0 || o.batch === void 0) {
998
+ for (let n of t) await W(e.store, n.id);
999
+ r.expired += t.length;
1000
+ return;
1001
+ }
1002
+ let s = [...t].sort((e, t) => e.firstSeenAt - t.firstSeenAt), c = s[0];
1003
+ if (pe(o, c, i)) {
1004
+ await e.onAbandoned({
1005
+ workflowName: a.workflowName,
1006
+ payload: { items: s.map((e) => e.payload) },
1007
+ callerContext: c.callerContext,
1008
+ reason: `timeouts.start elapsed with ${s.length} item(s) accumulated in the batch`
1009
+ });
1010
+ for (let t of s) await W(e.store, t.id);
1011
+ r.expired += s.length;
1012
+ return;
1013
+ }
1014
+ let l = F(o, c.payload);
1015
+ await $e(e, {
1016
+ control: o,
1017
+ intent: c,
1018
+ decision: await G({
1019
+ store: e.store,
1020
+ control: o,
1021
+ keys: l,
1022
+ paused: n.has(a.workflowName),
1023
+ now: i,
1024
+ reconsidering: !0
1025
+ }),
1026
+ keys: l,
1027
+ counters: r,
1028
+ now: i,
1029
+ items: s
1030
+ });
1031
+ }, $e = async (e, t) => {
1032
+ let { control: n, intent: r, decision: i, keys: a, counters: o, now: s, items: c } = t;
1033
+ if (i.kind === "defer") {
1034
+ await we({
1035
+ store: e.store,
1036
+ control: n,
1037
+ decision: i,
1038
+ payload: r.payload,
1039
+ callerContext: r.callerContext,
1040
+ tenantId: r.tenantId,
1041
+ now: s,
1042
+ existingId: r.id
1043
+ }), o.deferred++;
1044
+ return;
1045
+ }
1046
+ if (i.kind === "drop") {
1047
+ await U({
1048
+ store: e.store,
1049
+ control: n,
1050
+ keys: a,
1051
+ outcome: "dropped",
1052
+ mode: "rateLimit",
1053
+ reason: `rate limit reached while queued; retry after ${i.retryAfterMs}ms`,
1054
+ collapsed: r.collapsed,
1055
+ waitedMs: s - r.firstSeenAt,
1056
+ executionId: null,
1057
+ runId: null,
1058
+ tenantId: r.tenantId,
1059
+ now: s
1060
+ });
1061
+ for (let t of c ?? [r]) await W(e.store, t.id);
1062
+ o.dropped++;
1063
+ return;
1064
+ }
1065
+ if (i.kind === "skip") {
1066
+ await U({
1067
+ store: e.store,
1068
+ control: n,
1069
+ keys: a,
1070
+ outcome: "skipped",
1071
+ mode: "singleton",
1072
+ reason: `singleton key held by ${i.incumbent.executionId}`,
1073
+ collapsed: r.collapsed,
1074
+ waitedMs: s - r.firstSeenAt,
1075
+ executionId: i.incumbent.executionId,
1076
+ runId: i.incumbent.runId || null,
1077
+ tenantId: r.tenantId,
1078
+ now: s
1079
+ });
1080
+ for (let t of c ?? [r]) await W(e.store, t.id);
1081
+ o.skipped++;
1082
+ return;
1083
+ }
1084
+ i.evict !== void 0 && (await e.cancelRun(n.workflowName, i.evict.executionId), await Ee(e.store, i.evict.executionId, s), await U({
1085
+ store: e.store,
1086
+ control: n,
1087
+ keys: a,
1088
+ outcome: "evicted",
1089
+ mode: "singleton",
1090
+ reason: "cancelled to make room for a newer start (singleton mode 'cancel')",
1091
+ collapsed: 1,
1092
+ waitedMs: null,
1093
+ executionId: i.evict.executionId,
1094
+ runId: i.evict.runId || null,
1095
+ tenantId: r.tenantId,
1096
+ now: s
1097
+ }), o.evicted++);
1098
+ let l = c === void 0 ? r.payload : { items: c.map((e) => e.payload) }, u = c === void 0 ? r.collapsed : c.reduce((e, t) => e + t.collapsed, 0), d = await e.startAdmitted(n.workflowName, l, r.callerContext);
1099
+ await U({
1100
+ store: e.store,
1101
+ control: n,
1102
+ keys: a,
1103
+ outcome: "admitted",
1104
+ mode: r.mode,
1105
+ reason: i.reason,
1106
+ collapsed: u,
1107
+ waitedMs: s - r.firstSeenAt,
1108
+ executionId: d.executionId,
1109
+ runId: d.runId ?? null,
1110
+ tenantId: r.tenantId,
1111
+ now: s
1112
+ });
1113
+ for (let t of c ?? [r]) await W(e.store, t.id);
1114
+ o.admitted++;
1115
+ }, et = async (e, t) => {
1116
+ if (e.listRunningRuns === void 0) return 0;
1117
+ let n = 0;
1118
+ for (let r of e.controls.values()) {
1119
+ if (r.timeouts?.finishMs === void 0) continue;
1120
+ let i = await e.listRunningRuns(r.workflowName);
1121
+ for (let a of i) me(r, {
1122
+ startedAt: a.startedAt,
1123
+ terminal: !1
1124
+ }, t) && (await e.cancelRun(r.workflowName, a.executionId), await Ee(e.store, a.executionId, t), await e.onAbandoned({
1125
+ workflowName: r.workflowName,
1126
+ payload: null,
1127
+ callerContext: null,
1128
+ reason: `timeouts.finish (${r.timeouts.finishMs}ms) elapsed; the run was cancelled after ${t - a.startedAt}ms`
1129
+ }), n++);
1130
+ }
1131
+ return n;
1132
+ }, tt = async (e, t) => {
1133
+ if (e) try {
1134
+ await e.recordEvent(t);
1135
+ } catch {}
1136
+ }, nt = (e, n) => {
1137
+ let a = u.gen(function* () {
1138
+ let i = n.pollIntervalMs ?? 200, a = n.maxPollIntervalMs ?? 5e3, o = n.timeoutMs ?? 1440 * 6e4, s = yield* r, c = yield* u.serviceOption(t), l = c._tag === "Some" ? c.value : void 0;
1139
+ if (s === void 0) return yield* u.die(/* @__PURE__ */ Error("awaitSignal: no active workflow run id in scope"));
1140
+ let d = s;
1141
+ yield* u.promise(() => tt(l, {
1142
+ runId: d,
1143
+ eventType: "signal-awaited",
1144
+ payload: { signalName: n.name }
1145
+ }));
1146
+ let f = Date.now(), p = i;
1147
+ for (;;) {
1148
+ let t = Date.now() - f;
1149
+ if (t > o) return yield* u.die(/* @__PURE__ */ Error(`awaitSignal('${n.name}') timed out after ${t}ms`));
1150
+ let r = {
1151
+ table: "_voltro_workflow_run_events",
1152
+ order: [{
1153
+ column: "occurredAt",
1154
+ direction: "asc"
1155
+ }],
1156
+ predicate: g(v("runId", d), v("eventType", "signal-sent")),
1157
+ projection: void 0,
1158
+ skip: void 0,
1159
+ take: 1e3
1160
+ }, i = (yield* u.tryPromise({
1161
+ try: () => e.store.query(r),
1162
+ catch: (e) => e
1163
+ })).find((e) => e.payload?.signalName === n.name);
1164
+ if (i !== void 0) {
1165
+ let e = yield* h.decodeUnknown(n.schema)(i.payload?.value);
1166
+ return yield* u.promise(() => tt(l, {
1167
+ runId: d,
1168
+ eventType: "signal-received",
1169
+ payload: {
1170
+ signalName: n.name,
1171
+ value: i.payload?.value
1172
+ }
1173
+ })), e;
1174
+ }
1175
+ yield* u.sleep(`${p} millis`), p = Math.min(p * 2, a);
1176
+ }
1177
+ });
1178
+ return i.make({
1179
+ name: `await-signal:${n.name}`,
1180
+ success: n.schema,
1181
+ execute: a
1182
+ });
1183
+ }, rt = async (e, t) => {
1184
+ if (e !== void 0) try {
1185
+ await e.recordEvent(t);
1186
+ } catch {}
1187
+ }, it = (e, n) => {
1188
+ let a = u.gen(function* () {
1189
+ let i = n.pollIntervalMs ?? 200, a = n.maxPollIntervalMs ?? 5e3, o = n.timeoutMs ?? 1440 * 6e4, s = n.take ?? 500, c = yield* r, l = yield* u.serviceOption(t), d = l._tag === "Some" ? l.value : void 0;
1190
+ if (c === void 0) return yield* u.die(/* @__PURE__ */ Error("awaitEvent: no active workflow run id in scope"));
1191
+ let f = c, p = yield* n.since === "run-start" ? at(e, f) : u.succeed(/* @__PURE__ */ new Date());
1192
+ yield* u.promise(() => rt(d, {
1193
+ runId: f,
1194
+ eventType: "event-awaited",
1195
+ payload: {
1196
+ event: n.event,
1197
+ since: n.since ?? "wait-start",
1198
+ cutoff: p.toISOString()
1199
+ }
1200
+ }));
1201
+ let m = Date.now(), _ = i, y = 0;
1202
+ for (;;) {
1203
+ let t = Date.now() - m;
1204
+ if (t > o) return yield* u.die(/* @__PURE__ */ Error(`awaitEvent('${n.event}') timed out after ${t}ms having examined ${y} candidate event(s). ${y === 0 ? "NONE were published under that name in the window — check the spelling against ctx.events.publish, and consider since: 'run-start' if the event may have arrived before this step began." : "The predicate rejected all of them — log one payload and compare it with what `match` expects."}`));
1205
+ let r = {
1206
+ table: "_voltro_workflow_events",
1207
+ predicate: g(v("name", n.event), b("occurredAt", p)),
1208
+ order: [{
1209
+ column: "occurredAt",
1210
+ direction: "asc"
1211
+ }],
1212
+ take: s,
1213
+ skip: void 0,
1214
+ projection: void 0
1215
+ }, i = yield* u.tryPromise({
1216
+ try: () => e.store.query(r),
1217
+ catch: (e) => e
1218
+ });
1219
+ y = i.length;
1220
+ for (let e of i) {
1221
+ let t = yield* h.decodeUnknown(n.schema)(e.payload);
1222
+ if (n.match(t)) return yield* u.promise(() => rt(d, {
1223
+ runId: f,
1224
+ eventType: "event-received",
1225
+ payload: {
1226
+ event: n.event,
1227
+ eventId: e.id
1228
+ }
1229
+ })), t;
1230
+ }
1231
+ yield* u.sleep(`${_} millis`), _ = Math.min(_ * 2, a);
1232
+ }
1233
+ });
1234
+ return i.make({
1235
+ name: `awaitEvent:${n.event}`,
1236
+ success: n.schema,
1237
+ execute: a
1238
+ });
1239
+ }, at = (e, t) => u.gen(function* () {
1240
+ let n = (yield* u.tryPromise({
1241
+ try: () => e.store.query({
1242
+ table: "_voltro_workflow_runs",
1243
+ predicate: v("id", t),
1244
+ order: [],
1245
+ take: 1,
1246
+ skip: void 0,
1247
+ projection: void 0
1248
+ }),
1249
+ catch: (e) => e
1250
+ }))[0]?.startedAt;
1251
+ if (n instanceof Date) return n;
1252
+ if (typeof n == "string" || typeof n == "number") {
1253
+ let e = new Date(n);
1254
+ if (!Number.isNaN(e.getTime())) return e;
1255
+ }
1256
+ return /* @__PURE__ */ new Date(0);
1257
+ }), ot = (e) => new Promise((t) => setTimeout(t, e)), st = () => {
1258
+ let e = globalThis.crypto;
1259
+ return typeof e?.randomUUID == "function" ? e.randomUUID() : `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`;
1260
+ }, ct = () => `wfu_${st()}`, Y = async (e, t) => {
1261
+ let n = t.id ?? t.executionId;
1262
+ if (!n) throw Error("workflow message target requires target.id or target.executionId");
1263
+ let r = await e.query({
1264
+ table: "_voltro_workflow_runs",
1265
+ order: [],
1266
+ predicate: v("id", n),
1267
+ projection: void 0,
1268
+ skip: void 0,
1269
+ take: 1
1270
+ });
1271
+ if (r[0]) return r[0];
1272
+ let i = (await e.query({
1273
+ table: "_voltro_workflow_runs",
1274
+ order: [],
1275
+ predicate: v("executionId", n),
1276
+ projection: void 0,
1277
+ skip: void 0,
1278
+ take: 1
1279
+ }))[0];
1280
+ if (!i) throw Error(`workflow message target not found: ${n}`);
1281
+ return i;
1282
+ }, lt = async (e) => {
1283
+ let t = await Y(e.store, e.target);
1284
+ return { eventId: (await e.recorder.recordEvent({
1285
+ runId: t.id,
1286
+ eventType: "signal-sent",
1287
+ payload: {
1288
+ signalName: e.signalName,
1289
+ value: e.payload
1290
+ }
1291
+ })).id };
1292
+ }, ut = async (e) => {
1293
+ let t = await Y(e.store, e.target), n = ct(), r = await e.recorder.recordEvent({
1294
+ runId: t.id,
1295
+ eventType: "update-requested",
1296
+ payload: {
1297
+ updateId: n,
1298
+ updateName: e.updateName,
1299
+ value: e.payload
1300
+ }
1301
+ }), i = Date.now(), a = e.options?.timeoutMs ?? 3e4, o = e.options?.pollIntervalMs ?? 100;
1302
+ for (;;) {
1303
+ let s = {
1304
+ table: "_voltro_workflow_run_events",
1305
+ order: [{
1306
+ column: "occurredAt",
1307
+ direction: "asc"
1308
+ }],
1309
+ predicate: v("runId", t.id),
1310
+ projection: void 0,
1311
+ skip: void 0,
1312
+ take: 1e3
1313
+ }, c = await e.store.query(s), l = c.find((e) => e.eventType === "update-completed" && e.payload?.updateId === n);
1314
+ if (l) return {
1315
+ eventId: r.id,
1316
+ updateId: n,
1317
+ completedEventId: l.id,
1318
+ result: l.payload?.result
1319
+ };
1320
+ let u = c.find((e) => e.eventType === "update-failed" && e.payload?.updateId === n);
1321
+ if (u) {
1322
+ let t = Error(u.payload?.errorMessage ?? `workflow update '${e.updateName}' failed`);
1323
+ throw Object.assign(t, {
1324
+ updateId: n,
1325
+ eventId: r.id,
1326
+ errorTag: u.payload?.errorTag ?? null
1327
+ }), t;
1328
+ }
1329
+ if (Date.now() - i >= a) throw Error(`Timed out waiting for workflow update '${e.updateName}' (${n})`);
1330
+ await ot(o);
1331
+ }
1332
+ }, dt = 1440 * 6e4, ft = "voltro/suspending-signal", pt = (e, t) => `${ft}/${e}/${t}`, mt = (e) => o.make(e, { success: h.Unknown }), ht = async (e, t) => {
1333
+ if (e) try {
1334
+ await e.recordEvent(t);
1335
+ } catch {}
1336
+ }, gt = (e, n) => u.gen(function* () {
1337
+ let e = n.timeoutMs ?? dt, i = mt(pt((yield* c.WorkflowInstance).workflow.name, n.name)), s = yield* r, l = yield* u.serviceOption(t), d = l._tag === "Some" ? l.value : void 0;
1338
+ s !== void 0 && (yield* u.promise(() => ht(d, {
1339
+ runId: s,
1340
+ eventType: "signal-awaited",
1341
+ payload: { signalName: n.name }
1342
+ })));
1343
+ let f = o.await(i), p = Number.isFinite(e) ? yield* u.race(f, a.sleep({
1344
+ name: `await-signal-timeout/${n.name}`,
1345
+ duration: `${e} millis`
1346
+ }).pipe(u.andThen(u.die(/* @__PURE__ */ Error(`awaitSignalSuspending('${n.name}') timed out after ${e}ms`))))) : yield* f, m = yield* h.decodeUnknown(n.schema)(p);
1347
+ return s !== void 0 && (yield* u.promise(() => ht(d, {
1348
+ runId: s,
1349
+ eventType: "signal-received",
1350
+ payload: {
1351
+ signalName: n.name,
1352
+ value: m
1353
+ }
1354
+ }))), m;
1355
+ }), _t = (e) => u.gen(function* () {
1356
+ let t = e.target.executionId, n = e.target.workflowName;
1357
+ if (t === void 0 || n === void 0) {
1358
+ let r = e.store;
1359
+ if (r === void 0) return yield* u.die(/* @__PURE__ */ Error("completeSuspendingSignal: provide a store, or target.executionId AND target.workflowName"));
1360
+ let i = yield* u.tryPromise({
1361
+ try: () => Y(r, e.target),
1362
+ catch: (e) => e
1363
+ });
1364
+ t ??= i.executionId, n ??= i.tag;
1365
+ }
1366
+ if (t === void 0 || n === void 0) return { completed: !1 };
1367
+ let r = pt(n, e.signalName), i = mt(r), a = new o.TokenParsed({
1368
+ workflowName: n,
1369
+ executionId: t,
1370
+ deferredName: r
1371
+ }).asToken;
1372
+ return yield* o.done(i, {
1373
+ token: a,
1374
+ exit: f.succeed(e.payload)
1375
+ }), { completed: !0 };
1376
+ }), X = async (e, t) => {
1377
+ if (e) try {
1378
+ await e.recordEvent(t);
1379
+ } catch {}
1380
+ }, vt = (e) => {
1381
+ let t = l.failureOption(e), n = Array.from(l.defects(e)), r = t._tag === "Some" ? t.value : n[0] ?? l.squash(e);
1382
+ return {
1383
+ errorTag: r && typeof r == "object" && "_tag" in r ? String(r._tag) : null,
1384
+ errorMessage: r?.message ?? String(r)
1385
+ };
1386
+ }, yt = (e, n) => {
1387
+ let a = u.gen(function* () {
1388
+ let i = n.pollIntervalMs ?? 200, a = n.maxPollIntervalMs ?? 5e3, o = n.timeoutMs ?? 3e4, s = yield* r, c = yield* u.serviceOption(t), l = c._tag === "Some" ? c.value : void 0;
1389
+ if (s === void 0) return yield* u.die(/* @__PURE__ */ Error("awaitUpdate: no active workflow run id in scope"));
1390
+ let d = s, f = Date.now(), p = i;
1391
+ for (;;) {
1392
+ let t = Date.now() - f;
1393
+ if (t > o) return yield* u.die(/* @__PURE__ */ Error(`awaitUpdate('${n.name}') timed out after ${t}ms`));
1394
+ let r = {
1395
+ table: "_voltro_workflow_run_events",
1396
+ order: [{
1397
+ column: "occurredAt",
1398
+ direction: "asc"
1399
+ }],
1400
+ predicate: v("runId", d),
1401
+ projection: void 0,
1402
+ skip: void 0,
1403
+ take: 1e3
1404
+ }, i = yield* u.tryPromise({
1405
+ try: () => e.store.query(r),
1406
+ catch: (e) => e
1407
+ }), s = new Set(i.filter((e) => e.eventType === "update-completed" || e.eventType === "update-failed").map((e) => e.payload?.updateId).filter((e) => typeof e == "string" && e.length > 0)), c = i.find((e) => e.eventType === "update-requested" && e.payload?.updateName === n.name && typeof e.payload.updateId == "string" && !s.has(e.payload.updateId));
1408
+ if (c !== void 0) {
1409
+ let e = c.payload.updateId;
1410
+ yield* u.promise(() => X(l, {
1411
+ runId: d,
1412
+ eventType: "update-received",
1413
+ payload: {
1414
+ updateId: e,
1415
+ updateName: n.name
1416
+ }
1417
+ }));
1418
+ let t = yield* h.decodeUnknown(n.schema)(c.payload?.value).pipe(u.tapErrorCause((t) => u.promise(() => X(l, {
1419
+ runId: d,
1420
+ eventType: "update-failed",
1421
+ payload: {
1422
+ updateId: e,
1423
+ updateName: n.name,
1424
+ ...vt(t)
1425
+ }
1426
+ })))), r = yield* (n.handle ? n.handle(t) : u.succeed(t)).pipe(u.flatMap((e) => n.success ? h.decodeUnknown(n.success)(e) : u.succeed(e))).pipe(u.tapErrorCause((t) => u.promise(() => X(l, {
1427
+ runId: d,
1428
+ eventType: "update-failed",
1429
+ payload: {
1430
+ updateId: e,
1431
+ updateName: n.name,
1432
+ ...vt(t)
1433
+ }
1434
+ }))));
1435
+ return yield* u.promise(() => X(l, {
1436
+ runId: d,
1437
+ eventType: "update-completed",
1438
+ payload: {
1439
+ updateId: e,
1440
+ updateName: n.name,
1441
+ result: r
1442
+ }
1443
+ })), r;
1444
+ }
1445
+ yield* u.sleep(`${p} millis`), p = Math.min(p * 2, a);
1446
+ }
1447
+ });
1448
+ return i.make({
1449
+ name: `await-update:${n.name}`,
1450
+ success: n.success ?? n.schema,
1451
+ execute: a
1452
+ });
1453
+ }, bt = 8 * 1024, xt = () => {
1454
+ let e = globalThis.crypto;
1455
+ return typeof e?.randomUUID == "function" ? e.randomUUID() : `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`;
1456
+ }, St = (e) => `${e}_${xt()}`, Z = (e, t = bt) => {
1457
+ if (e == null) return e;
1458
+ try {
1459
+ let n = JSON.stringify(e);
1460
+ return n.length <= t ? e : {
1461
+ __truncated: !0,
1462
+ bytes: n.length,
1463
+ sample: n.slice(0, t)
1464
+ };
1465
+ } catch {
1466
+ return { __unserialisable: String(e) };
1467
+ }
1468
+ }, Q = (e) => {
1469
+ let t = {};
1470
+ for (let [n, r] of Object.entries(e)) t[n] = r instanceof Date ? r.toISOString() : r;
1471
+ return t;
1472
+ }, Ct = (e) => {
1473
+ let t = e.truncateBytes ?? bt, n = e.makeId ?? St, r = (t, n) => e.log?.warn(t, n), i = e.encryptStepPayload ?? ((e) => e), a = e.emit;
1474
+ return {
1475
+ startStep: async ({ runId: o, stepName: s, attempt: c, stepInput: l, retryPolicy: u }) => {
1476
+ try {
1477
+ let r = await e.store.insert("_voltro_workflow_run_steps", {
1478
+ id: n("ws"),
1479
+ runId: o,
1480
+ stepName: s,
1481
+ attempt: c,
1482
+ status: "running",
1483
+ input: l === void 0 ? null : i(Z(l, t)),
1484
+ retryPolicy: u ?? null,
1485
+ output: null,
1486
+ errorTag: null,
1487
+ errorMessage: null,
1488
+ startedAt: /* @__PURE__ */ new Date(),
1489
+ completedAt: null,
1490
+ durationMs: null
1491
+ });
1492
+ return a?.("workflowSteps", {
1493
+ op: "insert",
1494
+ row: Q(r)
1495
+ }), r.id;
1496
+ } catch (e) {
1497
+ r("failed to record step start (continuing)", {
1498
+ runId: o,
1499
+ stepName: s,
1500
+ attempt: c,
1501
+ reason: e?.message ?? String(e)
1502
+ });
1503
+ return;
1504
+ }
1505
+ },
1506
+ endStepSuccess: async ({ stepRecordId: n, output: o, durationMs: s }) => {
1507
+ try {
1508
+ let r = await e.store.update("_voltro_workflow_run_steps", n, {
1509
+ status: "succeeded",
1510
+ output: i(Z(o, t)),
1511
+ completedAt: /* @__PURE__ */ new Date(),
1512
+ durationMs: s
1513
+ });
1514
+ r && a?.("workflowSteps", {
1515
+ op: "update",
1516
+ row: Q(r)
1517
+ });
1518
+ } catch (e) {
1519
+ r("failed to record step success", {
1520
+ stepRecordId: n,
1521
+ reason: e?.message ?? String(e)
1522
+ });
1523
+ }
1524
+ },
1525
+ endStepFailure: async ({ stepRecordId: n, errorTag: o, errorMessage: s, errorCause: c, durationMs: l }) => {
1526
+ try {
1527
+ let r = await e.store.update("_voltro_workflow_run_steps", n, {
1528
+ status: "failed",
1529
+ errorTag: o,
1530
+ errorMessage: s,
1531
+ errorCause: c === void 0 ? null : i(Z(c, t)),
1532
+ completedAt: /* @__PURE__ */ new Date(),
1533
+ durationMs: l
1534
+ });
1535
+ r && a?.("workflowSteps", {
1536
+ op: "update",
1537
+ row: Q(r)
1538
+ });
1539
+ } catch (e) {
1540
+ r("failed to record step failure", {
1541
+ stepRecordId: n,
1542
+ reason: e?.message ?? String(e)
1543
+ });
1544
+ }
1545
+ },
1546
+ recordEvent: async ({ runId: t, eventType: i, payload: o, stepName: s, attempt: c }) => {
1547
+ let l = n("wfev");
1548
+ try {
1549
+ let n = await e.store.insert("_voltro_workflow_run_events", {
1550
+ id: l,
1551
+ runId: t,
1552
+ eventType: i,
1553
+ payload: o ?? null,
1554
+ occurredAt: /* @__PURE__ */ new Date(),
1555
+ stepName: s ?? null,
1556
+ attempt: c ?? null
1557
+ });
1558
+ a?.("workflowEvents", {
1559
+ op: "insert",
1560
+ row: Q(n)
1561
+ });
1562
+ } catch (e) {
1563
+ r("failed to record workflow event (continuing)", {
1564
+ runId: t,
1565
+ eventType: i,
1566
+ reason: e?.message ?? String(e)
1567
+ });
1568
+ }
1569
+ if (e.wakeups !== void 0) {
1570
+ let n = o?.scheduledWakeAt, r = typeof n == "string" ? new Date(n) : void 0, a = o?.tenantId, s = typeof a == "string" ? a : void 0;
1571
+ i === "timer-set" && r !== void 0 && !Number.isNaN(r.getTime()) ? await e.wakeups.register(t, r, s).catch(() => {}) : (i === "timer-fired" || i === "run-succeeded" || i === "run-failed" || i === "run-cancelled") && await e.wakeups.cancel(t, s).catch(() => {});
1572
+ }
1573
+ return { id: l };
1574
+ }
1575
+ };
1576
+ }, wt = (i, a) => {
1577
+ let o = i.truncateBytes ?? bt, c = i.makeId ?? St, d = i.recorder ?? Ct(i), m = (e, t) => i.log?.warn(e, t), h = i.emit, g = (e, t, n) => u.promise(async () => {
1578
+ if (i.onParentClose) try {
1579
+ await i.onParentClose({
1580
+ workflowName: i.name,
1581
+ executionId: e,
1582
+ ...n === void 0 ? {} : { runId: n },
1583
+ status: t
1584
+ });
1585
+ } catch (n) {
1586
+ m("failed to apply workflow parent-close policy", {
1587
+ tag: i.name,
1588
+ executionId: e,
1589
+ status: t,
1590
+ reason: n?.message ?? String(n)
1591
+ });
1592
+ }
1593
+ }), _ = (e, t, n) => u.promise(async () => {
1594
+ if (i.onTerminal) try {
1595
+ await i.onTerminal({
1596
+ workflowName: i.name,
1597
+ executionId: e,
1598
+ ...n === void 0 ? {} : { runId: n },
1599
+ status: t
1600
+ });
1601
+ } catch (n) {
1602
+ m("failed to release the workflow admission lease", {
1603
+ tag: i.name,
1604
+ executionId: e,
1605
+ status: t,
1606
+ reason: n?.message ?? String(n)
1607
+ });
1608
+ }
1609
+ });
1610
+ return (y, b) => u.gen(function* () {
1611
+ let x = Date.now(), S = yield* p.get(e), C = i.parentExecutionId ?? S ?? null, w = i.parentClosePolicy ?? null, T, E = (e, t) => t.pipe(u.catchAllCause((t) => l.isInterrupted(t) ? u.failCause(t) : u.sync(() => {
1612
+ let n = l.squash(t);
1613
+ m(e, {
1614
+ tag: i.name,
1615
+ executionId: b,
1616
+ reason: n?.message ?? String(n)
1617
+ });
1618
+ }))), D = (i.store.query ? yield* u.promise(() => i.store.query({
1619
+ table: "_voltro_workflow_runs",
1620
+ order: [],
1621
+ predicate: v("executionId", b),
1622
+ projection: void 0,
1623
+ skip: void 0,
1624
+ take: 1
1625
+ })) : [])[0], O = D?.workflowVersion ?? null;
1626
+ if (D?.id !== void 0 && O !== null && i.workflowCompatibleVersions !== void 0 && i.workflowCompatibleVersions !== null && !i.workflowCompatibleVersions.includes(O)) {
1627
+ let e = `Workflow '${i.name}' run '${b}' was started on version ${O}, but current code is compatible with ${i.workflowCompatibleVersions.join(", ")}`, t = yield* u.promise(() => i.store.update("_voltro_workflow_runs", D.id, {
1628
+ status: "failed",
1629
+ errorTag: "WorkflowVersionIncompatible",
1630
+ errorMessage: e,
1631
+ completedAt: /* @__PURE__ */ new Date()
1632
+ }));
1633
+ return t && h?.("workflowRuns", {
1634
+ op: "update",
1635
+ row: Q(t)
1636
+ }), yield* u.promise(() => d.recordEvent({
1637
+ runId: D.id,
1638
+ eventType: "run-failed",
1639
+ payload: {
1640
+ errorTag: "WorkflowVersionIncompatible",
1641
+ errorMessage: e,
1642
+ workflowVersion: i.workflowVersion ?? null,
1643
+ compatibleWith: i.workflowCompatibleVersions,
1644
+ previousVersion: O
1645
+ }
1646
+ })), yield* u.sync(() => i.recordRun?.({
1647
+ name: i.name,
1648
+ status: "failed",
1649
+ durationMs: 0
1650
+ })), yield* u.fail(Error(e));
1651
+ }
1652
+ yield* E("failed to record workflow start (continuing)", u.gen(function* () {
1653
+ let e = yield* u.promise(() => i.store.insert("_voltro_workflow_runs", {
1654
+ id: c("wr"),
1655
+ tag: i.name,
1656
+ executionId: b,
1657
+ status: "running",
1658
+ payload: y,
1659
+ workflowVersion: i.workflowVersion ?? null,
1660
+ workflowPatches: i.workflowPatches ?? null,
1661
+ output: null,
1662
+ subject: i.subject ?? null,
1663
+ source: i.source ?? null,
1664
+ errorTag: null,
1665
+ errorMessage: null,
1666
+ cancelled: !1,
1667
+ startedAt: /* @__PURE__ */ new Date(),
1668
+ completedAt: null,
1669
+ durationMs: null,
1670
+ traceId: i.traceId ?? null,
1671
+ parentExecutionId: C,
1672
+ parentClosePolicy: w
1673
+ }));
1674
+ if (T = e.id, h?.("workflowRuns", {
1675
+ op: "insert",
1676
+ row: Q(e)
1677
+ }), T) {
1678
+ let e = T;
1679
+ yield* u.promise(() => d.recordEvent({
1680
+ runId: e,
1681
+ eventType: "run-started",
1682
+ payload: {
1683
+ tag: i.name,
1684
+ executionId: b,
1685
+ source: i.source ?? null,
1686
+ workflowVersion: i.workflowVersion ?? null,
1687
+ workflowPatches: i.workflowPatches ?? null,
1688
+ parentExecutionId: C,
1689
+ parentClosePolicy: w
1690
+ }
1691
+ }));
1692
+ }
1693
+ }));
1694
+ let k = i.subject?.tenantId, A = a(y, b).pipe(u.locally(r, T), u.locally(e, b), u.locally(n, typeof k == "string" ? k : void 0), u.provideService(t, d)), ee = i.pluginWorkflowStepLayer ? A.pipe(u.provide(i.pluginWorkflowStepLayer)) : A, j = yield* s.intoResult(ee);
1695
+ if (s.isResult(j) && j._tag === "Suspended") {
1696
+ let e = j.cause, t = e !== void 0 && !l.isEmpty(e), n = t ? l.squash(e) : void 0, r = n && typeof n == "object" && "_tag" in n ? String(n._tag) : null, a = t ? n?.message ?? String(n) : null;
1697
+ t && (yield* u.sync(() => ne({
1698
+ error: n,
1699
+ source: "workflow",
1700
+ name: i.name,
1701
+ ...i.traceId ? { traceId: i.traceId } : {},
1702
+ fields: {
1703
+ executionId: b,
1704
+ suspendedOnFailure: !0,
1705
+ ...r ? { errorTag: r } : {},
1706
+ ...T ? { runId: T } : {}
1707
+ }
1708
+ }))), T && (yield* E("failed to record workflow suspend", u.gen(function* () {
1709
+ let e = yield* u.promise(() => i.store.update("_voltro_workflow_runs", T, {
1710
+ status: "suspended",
1711
+ ...t ? {
1712
+ errorTag: r,
1713
+ errorMessage: a
1714
+ } : {}
1715
+ }));
1716
+ e && h?.("workflowRuns", {
1717
+ op: "update",
1718
+ row: Q(e)
1719
+ }), yield* u.promise(() => d.recordEvent({
1720
+ runId: T,
1721
+ eventType: "run-suspended",
1722
+ payload: t ? {
1723
+ reason: "suspend-on-failure",
1724
+ errorTag: r,
1725
+ errorMessage: a
1726
+ } : { reason: "workflow-suspend" }
1727
+ }));
1728
+ })));
1729
+ let o = yield* te;
1730
+ return yield* s.suspend(o);
1731
+ }
1732
+ let M = j;
1733
+ if (f.isFailure(M.exit)) {
1734
+ let e = M.exit.cause, t = l.failureOption(e), n = t._tag === "Some" ? t.value : l.squash(e), r = n && typeof n == "object" && "_tag" in n ? String(n._tag) : null, a = n?.message ?? String(n);
1735
+ return yield* u.sync(() => ne({
1736
+ error: n,
1737
+ source: "workflow",
1738
+ name: i.name,
1739
+ ...i.traceId ? { traceId: i.traceId } : {},
1740
+ fields: {
1741
+ executionId: b,
1742
+ ...r ? { errorTag: r } : {},
1743
+ ...T ? { runId: T } : {}
1744
+ }
1745
+ })), T && (yield* E("failed to record workflow failure", u.gen(function* () {
1746
+ let e = yield* u.promise(() => i.store.update("_voltro_workflow_runs", T, {
1747
+ status: "failed",
1748
+ errorTag: r,
1749
+ errorMessage: a,
1750
+ completedAt: /* @__PURE__ */ new Date(),
1751
+ durationMs: Date.now() - x
1752
+ }));
1753
+ e && h?.("workflowRuns", {
1754
+ op: "update",
1755
+ row: Q(e)
1756
+ }), yield* u.promise(() => d.recordEvent({
1757
+ runId: T,
1758
+ eventType: "run-failed",
1759
+ payload: {
1760
+ errorTag: r,
1761
+ errorMessage: a,
1762
+ durationMs: Date.now() - x
1763
+ }
1764
+ })), yield* g(b, "failed", T);
1765
+ }))), yield* _(b, "failed", T), yield* u.sync(() => i.recordRun?.({
1766
+ name: i.name,
1767
+ status: "failed",
1768
+ durationMs: Date.now() - x
1769
+ })), yield* u.failCause(e);
1770
+ }
1771
+ let N = M.exit.value;
1772
+ return T && (yield* E("failed to record workflow success", u.gen(function* () {
1773
+ let e = yield* u.promise(() => i.store.update("_voltro_workflow_runs", T, {
1774
+ status: "succeeded",
1775
+ output: Z(N, o),
1776
+ completedAt: /* @__PURE__ */ new Date(),
1777
+ durationMs: Date.now() - x
1778
+ }));
1779
+ e && h?.("workflowRuns", {
1780
+ op: "update",
1781
+ row: Q(e)
1782
+ }), yield* u.promise(() => d.recordEvent({
1783
+ runId: T,
1784
+ eventType: "run-succeeded",
1785
+ payload: { durationMs: Date.now() - x }
1786
+ })), yield* g(b, "succeeded", T);
1787
+ }))), yield* _(b, "succeeded", T), yield* u.sync(() => i.recordRun?.({
1788
+ name: i.name,
1789
+ status: "succeeded",
1790
+ durationMs: Date.now() - x,
1791
+ completedAtSec: Date.now() / 1e3
1792
+ })), N;
1793
+ });
1794
+ }, Tt = (e) => e === "cancel" || e === "terminate", Et = (e) => e === "running" || e === "suspended", Dt = async (e) => {
1795
+ let t = await e.store.query({
1796
+ table: "_voltro_workflow_runs",
1797
+ order: [{
1798
+ column: "startedAt",
1799
+ direction: "asc"
1800
+ }],
1801
+ predicate: v("parentExecutionId", e.parentExecutionId),
1802
+ projection: void 0,
1803
+ skip: void 0,
1804
+ take: e.limit ?? 1e3
1805
+ }), n = [];
1806
+ for (let r of t) {
1807
+ let t = {
1808
+ runId: r.id,
1809
+ workflowName: r.tag,
1810
+ executionId: r.executionId,
1811
+ policy: r.parentClosePolicy
1812
+ };
1813
+ if (r.parentClosePolicy === "abandon") {
1814
+ n.push({
1815
+ ...t,
1816
+ action: "abandoned"
1817
+ });
1818
+ continue;
1819
+ }
1820
+ if (!Tt(r.parentClosePolicy)) {
1821
+ n.push({
1822
+ ...t,
1823
+ action: "skipped",
1824
+ reason: "no-parent-close-policy"
1825
+ });
1826
+ continue;
1827
+ }
1828
+ if (!Et(r.status)) {
1829
+ n.push({
1830
+ ...t,
1831
+ action: "skipped",
1832
+ reason: `status:${r.status}`
1833
+ });
1834
+ continue;
1835
+ }
1836
+ try {
1837
+ await e.interruptChild(r.tag, r.executionId, r.parentClosePolicy);
1838
+ let i = await e.store.update("_voltro_workflow_runs", r.id, {
1839
+ status: "cancelled",
1840
+ cancelled: !0,
1841
+ completedAt: /* @__PURE__ */ new Date()
1842
+ });
1843
+ i && e.emit?.("workflowRuns", {
1844
+ op: "update",
1845
+ row: Q(i)
1846
+ }), await e.recorder?.recordEvent({
1847
+ runId: r.id,
1848
+ eventType: "run-cancelled",
1849
+ payload: {
1850
+ reason: "parent-close",
1851
+ parentExecutionId: e.parentExecutionId,
1852
+ parentStatus: e.parentStatus,
1853
+ parentClosePolicy: r.parentClosePolicy,
1854
+ action: r.parentClosePolicy
1855
+ }
1856
+ }), n.push({
1857
+ ...t,
1858
+ action: "cancelled"
1859
+ });
1860
+ } catch (i) {
1861
+ let a = i?.message ?? String(i);
1862
+ e.log?.warn("workflow.parentClose.childInterrupt failed", {
1863
+ parentExecutionId: e.parentExecutionId,
1864
+ childExecutionId: r.executionId,
1865
+ childWorkflowName: r.tag,
1866
+ parentClosePolicy: r.parentClosePolicy,
1867
+ reason: a
1868
+ }), n.push({
1869
+ ...t,
1870
+ action: "failed",
1871
+ reason: a
1872
+ });
1873
+ }
1874
+ }
1875
+ return n;
1876
+ }, Ot = (e) => {
1877
+ if (e == null) return null;
1878
+ if (e instanceof Date) return e;
1879
+ if (typeof e == "string" || typeof e == "number") {
1880
+ let t = new Date(e);
1881
+ return Number.isNaN(t.getTime()) ? null : t;
1882
+ }
1883
+ return null;
1884
+ }, kt = (e) => typeof e == "number" ? e : e == null ? null : Number(e), $ = (e) => e == null ? null : String(e), At = (e) => {
1885
+ let t = /* @__PURE__ */ new Map();
1886
+ for (let n of e) {
1887
+ let e = String(n.stepName), r = t.get(e);
1888
+ r === void 0 ? t.set(e, [n]) : r.push(n);
1889
+ }
1890
+ let n = [];
1891
+ for (let [e, r] of t) {
1892
+ r.sort((e, t) => (kt(e.attempt) ?? 0) - (kt(t.attempt) ?? 0));
1893
+ let t = r[r.length - 1], i = $(t.errorTag), a = $(t.errorMessage), o = i !== null || a !== null ? {
1894
+ tag: i,
1895
+ message: a ?? ""
1896
+ } : null;
1897
+ n.push({
1898
+ name: e,
1899
+ attempt: kt(t.attempt) ?? r.length,
1900
+ attempts: r.length,
1901
+ status: t.status ?? "running",
1902
+ input: t.input ?? null,
1903
+ output: t.output ?? null,
1904
+ error: o,
1905
+ durationMs: kt(t.durationMs)
1906
+ });
1907
+ }
1908
+ return n.sort((t, n) => {
1909
+ let r = e.find((e) => String(e.stepName) === t.name), i = e.find((e) => String(e.stepName) === n.name);
1910
+ return (Ot(r?.startedAt)?.getTime() ?? 0) - (Ot(i?.startedAt)?.getTime() ?? 0);
1911
+ }), n;
1912
+ }, jt = (e) => {
1913
+ if (e == null) return null;
1914
+ if (typeof e == "string") try {
1915
+ return JSON.parse(e);
1916
+ } catch {
1917
+ return null;
1918
+ }
1919
+ return typeof e == "object" ? e : null;
1920
+ }, Mt = async (e, t) => {
1921
+ let n = E(M), r = (await t.query(n.where(T(v("id", e), v("executionId", e))).limit(1).descriptor))[0];
1922
+ if (r === void 0) return null;
1923
+ let i = String(r.id), a = E(N), o = await t.query(a.where(v("runId", i)).descriptor);
1924
+ return {
1925
+ id: i,
1926
+ executionId: $(r.executionId) ?? "",
1927
+ name: $(r.tag) ?? "",
1928
+ status: r.status ?? "running",
1929
+ input: r.payload ?? null,
1930
+ output: r.output ?? null,
1931
+ subject: jt(r.subject),
1932
+ source: $(r.source),
1933
+ steps: At(o),
1934
+ startedAt: Ot(r.startedAt) ?? /* @__PURE__ */ new Date(0),
1935
+ finishedAt: Ot(r.completedAt),
1936
+ traceId: $(r.traceId),
1937
+ parentExecutionId: $(r.parentExecutionId),
1938
+ parentClosePolicy: $(r.parentClosePolicy)
1939
+ };
1940
+ }, Nt = () => {
1941
+ let e = [], n = [], r = 0, i = 0;
1942
+ return {
1943
+ layer: m.succeed(t, {
1944
+ startStep: async ({ runId: t, stepName: n, attempt: i, stepInput: a, retryPolicy: o }) => {
1945
+ let s = `wfstep_mem_${++r}`;
1946
+ return e.push({
1947
+ id: s,
1948
+ runId: t,
1949
+ stepName: n,
1950
+ attempt: i,
1951
+ status: "running",
1952
+ input: a ?? null,
1953
+ retryPolicy: o ?? null,
1954
+ output: null,
1955
+ errorTag: null,
1956
+ errorMessage: null,
1957
+ errorCause: null,
1958
+ startedAt: /* @__PURE__ */ new Date(),
1959
+ completedAt: null,
1960
+ durationMs: null
1961
+ }), s;
1962
+ },
1963
+ endStepSuccess: async ({ stepRecordId: t, output: n, durationMs: r }) => {
1964
+ let i = e.find((e) => e.id === t);
1965
+ i !== void 0 && (i.status = "succeeded", i.output = n, i.completedAt = /* @__PURE__ */ new Date(), i.durationMs = r);
1966
+ },
1967
+ endStepFailure: async ({ stepRecordId: t, errorTag: n, errorMessage: r, errorCause: i, durationMs: a }) => {
1968
+ let o = e.find((e) => e.id === t);
1969
+ o !== void 0 && (o.status = "failed", o.errorTag = n, o.errorMessage = r, o.errorCause = i ?? null, o.completedAt = /* @__PURE__ */ new Date(), o.durationMs = a);
1970
+ },
1971
+ recordEvent: async ({ runId: e, eventType: t, payload: r, stepName: a, attempt: o }) => {
1972
+ let s = `wfev_mem_${++i}`;
1973
+ return n.push({
1974
+ id: s,
1975
+ runId: e,
1976
+ eventType: t,
1977
+ payload: r ?? null,
1978
+ stepName: a ?? null,
1979
+ attempt: o ?? null,
1980
+ occurredAt: /* @__PURE__ */ new Date()
1981
+ }), { id: s };
1982
+ }
1983
+ }),
1984
+ readSteps: () => e,
1985
+ readEvents: () => n
1986
+ };
1987
+ };
1988
+ //#endregion
1989
+ export { he as $, Fe as A, De as B, Be as C, We as D, qe as E, z as F, we as G, Ae as H, L as I, ye as J, je as K, Oe as L, Pe as M, R as N, Re as O, ge as P, ce as Q, W as R, He as S, Ue as T, be as U, G as V, _e as W, Ee as X, U as Y, xe as Z, nt as _, Q as a, F as at, K as b, yt as c, ae as ct, pt as d, N as dt, de as et, ct as f, M as ft, it as g, ut as h, Ct as i, le as it, Me as j, Le as k, gt as l, ie as lt, lt as m, Mt as n, pe as nt, Z as o, oe as ot, Y as p, j as pt, Se as q, Dt as r, ue as rt, wt as s, se as st, Nt as t, me as tt, _t as u, re as ut, Ye as v, ze as w, Ve as x, Xe as y, ke as z };