@voltro/workflow 0.33.0 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,1999 +0,0 @@
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 Oe(e, t, n)).due, Oe = async (e, t, n) => {
450
- let r = (await e.query(H(L, void 0, [{
451
- column: "priority",
452
- direction: "desc"
453
- }, {
454
- column: "firstSeenAt",
455
- direction: "asc"
456
- }], n))).map(ve), i;
457
- for (let e of r) e.dueAt <= t || (i === void 0 || e.dueAt < i) && (i = e.dueAt);
458
- return {
459
- due: r.filter((e) => e.dueAt <= t).sort(he),
460
- nextDueAt: i
461
- };
462
- }, ke = async (e, t) => (await e.query(H(L, void 0, [{
463
- column: "firstSeenAt",
464
- direction: "asc"
465
- }], t))).map(ve), W = async (e, t) => e.delete(L, t), Ae = async (e, t, n, r) => {
466
- let i = (await e.query(H(L, v("id", t), [], 1)))[0];
467
- if (i === void 0) return !1;
468
- let a = ve(i);
469
- try {
470
- await e.insert(R, {
471
- tenantId: a.tenantId,
472
- workflowName: a.workflowName,
473
- outcome: "discarded",
474
- mode: a.mode,
475
- reason: n,
476
- collapsed: a.collapsed,
477
- waitedMs: Math.max(0, r - a.firstSeenAt),
478
- executionId: null,
479
- runId: null,
480
- singletonKey: null,
481
- concurrencyKey: a.controlKey === "" ? null : a.controlKey,
482
- rateKey: null,
483
- admittedAt: new Date(r),
484
- expiresAt: null,
485
- releasedAt: new Date(r)
486
- });
487
- } catch {}
488
- return e.delete(L, t);
489
- }, je = async (e, t, n, r) => {
490
- await e.update(L, t.id, {
491
- attempts: t.attempts + 1,
492
- lastError: n.slice(0, 500),
493
- updatedAt: new Date(r)
494
- });
495
- }, G = async (e) => {
496
- let t = await Se({
497
- store: e.store,
498
- control: e.control,
499
- keys: e.keys,
500
- now: e.now,
501
- paused: e.paused
502
- });
503
- return de({
504
- control: e.control,
505
- keys: e.keys,
506
- state: t,
507
- now: e.now,
508
- reconsidering: e.reconsidering
509
- });
510
- }, Me = async (e, t, n = 1e3) => {
511
- let r = await e.query(H(R, void 0, [{
512
- column: "admittedAt",
513
- direction: "asc"
514
- }], n)), i = t.getTime(), a = r.filter((e) => e.releasedAt != null && B(e.admittedAt) < i);
515
- return await Promise.all(a.map((t) => e.delete(R, String(t.id)))), a.length;
516
- }, Ne = async (e) => {
517
- let { store: t, control: n, now: r } = e, i = F(n, e.payload), a = await G({
518
- store: t,
519
- control: n,
520
- keys: i,
521
- paused: e.paused,
522
- now: r,
523
- reconsidering: !1
524
- });
525
- if (a.kind === "drop") return await U({
526
- store: t,
527
- control: n,
528
- keys: i,
529
- outcome: "dropped",
530
- mode: "rateLimit",
531
- reason: `rate limit reached; retry after ${a.retryAfterMs}ms`,
532
- collapsed: 1,
533
- waitedMs: 0,
534
- executionId: null,
535
- runId: null,
536
- tenantId: e.tenantId,
537
- now: r
538
- }), {
539
- kind: "dropped",
540
- retryAfterMs: a.retryAfterMs
541
- };
542
- if (a.kind === "skip") return await U({
543
- store: t,
544
- control: n,
545
- keys: i,
546
- outcome: "skipped",
547
- mode: "singleton",
548
- reason: `singleton key held by ${a.incumbent.executionId}`,
549
- collapsed: 1,
550
- waitedMs: 0,
551
- executionId: a.incumbent.executionId,
552
- runId: a.incumbent.runId || null,
553
- tenantId: e.tenantId,
554
- now: r
555
- }), {
556
- kind: "skipped",
557
- executionId: a.incumbent.executionId,
558
- runId: a.incumbent.runId
559
- };
560
- if (a.kind === "defer") return {
561
- kind: "queued",
562
- intentId: await we({
563
- store: t,
564
- control: n,
565
- decision: a,
566
- payload: e.payload,
567
- callerContext: e.callerContext,
568
- tenantId: e.tenantId,
569
- now: r
570
- }),
571
- mode: a.mode,
572
- dueAt: a.dueAt
573
- };
574
- let o = e.payload, s = [], c = 1;
575
- if (n.batch !== void 0 && i.batchKey !== void 0) {
576
- let r = await Pe(t, n.workflowName, i.batchKey, n.batch.maxSize);
577
- o = { items: [...r.map((e) => e.payload), e.payload] }, s = r.map((e) => e.id), c = r.length + 1;
578
- }
579
- return {
580
- kind: "start",
581
- ledgerId: await U({
582
- store: t,
583
- control: n,
584
- keys: i,
585
- outcome: "admitted",
586
- mode: e.waiting ? "immediate" : null,
587
- reason: a.reason,
588
- collapsed: c,
589
- waitedMs: 0,
590
- executionId: null,
591
- runId: null,
592
- tenantId: e.tenantId,
593
- now: r
594
- }),
595
- keys: i,
596
- payload: o,
597
- consume: s,
598
- collapsed: c,
599
- ...a.evict === void 0 ? {} : { evict: {
600
- executionId: a.evict.executionId,
601
- runId: a.evict.runId
602
- } }
603
- };
604
- }, Pe = async (e, t, n, r) => (await e.query({
605
- table: "_voltro_workflow_pending",
606
- predicate: g(v("workflowName", t), v("controlKey", n), v("mode", "batch")),
607
- order: [{
608
- column: "firstSeenAt",
609
- direction: "asc"
610
- }],
611
- take: r,
612
- skip: void 0,
613
- projection: void 0
614
- })).map((e) => ({
615
- id: String(e.id),
616
- payload: e.payload
617
- })), Fe = async (e, t, n, r) => {
618
- await e.update("_voltro_workflow_admissions", t, {
619
- executionId: n,
620
- runId: r
621
- });
622
- }, Ie = O("_voltro_workflow_watermarks", {
623
- id: x({ prefix: "wfwm" }),
624
- positionAt: A(),
625
- updatedAt: A().default("now")
626
- }), Le = (e) => {
627
- let t = e instanceof Error ? e.message : String(e);
628
- return t.length > 400 ? `${t.slice(0, 400)}…` : t;
629
- }, Re = (e) => {
630
- let t = [], n = [], r = [], i = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set(), o = e.payloadSchema === void 0 ? (e) => d.right(e) : (t) => {
631
- let n = h.decodeUnknownEither(e.payloadSchema)(t);
632
- return d.isRight(n) ? d.right(n.right) : d.left(Le(n.left));
633
- }, s = e.runs.map((e) => ({
634
- run: e,
635
- decoded: o(e.payload)
636
- })), c = e.intents.map((e) => ({
637
- intent: e,
638
- decoded: o(e.payload)
639
- }));
640
- for (let o of e.entries) for (let l of e.events) {
641
- if (l.name !== o.event) continue;
642
- let u = h.decodeUnknownEither(o.schema)(l.payload);
643
- if (d.isLeft(u)) {
644
- r.push({
645
- kind: "event-decode",
646
- workflowName: e.workflowName,
647
- event: o.event,
648
- subject: l.id,
649
- detail: Le(u.left)
650
- });
651
- continue;
652
- }
653
- 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) => {
654
- if (d.isLeft(t)) return r.push({
655
- kind: "payload-decode",
656
- workflowName: e.workflowName,
657
- event: o.event,
658
- subject: n,
659
- detail: t.left
660
- }), !1;
661
- try {
662
- return o.match(f, t.right) === !0;
663
- } catch (t) {
664
- return r.push({
665
- kind: "match-threw",
666
- workflowName: e.workflowName,
667
- event: o.event,
668
- subject: n,
669
- detail: Le(t)
670
- }), !1;
671
- }
672
- };
673
- 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({
674
- runId: e.runId,
675
- executionId: e.executionId,
676
- reason: o.reason,
677
- event: o.event,
678
- eventId: l.id
679
- }));
680
- 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({
681
- intentId: e.intentId,
682
- reason: o.reason,
683
- event: o.event,
684
- eventId: l.id
685
- }));
686
- }
687
- return {
688
- cancels: t,
689
- discards: n,
690
- problems: r
691
- };
692
- }, ze = (e) => {
693
- let t;
694
- for (let n of e) (t === void 0 || n.occurredAt.getTime() > t.getTime()) && (t = n.occurredAt);
695
- return t;
696
- }, Be = "_voltro_workflow_watermarks", Ve = "_voltro_workflow_events", K = "cancelOn", He = 3600 * 1e3, Ue = 500, q = (e) => {
697
- if (e instanceof Date) return e;
698
- if (typeof e == "number") return new Date(e);
699
- if (typeof e == "string") {
700
- let t = new Date(e);
701
- if (!Number.isNaN(t.getTime())) return t;
702
- }
703
- }, J = (e) => e instanceof Error ? e.message : String(e), We = async (e, t) => q((await e.query({
704
- table: Be,
705
- predicate: v("id", t),
706
- order: [],
707
- take: 1,
708
- skip: void 0,
709
- projection: void 0
710
- }))[0]?.positionAt), Ge = async (e, t, n) => {
711
- await e.upsert(Be, {
712
- id: t,
713
- positionAt: n,
714
- updatedAt: /* @__PURE__ */ new Date()
715
- }, {
716
- conflictColumns: ["id"],
717
- update: (e) => {
718
- let t = q(e.positionAt);
719
- return t !== void 0 && t.getTime() >= n.getTime() ? {
720
- positionAt: t,
721
- updatedAt: /* @__PURE__ */ new Date()
722
- } : {
723
- positionAt: n,
724
- updatedAt: /* @__PURE__ */ new Date()
725
- };
726
- }
727
- });
728
- }, Ke = async (e, t, n) => {
729
- let r = async (r) => e.query({
730
- table: "_voltro_workflow_runs",
731
- predicate: g(v("tag", t), v("status", r)),
732
- order: [{
733
- column: "startedAt",
734
- direction: "asc"
735
- }],
736
- take: n,
737
- skip: void 0,
738
- projection: void 0
739
- });
740
- return [...await r("running"), ...await r("suspended")].flatMap((e) => {
741
- let t = e, n = q(t.startedAt);
742
- return typeof t.id != "string" || typeof t.executionId != "string" || n === void 0 ? [] : [{
743
- runId: t.id,
744
- executionId: t.executionId,
745
- payload: t.payload,
746
- startedAt: n
747
- }];
748
- });
749
- }, qe = async (e, t, n) => (await e.query({
750
- table: "_voltro_workflow_pending",
751
- predicate: v("workflowName", t),
752
- order: [{
753
- column: "firstSeenAt",
754
- direction: "asc"
755
- }],
756
- take: n,
757
- skip: void 0,
758
- projection: void 0
759
- })).flatMap((e) => {
760
- let t = e, n = q(t.firstSeenAt);
761
- return typeof t.id != "string" || n === void 0 ? [] : [{
762
- intentId: t.id,
763
- payload: t.payload,
764
- firstSeenAt: n
765
- }];
766
- }), Je = async (e, t) => {
767
- let n = t.workflows.filter((e) => e.entries.length > 0);
768
- if (n.length === 0) return {
769
- examined: !1,
770
- events: 0,
771
- cancelled: 0,
772
- discarded: 0,
773
- catchingUp: !1,
774
- sawFullRunPage: !1,
775
- problems: [],
776
- failures: [],
777
- watermark: void 0
778
- };
779
- let r = e.now?.() ?? Date.now(), i = t.batch ?? 500, a = t.coldLookbackMs ?? 36e5, o = /* @__PURE__ */ new Set();
780
- for (let e of n) for (let t of e.entries) o.add(t.event);
781
- let s = await We(e.store, K), c = s ?? new Date(r - a), l = await e.store.query({
782
- table: Ve,
783
- predicate: b("occurredAt", c),
784
- order: [{
785
- column: "occurredAt",
786
- direction: "asc"
787
- }],
788
- take: i,
789
- skip: void 0,
790
- projection: void 0
791
- }), u = [];
792
- for (let e of l) {
793
- let t = e, n = q(t.occurredAt);
794
- typeof t.id != "string" || typeof t.name != "string" || n === void 0 || o.has(t.name) && u.push({
795
- id: t.id,
796
- name: t.name,
797
- payload: t.payload,
798
- occurredAt: n
799
- });
800
- }
801
- let d = [], f = [], p = 0, m = 0, h = !1, g = !1, _ = t.runPage ?? 2e3;
802
- if (u.length > 0) for (let t of n) {
803
- let n = u.filter((e) => t.entries.some((t) => t.event === e.name));
804
- if (n.length === 0) continue;
805
- let r = [], i = [];
806
- try {
807
- r = await Ke(e.store, t.workflowName, _), i = await qe(e.store, t.workflowName, _), (r.length >= _ || i.length >= _) && (h = !0);
808
- } catch (e) {
809
- f.push({
810
- subject: t.workflowName,
811
- detail: J(e)
812
- }), g = !0;
813
- continue;
814
- }
815
- let a = Re({
816
- workflowName: t.workflowName,
817
- entries: t.entries,
818
- payloadSchema: t.payloadSchema,
819
- events: n,
820
- runs: r,
821
- intents: i
822
- });
823
- d.push(...a.problems);
824
- for (let n of a.cancels) try {
825
- await e.cancelRun({
826
- workflowName: t.workflowName,
827
- runId: n.runId,
828
- executionId: n.executionId,
829
- reason: n.reason,
830
- event: n.event
831
- }), p += 1, e.log?.info("workflow.cancelOn: run cancelled", {
832
- workflow: t.workflowName,
833
- runId: n.runId,
834
- event: n.event,
835
- eventId: n.eventId
836
- });
837
- } catch (e) {
838
- f.push({
839
- subject: n.runId,
840
- detail: J(e)
841
- });
842
- }
843
- for (let n of a.discards) try {
844
- await e.discardIntent({
845
- workflowName: t.workflowName,
846
- intentId: n.intentId,
847
- reason: n.reason,
848
- event: n.event
849
- }), m += 1;
850
- } catch (e) {
851
- f.push({
852
- subject: n.intentId,
853
- detail: J(e)
854
- });
855
- }
856
- }
857
- let v = ze(u), y = s;
858
- if (g) e.log?.warn("workflow.cancelOn: holding the watermark — some workflows could not be evaluated", { failures: f.length });
859
- else if (v !== void 0) try {
860
- await Ge(e.store, K, v), y = v;
861
- } catch (e) {
862
- f.push({
863
- subject: K,
864
- detail: J(e)
865
- });
866
- }
867
- else if (s === void 0) try {
868
- await Ge(e.store, K, c), y = c;
869
- } catch (e) {
870
- f.push({
871
- subject: K,
872
- detail: J(e)
873
- });
874
- }
875
- return d.length > 0 && e.log?.warn("workflow.cancelOn: some events could not be evaluated", {
876
- count: d.length,
877
- first: d[0]
878
- }), {
879
- examined: !0,
880
- events: u.length,
881
- cancelled: p,
882
- discarded: m,
883
- catchingUp: l.length >= i,
884
- sawFullRunPage: h,
885
- problems: d,
886
- failures: f,
887
- watermark: y
888
- };
889
- }, Ye = {
890
- scanned: 0,
891
- admitted: 0,
892
- deferred: 0,
893
- dropped: 0,
894
- skipped: 0,
895
- expired: 0,
896
- evicted: 0,
897
- failed: 0,
898
- timedOut: 0,
899
- examined: !1
900
- }, Xe = 200, Ze = async (e, t = {}) => {
901
- let n = e.now ?? (() => Date.now()), r = e.log, i = t.batchSize ?? 200, a, o, s;
902
- try {
903
- a = await ye(e.store);
904
- let t = await Oe(e.store, n(), i);
905
- o = t.due, s = t.nextDueAt;
906
- } catch (e) {
907
- return r?.warn?.("workflow flow control: could not read the admission queue", { cause: String(e) }), Ye;
908
- }
909
- let c = {
910
- scanned: o.length,
911
- admitted: 0,
912
- deferred: 0,
913
- dropped: 0,
914
- skipped: 0,
915
- expired: 0,
916
- evicted: 0,
917
- failed: 0,
918
- timedOut: 0
919
- }, l = /* @__PURE__ */ new Map(), u = [];
920
- for (let e of o) {
921
- if (e.mode === "batch") {
922
- let t = `${e.workflowName}\u0000${e.controlKey}`, n = l.get(t);
923
- n === void 0 ? l.set(t, [e]) : n.push(e);
924
- continue;
925
- }
926
- u.push(e);
927
- }
928
- for (let t of u) try {
929
- await Qe(e, t, a, c, n());
930
- } catch (i) {
931
- c.failed++, r?.warn?.("workflow flow control: an intent failed to drain", {
932
- workflow: t.workflowName,
933
- intent: t.id,
934
- cause: String(i)
935
- }), await je(e.store, t, String(i), n()).catch(() => {});
936
- }
937
- for (let t of l.values()) try {
938
- await $e(e, t, a, c, n());
939
- } catch (i) {
940
- c.failed++;
941
- let a = t[0];
942
- r?.warn?.("workflow flow control: a batch failed to drain", {
943
- workflow: a?.workflowName,
944
- size: t.length,
945
- cause: String(i)
946
- }), a !== void 0 && await je(e.store, a, String(i), n()).catch(() => {});
947
- }
948
- return c.timedOut = await tt(e, n()).catch(() => 0), {
949
- ...c,
950
- examined: !0,
951
- ...s === void 0 ? {} : { nextDueAt: s }
952
- };
953
- }, Qe = async (e, t, n, r, i) => {
954
- let a = e.controls.get(t.workflowName);
955
- if (a === void 0) {
956
- await e.onAbandoned({
957
- workflowName: t.workflowName,
958
- payload: t.payload,
959
- callerContext: t.callerContext,
960
- reason: `workflow '${t.workflowName}' is no longer registered — it was renamed or removed while this start was waiting in the admission queue`
961
- }), await W(e.store, t.id), r.expired++;
962
- return;
963
- }
964
- if (pe(a, t, i)) {
965
- await U({
966
- store: e.store,
967
- control: a,
968
- keys: F(a, t.payload),
969
- outcome: "expired",
970
- mode: t.mode,
971
- reason: `timeouts.start elapsed after ${i - t.firstSeenAt}ms`,
972
- collapsed: t.collapsed,
973
- waitedMs: i - t.firstSeenAt,
974
- executionId: null,
975
- runId: null,
976
- tenantId: t.tenantId,
977
- now: i
978
- }), await e.onAbandoned({
979
- workflowName: t.workflowName,
980
- payload: t.payload,
981
- callerContext: t.callerContext,
982
- reason: `timeouts.start (${a.timeouts?.startMs}ms) elapsed while this start waited in the admission queue; ${t.collapsed} start(s) had collapsed into it`
983
- }), await W(e.store, t.id), r.expired++;
984
- return;
985
- }
986
- let o = F(a, t.payload);
987
- await et(e, {
988
- control: a,
989
- intent: t,
990
- decision: await G({
991
- store: e.store,
992
- control: a,
993
- keys: o,
994
- paused: n.has(t.workflowName),
995
- now: i,
996
- reconsidering: !0
997
- }),
998
- keys: o,
999
- counters: r,
1000
- now: i,
1001
- items: void 0
1002
- });
1003
- }, $e = async (e, t, n, r, i) => {
1004
- let a = t[0];
1005
- if (a === void 0) return;
1006
- let o = e.controls.get(a.workflowName);
1007
- if (o === void 0 || o.batch === void 0) {
1008
- for (let n of t) await W(e.store, n.id);
1009
- r.expired += t.length;
1010
- return;
1011
- }
1012
- let s = [...t].sort((e, t) => e.firstSeenAt - t.firstSeenAt), c = s[0];
1013
- if (pe(o, c, i)) {
1014
- await e.onAbandoned({
1015
- workflowName: a.workflowName,
1016
- payload: { items: s.map((e) => e.payload) },
1017
- callerContext: c.callerContext,
1018
- reason: `timeouts.start elapsed with ${s.length} item(s) accumulated in the batch`
1019
- });
1020
- for (let t of s) await W(e.store, t.id);
1021
- r.expired += s.length;
1022
- return;
1023
- }
1024
- let l = F(o, c.payload);
1025
- await et(e, {
1026
- control: o,
1027
- intent: c,
1028
- decision: await G({
1029
- store: e.store,
1030
- control: o,
1031
- keys: l,
1032
- paused: n.has(a.workflowName),
1033
- now: i,
1034
- reconsidering: !0
1035
- }),
1036
- keys: l,
1037
- counters: r,
1038
- now: i,
1039
- items: s
1040
- });
1041
- }, et = async (e, t) => {
1042
- let { control: n, intent: r, decision: i, keys: a, counters: o, now: s, items: c } = t;
1043
- if (i.kind === "defer") {
1044
- await we({
1045
- store: e.store,
1046
- control: n,
1047
- decision: i,
1048
- payload: r.payload,
1049
- callerContext: r.callerContext,
1050
- tenantId: r.tenantId,
1051
- now: s,
1052
- existingId: r.id
1053
- }), o.deferred++;
1054
- return;
1055
- }
1056
- if (i.kind === "drop") {
1057
- await U({
1058
- store: e.store,
1059
- control: n,
1060
- keys: a,
1061
- outcome: "dropped",
1062
- mode: "rateLimit",
1063
- reason: `rate limit reached while queued; retry after ${i.retryAfterMs}ms`,
1064
- collapsed: r.collapsed,
1065
- waitedMs: s - r.firstSeenAt,
1066
- executionId: null,
1067
- runId: null,
1068
- tenantId: r.tenantId,
1069
- now: s
1070
- });
1071
- for (let t of c ?? [r]) await W(e.store, t.id);
1072
- o.dropped++;
1073
- return;
1074
- }
1075
- if (i.kind === "skip") {
1076
- await U({
1077
- store: e.store,
1078
- control: n,
1079
- keys: a,
1080
- outcome: "skipped",
1081
- mode: "singleton",
1082
- reason: `singleton key held by ${i.incumbent.executionId}`,
1083
- collapsed: r.collapsed,
1084
- waitedMs: s - r.firstSeenAt,
1085
- executionId: i.incumbent.executionId,
1086
- runId: i.incumbent.runId || null,
1087
- tenantId: r.tenantId,
1088
- now: s
1089
- });
1090
- for (let t of c ?? [r]) await W(e.store, t.id);
1091
- o.skipped++;
1092
- return;
1093
- }
1094
- i.evict !== void 0 && (await e.cancelRun(n.workflowName, i.evict.executionId), await Ee(e.store, i.evict.executionId, s), await U({
1095
- store: e.store,
1096
- control: n,
1097
- keys: a,
1098
- outcome: "evicted",
1099
- mode: "singleton",
1100
- reason: "cancelled to make room for a newer start (singleton mode 'cancel')",
1101
- collapsed: 1,
1102
- waitedMs: null,
1103
- executionId: i.evict.executionId,
1104
- runId: i.evict.runId || null,
1105
- tenantId: r.tenantId,
1106
- now: s
1107
- }), o.evicted++);
1108
- 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);
1109
- await U({
1110
- store: e.store,
1111
- control: n,
1112
- keys: a,
1113
- outcome: "admitted",
1114
- mode: r.mode,
1115
- reason: i.reason,
1116
- collapsed: u,
1117
- waitedMs: s - r.firstSeenAt,
1118
- executionId: d.executionId,
1119
- runId: d.runId ?? null,
1120
- tenantId: r.tenantId,
1121
- now: s
1122
- });
1123
- for (let t of c ?? [r]) await W(e.store, t.id);
1124
- o.admitted++;
1125
- }, tt = async (e, t) => {
1126
- if (e.listRunningRuns === void 0) return 0;
1127
- let n = 0;
1128
- for (let r of e.controls.values()) {
1129
- if (r.timeouts?.finishMs === void 0) continue;
1130
- let i = await e.listRunningRuns(r.workflowName);
1131
- for (let a of i) me(r, {
1132
- startedAt: a.startedAt,
1133
- terminal: !1
1134
- }, t) && (await e.cancelRun(r.workflowName, a.executionId), await Ee(e.store, a.executionId, t), await e.onAbandoned({
1135
- workflowName: r.workflowName,
1136
- payload: null,
1137
- callerContext: null,
1138
- reason: `timeouts.finish (${r.timeouts.finishMs}ms) elapsed; the run was cancelled after ${t - a.startedAt}ms`
1139
- }), n++);
1140
- }
1141
- return n;
1142
- }, nt = async (e, t) => {
1143
- if (e) try {
1144
- await e.recordEvent(t);
1145
- } catch {}
1146
- }, rt = (e, n) => {
1147
- let a = u.gen(function* () {
1148
- 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;
1149
- if (s === void 0) return yield* u.die(/* @__PURE__ */ Error("awaitSignal: no active workflow run id in scope"));
1150
- let d = s;
1151
- yield* u.promise(() => nt(l, {
1152
- runId: d,
1153
- eventType: "signal-awaited",
1154
- payload: { signalName: n.name }
1155
- }));
1156
- let f = Date.now(), p = i;
1157
- for (;;) {
1158
- let t = Date.now() - f;
1159
- if (t > o) return yield* u.die(/* @__PURE__ */ Error(`awaitSignal('${n.name}') timed out after ${t}ms`));
1160
- let r = {
1161
- table: "_voltro_workflow_run_events",
1162
- order: [{
1163
- column: "occurredAt",
1164
- direction: "asc"
1165
- }],
1166
- predicate: g(v("runId", d), v("eventType", "signal-sent")),
1167
- projection: void 0,
1168
- skip: void 0,
1169
- take: 1e3
1170
- }, i = (yield* u.tryPromise({
1171
- try: () => e.store.query(r),
1172
- catch: (e) => e
1173
- })).find((e) => e.payload?.signalName === n.name);
1174
- if (i !== void 0) {
1175
- let e = yield* h.decodeUnknown(n.schema)(i.payload?.value);
1176
- return yield* u.promise(() => nt(l, {
1177
- runId: d,
1178
- eventType: "signal-received",
1179
- payload: {
1180
- signalName: n.name,
1181
- value: i.payload?.value
1182
- }
1183
- })), e;
1184
- }
1185
- yield* u.sleep(`${p} millis`), p = Math.min(p * 2, a);
1186
- }
1187
- });
1188
- return i.make({
1189
- name: `await-signal:${n.name}`,
1190
- success: n.schema,
1191
- execute: a
1192
- });
1193
- }, it = async (e, t) => {
1194
- if (e !== void 0) try {
1195
- await e.recordEvent(t);
1196
- } catch {}
1197
- }, at = (e, n) => {
1198
- let a = u.gen(function* () {
1199
- 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;
1200
- if (c === void 0) return yield* u.die(/* @__PURE__ */ Error("awaitEvent: no active workflow run id in scope"));
1201
- let f = c, p = yield* n.since === "run-start" ? ot(e, f) : u.succeed(/* @__PURE__ */ new Date());
1202
- yield* u.promise(() => it(d, {
1203
- runId: f,
1204
- eventType: "event-awaited",
1205
- payload: {
1206
- event: n.event,
1207
- since: n.since ?? "wait-start",
1208
- cutoff: p.toISOString()
1209
- }
1210
- }));
1211
- let m = Date.now(), _ = i, y = 0;
1212
- for (;;) {
1213
- let t = Date.now() - m;
1214
- 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."}`));
1215
- let r = {
1216
- table: "_voltro_workflow_events",
1217
- predicate: g(v("name", n.event), b("occurredAt", p)),
1218
- order: [{
1219
- column: "occurredAt",
1220
- direction: "asc"
1221
- }],
1222
- take: s,
1223
- skip: void 0,
1224
- projection: void 0
1225
- }, i = yield* u.tryPromise({
1226
- try: () => e.store.query(r),
1227
- catch: (e) => e
1228
- });
1229
- y = i.length;
1230
- for (let e of i) {
1231
- let t = yield* h.decodeUnknown(n.schema)(e.payload);
1232
- if (n.match(t)) return yield* u.promise(() => it(d, {
1233
- runId: f,
1234
- eventType: "event-received",
1235
- payload: {
1236
- event: n.event,
1237
- eventId: e.id
1238
- }
1239
- })), t;
1240
- }
1241
- yield* u.sleep(`${_} millis`), _ = Math.min(_ * 2, a);
1242
- }
1243
- });
1244
- return i.make({
1245
- name: `awaitEvent:${n.event}`,
1246
- success: n.schema,
1247
- execute: a
1248
- });
1249
- }, ot = (e, t) => u.gen(function* () {
1250
- let n = (yield* u.tryPromise({
1251
- try: () => e.store.query({
1252
- table: "_voltro_workflow_runs",
1253
- predicate: v("id", t),
1254
- order: [],
1255
- take: 1,
1256
- skip: void 0,
1257
- projection: void 0
1258
- }),
1259
- catch: (e) => e
1260
- }))[0]?.startedAt;
1261
- if (n instanceof Date) return n;
1262
- if (typeof n == "string" || typeof n == "number") {
1263
- let e = new Date(n);
1264
- if (!Number.isNaN(e.getTime())) return e;
1265
- }
1266
- return /* @__PURE__ */ new Date(0);
1267
- }), st = (e) => new Promise((t) => setTimeout(t, e)), ct = () => {
1268
- let e = globalThis.crypto;
1269
- return typeof e?.randomUUID == "function" ? e.randomUUID() : `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`;
1270
- }, lt = () => `wfu_${ct()}`, Y = async (e, t) => {
1271
- let n = t.id ?? t.executionId;
1272
- if (!n) throw Error("workflow message target requires target.id or target.executionId");
1273
- let r = await e.query({
1274
- table: "_voltro_workflow_runs",
1275
- order: [],
1276
- predicate: v("id", n),
1277
- projection: void 0,
1278
- skip: void 0,
1279
- take: 1
1280
- });
1281
- if (r[0]) return r[0];
1282
- let i = (await e.query({
1283
- table: "_voltro_workflow_runs",
1284
- order: [],
1285
- predicate: v("executionId", n),
1286
- projection: void 0,
1287
- skip: void 0,
1288
- take: 1
1289
- }))[0];
1290
- if (!i) throw Error(`workflow message target not found: ${n}`);
1291
- return i;
1292
- }, ut = async (e) => {
1293
- let t = await Y(e.store, e.target);
1294
- return { eventId: (await e.recorder.recordEvent({
1295
- runId: t.id,
1296
- eventType: "signal-sent",
1297
- payload: {
1298
- signalName: e.signalName,
1299
- value: e.payload
1300
- }
1301
- })).id };
1302
- }, dt = async (e) => {
1303
- let t = await Y(e.store, e.target), n = lt(), r = await e.recorder.recordEvent({
1304
- runId: t.id,
1305
- eventType: "update-requested",
1306
- payload: {
1307
- updateId: n,
1308
- updateName: e.updateName,
1309
- value: e.payload
1310
- }
1311
- }), i = Date.now(), a = e.options?.timeoutMs ?? 3e4, o = e.options?.pollIntervalMs ?? 100;
1312
- for (;;) {
1313
- let s = {
1314
- table: "_voltro_workflow_run_events",
1315
- order: [{
1316
- column: "occurredAt",
1317
- direction: "asc"
1318
- }],
1319
- predicate: v("runId", t.id),
1320
- projection: void 0,
1321
- skip: void 0,
1322
- take: 1e3
1323
- }, c = await e.store.query(s), l = c.find((e) => e.eventType === "update-completed" && e.payload?.updateId === n);
1324
- if (l) return {
1325
- eventId: r.id,
1326
- updateId: n,
1327
- completedEventId: l.id,
1328
- result: l.payload?.result
1329
- };
1330
- let u = c.find((e) => e.eventType === "update-failed" && e.payload?.updateId === n);
1331
- if (u) {
1332
- let t = Error(u.payload?.errorMessage ?? `workflow update '${e.updateName}' failed`);
1333
- throw Object.assign(t, {
1334
- updateId: n,
1335
- eventId: r.id,
1336
- errorTag: u.payload?.errorTag ?? null
1337
- }), t;
1338
- }
1339
- if (Date.now() - i >= a) throw Error(`Timed out waiting for workflow update '${e.updateName}' (${n})`);
1340
- await st(o);
1341
- }
1342
- }, ft = 1440 * 6e4, pt = "voltro/suspending-signal", mt = (e, t) => `${pt}/${e}/${t}`, ht = (e) => o.make(e, { success: h.Unknown }), gt = async (e, t) => {
1343
- if (e) try {
1344
- await e.recordEvent(t);
1345
- } catch {}
1346
- }, _t = (e, n) => u.gen(function* () {
1347
- let e = n.timeoutMs ?? ft, i = ht(mt((yield* c.WorkflowInstance).workflow.name, n.name)), s = yield* r, l = yield* u.serviceOption(t), d = l._tag === "Some" ? l.value : void 0;
1348
- s !== void 0 && (yield* u.promise(() => gt(d, {
1349
- runId: s,
1350
- eventType: "signal-awaited",
1351
- payload: { signalName: n.name }
1352
- })));
1353
- let f = o.await(i), p = Number.isFinite(e) ? yield* u.race(f, a.sleep({
1354
- name: `await-signal-timeout/${n.name}`,
1355
- duration: `${e} millis`
1356
- }).pipe(u.andThen(u.die(/* @__PURE__ */ Error(`awaitSignalSuspending('${n.name}') timed out after ${e}ms`))))) : yield* f, m = yield* h.decodeUnknown(n.schema)(p);
1357
- return s !== void 0 && (yield* u.promise(() => gt(d, {
1358
- runId: s,
1359
- eventType: "signal-received",
1360
- payload: {
1361
- signalName: n.name,
1362
- value: m
1363
- }
1364
- }))), m;
1365
- }), vt = (e) => u.gen(function* () {
1366
- let t = e.target.executionId, n = e.target.workflowName;
1367
- if (t === void 0 || n === void 0) {
1368
- let r = e.store;
1369
- if (r === void 0) return yield* u.die(/* @__PURE__ */ Error("completeSuspendingSignal: provide a store, or target.executionId AND target.workflowName"));
1370
- let i = yield* u.tryPromise({
1371
- try: () => Y(r, e.target),
1372
- catch: (e) => e
1373
- });
1374
- t ??= i.executionId, n ??= i.tag;
1375
- }
1376
- if (t === void 0 || n === void 0) return { completed: !1 };
1377
- let r = mt(n, e.signalName), i = ht(r), a = new o.TokenParsed({
1378
- workflowName: n,
1379
- executionId: t,
1380
- deferredName: r
1381
- }).asToken;
1382
- return yield* o.done(i, {
1383
- token: a,
1384
- exit: f.succeed(e.payload)
1385
- }), { completed: !0 };
1386
- }), X = async (e, t) => {
1387
- if (e) try {
1388
- await e.recordEvent(t);
1389
- } catch {}
1390
- }, yt = (e) => {
1391
- let t = l.failureOption(e), n = Array.from(l.defects(e)), r = t._tag === "Some" ? t.value : n[0] ?? l.squash(e);
1392
- return {
1393
- errorTag: r && typeof r == "object" && "_tag" in r ? String(r._tag) : null,
1394
- errorMessage: r?.message ?? String(r)
1395
- };
1396
- }, bt = (e, n) => {
1397
- let a = u.gen(function* () {
1398
- 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;
1399
- if (s === void 0) return yield* u.die(/* @__PURE__ */ Error("awaitUpdate: no active workflow run id in scope"));
1400
- let d = s, f = Date.now(), p = i;
1401
- for (;;) {
1402
- let t = Date.now() - f;
1403
- if (t > o) return yield* u.die(/* @__PURE__ */ Error(`awaitUpdate('${n.name}') timed out after ${t}ms`));
1404
- let r = {
1405
- table: "_voltro_workflow_run_events",
1406
- order: [{
1407
- column: "occurredAt",
1408
- direction: "asc"
1409
- }],
1410
- predicate: v("runId", d),
1411
- projection: void 0,
1412
- skip: void 0,
1413
- take: 1e3
1414
- }, i = yield* u.tryPromise({
1415
- try: () => e.store.query(r),
1416
- catch: (e) => e
1417
- }), 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));
1418
- if (c !== void 0) {
1419
- let e = c.payload.updateId;
1420
- yield* u.promise(() => X(l, {
1421
- runId: d,
1422
- eventType: "update-received",
1423
- payload: {
1424
- updateId: e,
1425
- updateName: n.name
1426
- }
1427
- }));
1428
- let t = yield* h.decodeUnknown(n.schema)(c.payload?.value).pipe(u.tapErrorCause((t) => u.promise(() => X(l, {
1429
- runId: d,
1430
- eventType: "update-failed",
1431
- payload: {
1432
- updateId: e,
1433
- updateName: n.name,
1434
- ...yt(t)
1435
- }
1436
- })))), 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, {
1437
- runId: d,
1438
- eventType: "update-failed",
1439
- payload: {
1440
- updateId: e,
1441
- updateName: n.name,
1442
- ...yt(t)
1443
- }
1444
- }))));
1445
- return yield* u.promise(() => X(l, {
1446
- runId: d,
1447
- eventType: "update-completed",
1448
- payload: {
1449
- updateId: e,
1450
- updateName: n.name,
1451
- result: r
1452
- }
1453
- })), r;
1454
- }
1455
- yield* u.sleep(`${p} millis`), p = Math.min(p * 2, a);
1456
- }
1457
- });
1458
- return i.make({
1459
- name: `await-update:${n.name}`,
1460
- success: n.success ?? n.schema,
1461
- execute: a
1462
- });
1463
- }, xt = 8 * 1024, St = () => {
1464
- let e = globalThis.crypto;
1465
- return typeof e?.randomUUID == "function" ? e.randomUUID() : `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`;
1466
- }, Ct = (e) => `${e}_${St()}`, Z = (e, t = xt) => {
1467
- if (e == null) return e;
1468
- try {
1469
- let n = JSON.stringify(e);
1470
- return n.length <= t ? e : {
1471
- __truncated: !0,
1472
- bytes: n.length,
1473
- sample: n.slice(0, t)
1474
- };
1475
- } catch {
1476
- return { __unserialisable: String(e) };
1477
- }
1478
- }, Q = (e) => {
1479
- let t = {};
1480
- for (let [n, r] of Object.entries(e)) t[n] = r instanceof Date ? r.toISOString() : r;
1481
- return t;
1482
- }, wt = (e) => {
1483
- let t = e.truncateBytes ?? xt, n = e.makeId ?? Ct, r = (t, n) => e.log?.warn(t, n), i = e.encryptStepPayload ?? ((e) => e), a = e.emit;
1484
- return {
1485
- startStep: async ({ runId: o, stepName: s, attempt: c, stepInput: l, retryPolicy: u }) => {
1486
- try {
1487
- let r = await e.store.insert("_voltro_workflow_run_steps", {
1488
- id: n("ws"),
1489
- runId: o,
1490
- stepName: s,
1491
- attempt: c,
1492
- status: "running",
1493
- input: l === void 0 ? null : i(Z(l, t)),
1494
- retryPolicy: u ?? null,
1495
- output: null,
1496
- errorTag: null,
1497
- errorMessage: null,
1498
- startedAt: /* @__PURE__ */ new Date(),
1499
- completedAt: null,
1500
- durationMs: null
1501
- });
1502
- return a?.("workflowSteps", {
1503
- op: "insert",
1504
- row: Q(r)
1505
- }), r.id;
1506
- } catch (e) {
1507
- r("failed to record step start (continuing)", {
1508
- runId: o,
1509
- stepName: s,
1510
- attempt: c,
1511
- reason: e?.message ?? String(e)
1512
- });
1513
- return;
1514
- }
1515
- },
1516
- endStepSuccess: async ({ stepRecordId: n, output: o, durationMs: s }) => {
1517
- try {
1518
- let r = await e.store.update("_voltro_workflow_run_steps", n, {
1519
- status: "succeeded",
1520
- output: i(Z(o, t)),
1521
- completedAt: /* @__PURE__ */ new Date(),
1522
- durationMs: s
1523
- });
1524
- r && a?.("workflowSteps", {
1525
- op: "update",
1526
- row: Q(r)
1527
- });
1528
- } catch (e) {
1529
- r("failed to record step success", {
1530
- stepRecordId: n,
1531
- reason: e?.message ?? String(e)
1532
- });
1533
- }
1534
- },
1535
- endStepFailure: async ({ stepRecordId: n, errorTag: o, errorMessage: s, errorCause: c, durationMs: l }) => {
1536
- try {
1537
- let r = await e.store.update("_voltro_workflow_run_steps", n, {
1538
- status: "failed",
1539
- errorTag: o,
1540
- errorMessage: s,
1541
- errorCause: c === void 0 ? null : i(Z(c, t)),
1542
- completedAt: /* @__PURE__ */ new Date(),
1543
- durationMs: l
1544
- });
1545
- r && a?.("workflowSteps", {
1546
- op: "update",
1547
- row: Q(r)
1548
- });
1549
- } catch (e) {
1550
- r("failed to record step failure", {
1551
- stepRecordId: n,
1552
- reason: e?.message ?? String(e)
1553
- });
1554
- }
1555
- },
1556
- recordEvent: async ({ runId: t, eventType: i, payload: o, stepName: s, attempt: c }) => {
1557
- let l = n("wfev");
1558
- try {
1559
- let n = await e.store.insert("_voltro_workflow_run_events", {
1560
- id: l,
1561
- runId: t,
1562
- eventType: i,
1563
- payload: o ?? null,
1564
- occurredAt: /* @__PURE__ */ new Date(),
1565
- stepName: s ?? null,
1566
- attempt: c ?? null
1567
- });
1568
- a?.("workflowEvents", {
1569
- op: "insert",
1570
- row: Q(n)
1571
- });
1572
- } catch (e) {
1573
- r("failed to record workflow event (continuing)", {
1574
- runId: t,
1575
- eventType: i,
1576
- reason: e?.message ?? String(e)
1577
- });
1578
- }
1579
- if (e.wakeups !== void 0) {
1580
- let n = o?.scheduledWakeAt, r = typeof n == "string" ? new Date(n) : void 0, a = o?.tenantId, s = typeof a == "string" ? a : void 0;
1581
- 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(() => {});
1582
- }
1583
- return { id: l };
1584
- }
1585
- };
1586
- }, Tt = (i, a) => {
1587
- let o = i.truncateBytes ?? xt, c = i.makeId ?? Ct, d = i.recorder ?? wt(i), m = (e, t) => i.log?.warn(e, t), h = i.emit, g = (e, t, n) => u.promise(async () => {
1588
- if (i.onParentClose) try {
1589
- await i.onParentClose({
1590
- workflowName: i.name,
1591
- executionId: e,
1592
- ...n === void 0 ? {} : { runId: n },
1593
- status: t
1594
- });
1595
- } catch (n) {
1596
- m("failed to apply workflow parent-close policy", {
1597
- tag: i.name,
1598
- executionId: e,
1599
- status: t,
1600
- reason: n?.message ?? String(n)
1601
- });
1602
- }
1603
- }), _ = (e, t, n) => u.promise(async () => {
1604
- if (i.onTerminal) try {
1605
- await i.onTerminal({
1606
- workflowName: i.name,
1607
- executionId: e,
1608
- ...n === void 0 ? {} : { runId: n },
1609
- status: t
1610
- });
1611
- } catch (n) {
1612
- m("failed to release the workflow admission lease", {
1613
- tag: i.name,
1614
- executionId: e,
1615
- status: t,
1616
- reason: n?.message ?? String(n)
1617
- });
1618
- }
1619
- });
1620
- return (y, b) => u.gen(function* () {
1621
- 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(() => {
1622
- let n = l.squash(t);
1623
- m(e, {
1624
- tag: i.name,
1625
- executionId: b,
1626
- reason: n?.message ?? String(n)
1627
- });
1628
- }))), D = (i.store.query ? yield* u.promise(() => i.store.query({
1629
- table: "_voltro_workflow_runs",
1630
- order: [],
1631
- predicate: v("executionId", b),
1632
- projection: void 0,
1633
- skip: void 0,
1634
- take: 1
1635
- })) : [])[0], O = D?.workflowVersion ?? null;
1636
- if (D?.id !== void 0 && O !== null && i.workflowCompatibleVersions !== void 0 && i.workflowCompatibleVersions !== null && !i.workflowCompatibleVersions.includes(O)) {
1637
- 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, {
1638
- status: "failed",
1639
- errorTag: "WorkflowVersionIncompatible",
1640
- errorMessage: e,
1641
- completedAt: /* @__PURE__ */ new Date()
1642
- }));
1643
- return t && h?.("workflowRuns", {
1644
- op: "update",
1645
- row: Q(t)
1646
- }), yield* u.promise(() => d.recordEvent({
1647
- runId: D.id,
1648
- eventType: "run-failed",
1649
- payload: {
1650
- errorTag: "WorkflowVersionIncompatible",
1651
- errorMessage: e,
1652
- workflowVersion: i.workflowVersion ?? null,
1653
- compatibleWith: i.workflowCompatibleVersions,
1654
- previousVersion: O
1655
- }
1656
- })), yield* u.sync(() => i.recordRun?.({
1657
- name: i.name,
1658
- status: "failed",
1659
- durationMs: 0
1660
- })), yield* u.fail(Error(e));
1661
- }
1662
- yield* E("failed to record workflow start (continuing)", u.gen(function* () {
1663
- let e = yield* u.promise(() => i.store.insert("_voltro_workflow_runs", {
1664
- id: c("wr"),
1665
- tag: i.name,
1666
- executionId: b,
1667
- status: "running",
1668
- payload: y,
1669
- workflowVersion: i.workflowVersion ?? null,
1670
- workflowPatches: i.workflowPatches ?? null,
1671
- output: null,
1672
- subject: i.subject ?? null,
1673
- source: i.source ?? null,
1674
- errorTag: null,
1675
- errorMessage: null,
1676
- cancelled: !1,
1677
- startedAt: /* @__PURE__ */ new Date(),
1678
- completedAt: null,
1679
- durationMs: null,
1680
- traceId: i.traceId ?? null,
1681
- parentExecutionId: C,
1682
- parentClosePolicy: w
1683
- }));
1684
- if (T = e.id, h?.("workflowRuns", {
1685
- op: "insert",
1686
- row: Q(e)
1687
- }), T) {
1688
- let e = T;
1689
- yield* u.promise(() => d.recordEvent({
1690
- runId: e,
1691
- eventType: "run-started",
1692
- payload: {
1693
- tag: i.name,
1694
- executionId: b,
1695
- source: i.source ?? null,
1696
- workflowVersion: i.workflowVersion ?? null,
1697
- workflowPatches: i.workflowPatches ?? null,
1698
- parentExecutionId: C,
1699
- parentClosePolicy: w
1700
- }
1701
- }));
1702
- }
1703
- }));
1704
- 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);
1705
- if (s.isResult(j) && j._tag === "Suspended") {
1706
- 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;
1707
- t && (yield* u.sync(() => ne({
1708
- error: n,
1709
- source: "workflow",
1710
- name: i.name,
1711
- ...i.traceId ? { traceId: i.traceId } : {},
1712
- fields: {
1713
- executionId: b,
1714
- suspendedOnFailure: !0,
1715
- ...r ? { errorTag: r } : {},
1716
- ...T ? { runId: T } : {}
1717
- }
1718
- }))), T && (yield* E("failed to record workflow suspend", u.gen(function* () {
1719
- let e = yield* u.promise(() => i.store.update("_voltro_workflow_runs", T, {
1720
- status: "suspended",
1721
- ...t ? {
1722
- errorTag: r,
1723
- errorMessage: a
1724
- } : {}
1725
- }));
1726
- e && h?.("workflowRuns", {
1727
- op: "update",
1728
- row: Q(e)
1729
- }), yield* u.promise(() => d.recordEvent({
1730
- runId: T,
1731
- eventType: "run-suspended",
1732
- payload: t ? {
1733
- reason: "suspend-on-failure",
1734
- errorTag: r,
1735
- errorMessage: a
1736
- } : { reason: "workflow-suspend" }
1737
- }));
1738
- })));
1739
- let o = yield* te;
1740
- return yield* s.suspend(o);
1741
- }
1742
- let M = j;
1743
- if (f.isFailure(M.exit)) {
1744
- 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);
1745
- return yield* u.sync(() => ne({
1746
- error: n,
1747
- source: "workflow",
1748
- name: i.name,
1749
- ...i.traceId ? { traceId: i.traceId } : {},
1750
- fields: {
1751
- executionId: b,
1752
- ...r ? { errorTag: r } : {},
1753
- ...T ? { runId: T } : {}
1754
- }
1755
- })), T && (yield* E("failed to record workflow failure", u.gen(function* () {
1756
- let e = yield* u.promise(() => i.store.update("_voltro_workflow_runs", T, {
1757
- status: "failed",
1758
- errorTag: r,
1759
- errorMessage: a,
1760
- completedAt: /* @__PURE__ */ new Date(),
1761
- durationMs: Date.now() - x
1762
- }));
1763
- e && h?.("workflowRuns", {
1764
- op: "update",
1765
- row: Q(e)
1766
- }), yield* u.promise(() => d.recordEvent({
1767
- runId: T,
1768
- eventType: "run-failed",
1769
- payload: {
1770
- errorTag: r,
1771
- errorMessage: a,
1772
- durationMs: Date.now() - x
1773
- }
1774
- })), yield* g(b, "failed", T);
1775
- }))), yield* _(b, "failed", T), yield* u.sync(() => i.recordRun?.({
1776
- name: i.name,
1777
- status: "failed",
1778
- durationMs: Date.now() - x
1779
- })), yield* u.failCause(e);
1780
- }
1781
- let N = M.exit.value;
1782
- return T && (yield* E("failed to record workflow success", u.gen(function* () {
1783
- let e = yield* u.promise(() => i.store.update("_voltro_workflow_runs", T, {
1784
- status: "succeeded",
1785
- output: Z(N, o),
1786
- completedAt: /* @__PURE__ */ new Date(),
1787
- durationMs: Date.now() - x
1788
- }));
1789
- e && h?.("workflowRuns", {
1790
- op: "update",
1791
- row: Q(e)
1792
- }), yield* u.promise(() => d.recordEvent({
1793
- runId: T,
1794
- eventType: "run-succeeded",
1795
- payload: { durationMs: Date.now() - x }
1796
- })), yield* g(b, "succeeded", T);
1797
- }))), yield* _(b, "succeeded", T), yield* u.sync(() => i.recordRun?.({
1798
- name: i.name,
1799
- status: "succeeded",
1800
- durationMs: Date.now() - x,
1801
- completedAtSec: Date.now() / 1e3
1802
- })), N;
1803
- });
1804
- }, Et = (e) => e === "cancel" || e === "terminate", Dt = (e) => e === "running" || e === "suspended", Ot = async (e) => {
1805
- let t = await e.store.query({
1806
- table: "_voltro_workflow_runs",
1807
- order: [{
1808
- column: "startedAt",
1809
- direction: "asc"
1810
- }],
1811
- predicate: v("parentExecutionId", e.parentExecutionId),
1812
- projection: void 0,
1813
- skip: void 0,
1814
- take: e.limit ?? 1e3
1815
- }), n = [];
1816
- for (let r of t) {
1817
- let t = {
1818
- runId: r.id,
1819
- workflowName: r.tag,
1820
- executionId: r.executionId,
1821
- policy: r.parentClosePolicy
1822
- };
1823
- if (r.parentClosePolicy === "abandon") {
1824
- n.push({
1825
- ...t,
1826
- action: "abandoned"
1827
- });
1828
- continue;
1829
- }
1830
- if (!Et(r.parentClosePolicy)) {
1831
- n.push({
1832
- ...t,
1833
- action: "skipped",
1834
- reason: "no-parent-close-policy"
1835
- });
1836
- continue;
1837
- }
1838
- if (!Dt(r.status)) {
1839
- n.push({
1840
- ...t,
1841
- action: "skipped",
1842
- reason: `status:${r.status}`
1843
- });
1844
- continue;
1845
- }
1846
- try {
1847
- await e.interruptChild(r.tag, r.executionId, r.parentClosePolicy);
1848
- let i = await e.store.update("_voltro_workflow_runs", r.id, {
1849
- status: "cancelled",
1850
- cancelled: !0,
1851
- completedAt: /* @__PURE__ */ new Date()
1852
- });
1853
- i && e.emit?.("workflowRuns", {
1854
- op: "update",
1855
- row: Q(i)
1856
- }), await e.recorder?.recordEvent({
1857
- runId: r.id,
1858
- eventType: "run-cancelled",
1859
- payload: {
1860
- reason: "parent-close",
1861
- parentExecutionId: e.parentExecutionId,
1862
- parentStatus: e.parentStatus,
1863
- parentClosePolicy: r.parentClosePolicy,
1864
- action: r.parentClosePolicy
1865
- }
1866
- }), n.push({
1867
- ...t,
1868
- action: "cancelled"
1869
- });
1870
- } catch (i) {
1871
- let a = i?.message ?? String(i);
1872
- e.log?.warn("workflow.parentClose.childInterrupt failed", {
1873
- parentExecutionId: e.parentExecutionId,
1874
- childExecutionId: r.executionId,
1875
- childWorkflowName: r.tag,
1876
- parentClosePolicy: r.parentClosePolicy,
1877
- reason: a
1878
- }), n.push({
1879
- ...t,
1880
- action: "failed",
1881
- reason: a
1882
- });
1883
- }
1884
- }
1885
- return n;
1886
- }, kt = (e) => {
1887
- if (e == null) return null;
1888
- if (e instanceof Date) return e;
1889
- if (typeof e == "string" || typeof e == "number") {
1890
- let t = new Date(e);
1891
- return Number.isNaN(t.getTime()) ? null : t;
1892
- }
1893
- return null;
1894
- }, At = (e) => typeof e == "number" ? e : e == null ? null : Number(e), $ = (e) => e == null ? null : String(e), jt = (e) => {
1895
- let t = /* @__PURE__ */ new Map();
1896
- for (let n of e) {
1897
- let e = String(n.stepName), r = t.get(e);
1898
- r === void 0 ? t.set(e, [n]) : r.push(n);
1899
- }
1900
- let n = [];
1901
- for (let [e, r] of t) {
1902
- r.sort((e, t) => (At(e.attempt) ?? 0) - (At(t.attempt) ?? 0));
1903
- let t = r[r.length - 1], i = $(t.errorTag), a = $(t.errorMessage), o = i !== null || a !== null ? {
1904
- tag: i,
1905
- message: a ?? ""
1906
- } : null;
1907
- n.push({
1908
- name: e,
1909
- attempt: At(t.attempt) ?? r.length,
1910
- attempts: r.length,
1911
- status: t.status ?? "running",
1912
- input: t.input ?? null,
1913
- output: t.output ?? null,
1914
- error: o,
1915
- durationMs: At(t.durationMs)
1916
- });
1917
- }
1918
- return n.sort((t, n) => {
1919
- let r = e.find((e) => String(e.stepName) === t.name), i = e.find((e) => String(e.stepName) === n.name);
1920
- return (kt(r?.startedAt)?.getTime() ?? 0) - (kt(i?.startedAt)?.getTime() ?? 0);
1921
- }), n;
1922
- }, Mt = (e) => {
1923
- if (e == null) return null;
1924
- if (typeof e == "string") try {
1925
- return JSON.parse(e);
1926
- } catch {
1927
- return null;
1928
- }
1929
- return typeof e == "object" ? e : null;
1930
- }, Nt = async (e, t) => {
1931
- let n = E(M), r = (await t.query(n.where(T(v("id", e), v("executionId", e))).limit(1).descriptor))[0];
1932
- if (r === void 0) return null;
1933
- let i = String(r.id), a = E(N), o = await t.query(a.where(v("runId", i)).descriptor);
1934
- return {
1935
- id: i,
1936
- executionId: $(r.executionId) ?? "",
1937
- name: $(r.tag) ?? "",
1938
- status: r.status ?? "running",
1939
- input: r.payload ?? null,
1940
- output: r.output ?? null,
1941
- subject: Mt(r.subject),
1942
- source: $(r.source),
1943
- steps: jt(o),
1944
- startedAt: kt(r.startedAt) ?? /* @__PURE__ */ new Date(0),
1945
- finishedAt: kt(r.completedAt),
1946
- traceId: $(r.traceId),
1947
- parentExecutionId: $(r.parentExecutionId),
1948
- parentClosePolicy: $(r.parentClosePolicy)
1949
- };
1950
- }, Pt = () => {
1951
- let e = [], n = [], r = 0, i = 0;
1952
- return {
1953
- layer: m.succeed(t, {
1954
- startStep: async ({ runId: t, stepName: n, attempt: i, stepInput: a, retryPolicy: o }) => {
1955
- let s = `wfstep_mem_${++r}`;
1956
- return e.push({
1957
- id: s,
1958
- runId: t,
1959
- stepName: n,
1960
- attempt: i,
1961
- status: "running",
1962
- input: a ?? null,
1963
- retryPolicy: o ?? null,
1964
- output: null,
1965
- errorTag: null,
1966
- errorMessage: null,
1967
- errorCause: null,
1968
- startedAt: /* @__PURE__ */ new Date(),
1969
- completedAt: null,
1970
- durationMs: null
1971
- }), s;
1972
- },
1973
- endStepSuccess: async ({ stepRecordId: t, output: n, durationMs: r }) => {
1974
- let i = e.find((e) => e.id === t);
1975
- i !== void 0 && (i.status = "succeeded", i.output = n, i.completedAt = /* @__PURE__ */ new Date(), i.durationMs = r);
1976
- },
1977
- endStepFailure: async ({ stepRecordId: t, errorTag: n, errorMessage: r, errorCause: i, durationMs: a }) => {
1978
- let o = e.find((e) => e.id === t);
1979
- o !== void 0 && (o.status = "failed", o.errorTag = n, o.errorMessage = r, o.errorCause = i ?? null, o.completedAt = /* @__PURE__ */ new Date(), o.durationMs = a);
1980
- },
1981
- recordEvent: async ({ runId: e, eventType: t, payload: r, stepName: a, attempt: o }) => {
1982
- let s = `wfev_mem_${++i}`;
1983
- return n.push({
1984
- id: s,
1985
- runId: e,
1986
- eventType: t,
1987
- payload: r ?? null,
1988
- stepName: a ?? null,
1989
- attempt: o ?? null,
1990
- occurredAt: /* @__PURE__ */ new Date()
1991
- }), { id: s };
1992
- }
1993
- }),
1994
- readSteps: () => e,
1995
- readEvents: () => n
1996
- };
1997
- };
1998
- //#endregion
1999
- export { ce as $, Ie as A, De as B, Ve as C, Ge as D, Je as E, z as F, Oe as G, je as H, L as I, Se as J, we as K, ke as L, Fe as M, R as N, ze as O, ge as P, xe as Q, W as R, Ue as S, We as T, be as U, G as V, _e as W, U as X, ye as Y, Ee as Z, rt as _, Q as a, le as at, K as b, bt as c, se as ct, mt as d, re as dt, he as et, lt as f, N as ft, at as g, dt as h, wt as i, ue as it, Ne as j, Re as k, _t as l, ae as lt, ut as m, j as mt, Nt as n, me as nt, Z as o, F as ot, Y as p, M as pt, Me as q, Ot as r, pe as rt, Tt as s, oe as st, Pt as t, de as tt, vt as u, ie as ut, Xe as v, Be as w, He as x, Ze as y, Ae as z };