@voltro/workflow 0.84.0 → 0.86.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.
Files changed (89) hide show
  1. package/CHANGELOG.md +1215 -0
  2. package/THIRD-PARTY-NOTICES.md +5 -151
  3. package/dist/admission.js +140 -0
  4. package/dist/admissionDrainer.js +705 -0
  5. package/dist/admissionGate.js +115 -0
  6. package/dist/admissionStore.js +347 -0
  7. package/dist/admissionSubmission.js +297 -0
  8. package/dist/admissionTables.js +137 -0
  9. package/dist/admissionTransaction.js +21 -0
  10. package/dist/awaitEvent.js +82 -0
  11. package/dist/budgetHold.js +136 -0
  12. package/dist/cancelOnPlan.js +75 -0
  13. package/dist/cancelOnSweep.js +188 -0
  14. package/dist/cancelPendingStart.js +50 -0
  15. package/dist/cluster.d.ts +304 -280
  16. package/dist/cluster.js +8 -2
  17. package/dist/clusterCron.js +11 -0
  18. package/dist/clusterDiagnostics.js +20 -0
  19. package/dist/clusterDiagnosticsSql.js +145 -0
  20. package/dist/clusterLayer.js +110 -0
  21. package/dist/clusterMigrationGate.js +61 -0
  22. package/dist/clusterRunnerLayer.js +21 -0
  23. package/dist/clusterTestSuite.d.ts +11 -11
  24. package/dist/clusterTestSuite.js +257 -257
  25. package/dist/controlMonitor.js +13 -0
  26. package/dist/controlRequest.js +367 -0
  27. package/dist/executionRefusal.js +162 -0
  28. package/dist/failureHandoff.js +183 -0
  29. package/dist/failureMessage.js +12 -0
  30. package/dist/failureRecovery.js +50 -0
  31. package/dist/failureReportStore.js +60 -0
  32. package/dist/flowControl.js +142 -0
  33. package/dist/forwardStartReceipts.js +41 -0
  34. package/dist/inMemoryLayer.js +7 -0
  35. package/dist/inMemoryRecorder.js +56 -0
  36. package/dist/index.d.ts +456 -360
  37. package/dist/index.js +49 -5
  38. package/dist/inspectWorkflow.js +101 -0
  39. package/dist/journalEncryption.js +147 -0
  40. package/dist/messages.js +92 -0
  41. package/dist/nondeterminism.js +51 -0
  42. package/dist/parentClosure.js +141 -0
  43. package/dist/parentClosureRecovery.js +54 -0
  44. package/dist/pendingSubmission.js +85 -0
  45. package/dist/prepareSubmissionDispatch.js +17 -0
  46. package/dist/preparedExecution.js +14 -0
  47. package/dist/primitives.d.ts +56 -31
  48. package/dist/primitives.js +225 -2
  49. package/dist/queuedCancellationRequest.js +364 -0
  50. package/dist/queuedControl.js +21 -0
  51. package/dist/recorder.js +11 -0
  52. package/dist/residentExecutionEvidence.js +64 -0
  53. package/dist/retryPolicy.js +57 -0
  54. package/dist/runEventsTable.js +17 -0
  55. package/dist/runGeneration.js +345 -0
  56. package/dist/runRecording.js +615 -0
  57. package/dist/runStepsTable.js +28 -0
  58. package/dist/runnerStorageGuard.js +29 -0
  59. package/dist/runsTable.js +42 -0
  60. package/dist/scheduleDeclaration.js +44 -0
  61. package/dist/signalHint.js +23 -0
  62. package/dist/signals.js +70 -0
  63. package/dist/signalsSuspending.js +57 -0
  64. package/dist/sqliteWorkflowOwnership.js +26 -0
  65. package/dist/stalenessSweep.js +191 -0
  66. package/dist/startContextsTable.js +20 -0
  67. package/dist/startReceipt.js +143 -0
  68. package/dist/submissionRecovery.js +122 -0
  69. package/dist/submissionRejection.js +10 -0
  70. package/dist/submissionRetry.js +71 -0
  71. package/dist/suspensionUnavailable.js +9 -0
  72. package/dist/updates.js +87 -0
  73. package/dist/watermarkTable.js +9 -0
  74. package/dist/webCrypto.js +17 -0
  75. package/dist/workflowDelivery.js +24 -0
  76. package/dist/workflowJournal.js +124 -0
  77. package/dist/workflowJournalReset.js +111 -0
  78. package/dist/workflowReadSelections.js +12 -0
  79. package/dist/workflowRestartDispatch.js +29 -0
  80. package/dist/workflowRestartObservation.js +60 -0
  81. package/dist/workflowRestartPreparation.js +109 -0
  82. package/dist/workflowRestartReservation.js +426 -0
  83. package/dist/workflowResumeDispatch.js +29 -0
  84. package/package.json +6 -9
  85. package/dist/cluster-i3frC3Da.js +0 -646
  86. package/dist/clusterDiagnostics-CGUtnJkX.js +0 -2084
  87. package/dist/journalEncryption--n5VDdYO.js +0 -148
  88. package/dist/primitives-Btjhjm8P.js +0 -483
  89. package/dist/src-DP-lKqaG.js +0 -3867
@@ -1,3867 +0,0 @@
1
- import { E as e, F as t, L as n, M as r, N as i, P as a, R as o, T as s, w as c } from "./primitives-Btjhjm8P.js";
2
- import { S as l, T as u, _ as d, a as f, b as p, g as m, h, i as g, l as _, n as v, u as y, v as ee, x as b } from "./journalEncryption--n5VDdYO.js";
3
- import { $ as x, A as te, At as ne, C as re, Ct as ie, D as ae, Dt as S, E as C, Et as w, F as oe, Ft as se, H as ce, Ht as T, I as E, It as le, J as ue, Kt as D, L as de, Mt as fe, N as O, Nt as k, O as pe, Pt as me, Q as A, Rt as j, S as he, T as ge, Tt as M, U as _e, Ut as ve, V as ye, Z as be, _t as xe, bt as Se, ct as Ce, ft as N, gt as we, h as Te, i as Ee, it as De, jt as Oe, k as ke, kt as Ae, ot as je, pt as Me, q as Ne, qt as Pe, rt as P, st as Fe, tt as Ie, v as Le, vt as Re, w as ze, wt as Be, xt as Ve, y as He, yt as Ue } from "./clusterDiagnostics-CGUtnJkX.js";
4
- import { DurableClock as We, DurableDeferred as Ge, Workflow as Ke, WorkflowEngine as qe } from "@effect/workflow";
5
- import { Cause as F, Context as Je, Effect as I, Either as L, Exit as Ye, Fiber as Xe, FiberRef as Ze, Layer as Qe, Schema as R } from "effect";
6
- import { WorkflowQueuedCancellationResultSchema as $e, publishServerError as et } from "@voltro/protocol";
7
- import { and as z, boolean as tt, derivedRowId as nt, eq as B, generateId as rt, gt as V, gte as it, id as H, inSet as at, integer as U, isNotNull as ot, isNull as W, json as G, lt as st, or as ct, queryFor as lt, real as ut, reference as dt, registerRetention as ft, retentionTtlMsFromEnv as pt, table as K, text as q, timestamp as J } from "@voltro/database";
8
- import { createHash as mt, randomUUID as ht } from "node:crypto";
9
- import { WorkflowInstance as Y } from "@effect/workflow/WorkflowEngine";
10
- //#region src/inMemoryLayer.ts
11
- var gt = qe.layerMemory, _t = K("_voltro_workflow_runs", {
12
- id: H({ prefix: "wfrun" }),
13
- tag: q(),
14
- executionId: q().unique(),
15
- status: q().oneOf([
16
- "running",
17
- "succeeded",
18
- "failed",
19
- "cancelled",
20
- "suspended"
21
- ]).default("running"),
22
- payload: G(),
23
- workflowVersion: q().nullable(),
24
- workflowPatches: G().nullable(),
25
- runnerEnteredAt: J().nullable(),
26
- runnerGeneration: q().nullable(),
27
- engineDelivery: G().nullable(),
28
- reclaimCount: U().default(0),
29
- output: G().nullable(),
30
- subject: G().nullable(),
31
- source: q().nullable(),
32
- errorTag: q().nullable(),
33
- errorMessage: q().nullable(),
34
- cancelled: tt().default(!1),
35
- discardedAt: J().nullable(),
36
- discardedBy: q().nullable(),
37
- startedAt: J().default("now"),
38
- completedAt: J().nullable(),
39
- durationMs: U().nullable(),
40
- traceId: q().nullable(),
41
- parentExecutionId: q().nullable(),
42
- parentGeneration: q().nullable(),
43
- parentClosePolicy: q().oneOf([
44
- "cancel",
45
- "terminate",
46
- "abandon"
47
- ]).nullable()
48
- }).index(["tag"]).index(["status"]).index(["source"]).index(["startedAt"]).index(["parentExecutionId"]).index(["parentClosePolicy"]), vt = K("_voltro_workflow_run_steps", {
49
- id: H({ prefix: "wfstep" }),
50
- runId: dt(() => _t, {
51
- index: !1,
52
- onDelete: "cascade"
53
- }),
54
- stepName: q(),
55
- attempt: U().default(1),
56
- status: q().oneOf([
57
- "running",
58
- "succeeded",
59
- "failed"
60
- ]).default("running"),
61
- input: G().nullable(),
62
- retryPolicy: G().nullable(),
63
- output: G().nullable(),
64
- errorTag: q().nullable(),
65
- errorMessage: q().nullable(),
66
- errorCause: G().nullable(),
67
- startedAt: J().default("now"),
68
- completedAt: J().nullable(),
69
- durationMs: U().nullable()
70
- }).index(["runId", "stepName"]).index(["startedAt"]), yt = K("_voltro_workflow_run_events", {
71
- id: H({ prefix: "wfev" }),
72
- runId: dt(() => _t, {
73
- index: !1,
74
- onDelete: "cascade"
75
- }),
76
- eventType: q(),
77
- payload: G().nullable(),
78
- occurredAt: J().default("now"),
79
- stepName: q().nullable(),
80
- attempt: U().nullable()
81
- }).index(["runId", "occurredAt"]).index(["eventType"]), bt = K("_voltro_workflow_start_contexts", {
82
- id: H({ prefix: "wfctx" }),
83
- workflowName: q(),
84
- executionId: q().unique(),
85
- subject: G().nullable(),
86
- traceId: q().nullable(),
87
- source: q().nullable(),
88
- parentExecutionId: q().nullable(),
89
- parentGeneration: q().nullable(),
90
- parentClosePolicy: q().oneOf([
91
- "cancel",
92
- "terminate",
93
- "abandon"
94
- ]).nullable(),
95
- createdAt: J().default("now")
96
- }).index(["workflowName"]).index(["executionId"]).index(["parentExecutionId"]), xt = K("_voltro_workflow_admission_locks", {
97
- id: H({ prefix: "wfalk" }),
98
- nonce: q()
99
- }).nonReactive(), St = K("_voltro_workflow_parent_closures", {
100
- id: H({ prefix: "wfpc" }),
101
- runId: q(),
102
- workflowName: q(),
103
- executionId: q(),
104
- generation: q(),
105
- parentStatus: q().oneOf([
106
- "succeeded",
107
- "failed",
108
- "cancelled"
109
- ]),
110
- closedAt: J(),
111
- afterChildId: q().nullable(),
112
- scanHasOpenChildren: tt().default(!1),
113
- completedAt: J().nullable()
114
- }).index(["executionId"]).index(["completedAt", "id"]).nonReactive(), Ct = K("_voltro_workflow_control_requests", {
115
- id: H({ prefix: "wfctl" }),
116
- runId: q(),
117
- workflowName: q(),
118
- executionId: q(),
119
- generation: q(),
120
- operation: q().oneOf([
121
- "cancel",
122
- "terminate",
123
- "resume"
124
- ]),
125
- requestedAt: J(),
126
- owner: G().nullable(),
127
- cause: G().nullable(),
128
- parentClosureId: q().nullable(),
129
- resumeJournal: G().nullable(),
130
- dispatchAttempts: U().default(0),
131
- result: G().nullable()
132
- }).index(["runId"]).index(["parentClosureId", "id"]).nonReactive(), wt = K("_voltro_workflow_failure_reports", {
133
- id: H({ prefix: "wffr" }),
134
- workflowName: q(),
135
- tenantId: q().nullable(),
136
- sourceId: q(),
137
- sourceKind: q().oneOf([
138
- "submission",
139
- "intent",
140
- "run"
141
- ]),
142
- handler: q().nullable(),
143
- callerContext: G().nullable(),
144
- report: G(),
145
- handoffReceiptId: q().nullable(),
146
- handoffAttempt: U().default(0),
147
- acceptedExecutionId: q().nullable()
148
- }).index(["sourceKind", "sourceId"]).nonReactive(), Tt = K("_voltro_workflow_submissions", {
149
- id: H({ prefix: "wfsub" }),
150
- workflowName: q(),
151
- tenantId: q().nullable(),
152
- ledgerId: q(),
153
- executionId: q().nullable(),
154
- runId: q().nullable(),
155
- receiptsBound: tt().default(!1),
156
- preparedExecutionId: q().nullable(),
157
- dispatchAttempts: U().default(0),
158
- failureId: q().nullable(),
159
- retry: G(),
160
- payload: G(),
161
- callerContext: G().nullable(),
162
- intentIds: G(),
163
- eviction: G().nullable()
164
- }).nonReactive(), Et = K("_voltro_workflow_start_receipts", {
165
- id: H({ prefix: "wfrc" }),
166
- workflowName: q(),
167
- tenantId: q().nullable(),
168
- pendingId: q().maxLength(64),
169
- submissionId: q().maxLength(64).nullable(),
170
- terminal: G().nullable(),
171
- requestFingerprint: q().maxLength(64).nullable()
172
- }).index(["pendingId"]).nonReactive(), Dt = K("_voltro_workflow_pending", {
173
- id: H({ prefix: "wfp" }),
174
- tenantId: q().nullable(),
175
- workflowName: q(),
176
- controlKey: q(),
177
- mode: q().oneOf([
178
- "debounce",
179
- "batch",
180
- "throttle",
181
- "concurrency",
182
- "paused",
183
- "delayed"
184
- ]),
185
- payload: G(),
186
- callerContext: G().nullable(),
187
- queuedAppVersion: q().nullable(),
188
- queuedSchemaFingerprint: q().nullable(),
189
- priority: U().default(0),
190
- dueAt: J(),
191
- deadlineAt: J().nullable(),
192
- collapsed: U().default(1),
193
- firstSeenAt: J().default("now"),
194
- updatedAt: J().default("now"),
195
- attempts: U().default(0),
196
- lastError: q().nullable(),
197
- deadLetteredAt: J().nullable()
198
- }).index(["workflowName", "controlKey"]).index(["dueAt"]).index(["workflowName", "mode"]).index(["tenantId"]), Ot = K("_voltro_workflow_admissions", {
199
- id: H({ prefix: "wfadm" }),
200
- tenantId: q().nullable(),
201
- workflowName: q(),
202
- outcome: q().oneOf([
203
- "admitted",
204
- "dropped",
205
- "skipped",
206
- "evicted",
207
- "expired",
208
- "discarded"
209
- ]),
210
- mode: q().nullable(),
211
- reason: q().nullable(),
212
- collapsed: U().default(1),
213
- waitedMs: ut().nullable().narrowedFrom("integer"),
214
- executionId: q().nullable(),
215
- runId: q().nullable(),
216
- singletonKey: q().nullable(),
217
- concurrencyKey: q().nullable(),
218
- concurrencyReservation: G().nullable(),
219
- rateKey: q().nullable(),
220
- admittedAt: J().default("now"),
221
- expiresAt: J().nullable(),
222
- releasedAt: J().nullable()
223
- }).index(["workflowName", "admittedAt"]).index(["concurrencyKey", "releasedAt"]).index(["singletonKey", "releasedAt"]).index(["rateKey", "admittedAt"]).index(["executionId"]).index(["tenantId"]), kt = K("_voltro_workflow_pauses", {
224
- id: H({ prefix: "wfpause" }),
225
- pausedAt: J().default("now"),
226
- pausedBy: q().nullable(),
227
- reason: q().nullable()
228
- }), At = async (e, t) => {
229
- if (!Number.isFinite(t.now) || !Number.isFinite(new Date(t.now).getTime())) throw Error("Queued cancellation requires a valid timestamp");
230
- let n = await Ce(e, t.receiptId);
231
- if (n === void 0 || n.workflowName !== t.workflowName || n.tenantId !== t.tenantId) throw Error("Queued cancellation receipt is missing or belongs to another workflow or tenant");
232
- if (n.terminal !== null) return {
233
- kind: "terminal",
234
- outcome: n.terminal
235
- };
236
- if (n.submissionId !== null) {
237
- let t = await M(e, n.submissionId);
238
- if (t === void 0 || !t.receiptsBound || t.workflowName !== n.workflowName || t.tenantId !== n.tenantId || !t.intentIds.includes(n.pendingId)) throw Error("Queued cancellation receipt has no matching submission");
239
- return {
240
- kind: "submitted",
241
- submissionId: t.id
242
- };
243
- }
244
- let [r] = await e.query({
245
- table: O,
246
- predicate: B("id", n.pendingId),
247
- lock: "update",
248
- order: [],
249
- take: 1,
250
- skip: void 0,
251
- projection: void 0
252
- });
253
- if (r === void 0) throw Error("Queued cancellation has no pending input or submission");
254
- let i = P(r);
255
- if (i.workflowName !== n.workflowName || i.tenantId !== n.tenantId || i.deadLetteredAt !== void 0) throw Error("Queued cancellation input has contradictory ownership or is dead-lettered");
256
- let a = {
257
- kind: "cancelled",
258
- at: t.now
259
- };
260
- if (await N(e, {
261
- pendingId: n.pendingId,
262
- workflowName: n.workflowName,
263
- tenantId: n.tenantId,
264
- terminal: a
265
- }), !await e.delete("_voltro_workflow_pending", n.pendingId)) throw Error("Queued cancellation lost its pending input");
266
- return {
267
- kind: "terminal",
268
- outcome: a
269
- };
270
- }, jt = "_voltro_workflow_parent_closures", X = R.NonEmptyString, Mt = R.Struct({
271
- id: X,
272
- runId: X,
273
- workflowName: X,
274
- executionId: X,
275
- generation: X,
276
- parentStatus: R.Literal("succeeded", "failed", "cancelled"),
277
- closedAt: R.DateFromSelf,
278
- afterChildId: R.NullOr(X),
279
- scanHasOpenChildren: R.Boolean,
280
- completedAt: R.NullOr(R.DateFromSelf)
281
- }), Nt = R.Struct({
282
- id: X,
283
- tag: X,
284
- executionId: X,
285
- status: R.Literal("running", "suspended", "succeeded", "failed", "cancelled"),
286
- runnerGeneration: R.optional(R.NullOr(X)),
287
- parentGeneration: R.optional(R.NullOr(X)),
288
- parentClosePolicy: R.NullOr(R.Literal("cancel", "terminate", "abandon"))
289
- }), Pt = async (e, t, n) => {
290
- if (t.parentClosePolicy !== "cancel" && t.parentClosePolicy !== "terminate") return !1;
291
- if (typeof t.parentExecutionId != "string" || t.parentExecutionId.length === 0 || typeof t.parentGeneration != "string" || t.parentGeneration.length === 0) throw Error("Child entry requires its original parent execution and generation");
292
- let r = n ?? (await e.query({
293
- table: jt,
294
- predicate: z(B("executionId", t.parentExecutionId), B("generation", t.parentGeneration)),
295
- lock: "update",
296
- order: [],
297
- take: 1,
298
- skip: void 0,
299
- projection: void 0
300
- }))[0];
301
- if (r === void 0) return !1;
302
- let i = R.decodeUnknownSync(Mt)(r);
303
- if (i.executionId !== t.parentExecutionId || i.generation !== t.parentGeneration) return !1;
304
- let a = R.decodeUnknownSync(Nt)(t), o = nt("wfctl", JSON.stringify([
305
- "parent-close",
306
- i.id,
307
- a.id
308
- ])), s = await ae(e, o);
309
- if (s !== void 0) {
310
- if (s.runId !== a.id || s.workflowName !== a.tag || s.executionId !== a.executionId || s.operation === "resume" || s.cause?.reason !== "parent-close" || s.cause.detail?.closureId !== i.id) throw Error("Parent closure receipt belongs to another child");
311
- } else {
312
- if (a.status !== "running" && a.status !== "suspended") return !1;
313
- if (a.runnerGeneration === void 0 || a.runnerGeneration === null) throw Error("Child entry requires its own generation");
314
- await He(e, {
315
- id: o,
316
- runId: a.id,
317
- workflowName: a.tag,
318
- executionId: a.executionId,
319
- generation: a.runnerGeneration,
320
- operation: t.parentClosePolicy,
321
- requestedAt: i.closedAt.getTime(),
322
- cause: {
323
- reason: "parent-close",
324
- detail: {
325
- closureId: i.id,
326
- parentRunId: i.runId,
327
- parentExecutionId: i.executionId,
328
- parentGeneration: i.generation,
329
- parentStatus: i.parentStatus,
330
- parentClosePolicy: t.parentClosePolicy
331
- }
332
- }
333
- });
334
- }
335
- return !0;
336
- }, Ft = async (e, t, n = Date.now()) => {
337
- let [r] = await e.query({
338
- table: jt,
339
- predicate: B("id", t),
340
- lock: "update",
341
- order: [],
342
- take: 1,
343
- skip: void 0,
344
- projection: void 0
345
- });
346
- if (r === void 0) throw Error("Parent closure is missing");
347
- let i = R.decodeUnknownSync(Mt)(r);
348
- if (i.completedAt !== null) return {
349
- scanned: 0,
350
- controls: 0,
351
- wrapped: !1
352
- };
353
- if (!Number.isFinite(n)) throw Error("Parent closure requires a finite completion timestamp");
354
- let a = await e.query({
355
- table: "_voltro_workflow_runs",
356
- predicate: z(B("parentExecutionId", i.executionId), ...i.afterChildId === null ? [] : [V("id", i.afterChildId)]),
357
- lock: "update",
358
- order: [{
359
- column: "id",
360
- direction: "asc"
361
- }],
362
- take: 100,
363
- skip: void 0,
364
- projection: void 0
365
- }), o = 0, s = i.scanHasOpenChildren, c = null;
366
- for (let t of a) {
367
- let r = R.decodeUnknownSync(Nt)(t);
368
- if (c = r.id, r.parentClosePolicy !== null && r.parentClosePolicy !== "abandon") {
369
- if (r.parentGeneration === void 0 || r.parentGeneration === null) throw Error("Parent closure cannot attribute a child without its parent generation");
370
- r.parentGeneration === i.generation && ((r.status === "running" || r.status === "suspended") && (s = !0), await Pt(e, t, i) && (o++, r.status === "suspended" && typeof r.runnerGeneration == "string" && await Ht(e, {
371
- runId: r.id,
372
- workflowName: r.tag,
373
- executionId: r.executionId,
374
- generation: r.runnerGeneration
375
- }, n)));
376
- }
377
- }
378
- let l = a.length < 100, u = l && !s && !await ze(e, i.id);
379
- if (await e.update(jt, i.id, {
380
- afterChildId: l ? null : c,
381
- scanHasOpenChildren: !l && s,
382
- completedAt: u ? new Date(n) : null
383
- }) === null) throw Error("Parent closure disappeared before saving its cursor");
384
- return {
385
- scanned: a.length,
386
- controls: o,
387
- wrapped: l
388
- };
389
- }, It = "_voltro_workflow_runs", Lt = R.NullOr(R.Struct({
390
- requestId: R.NonEmptyString,
391
- restartToken: R.NullOr(R.NonEmptyString)
392
- })), Rt = async (e, t, n, r) => {
393
- if (typeof t.id != "string") throw Error("Child entry has no allocated run identity");
394
- let i = {
395
- runId: t.id,
396
- workflowName: n.workflowName,
397
- executionId: n.executionId,
398
- generation: n.generation
399
- }, a = await rn(e, i), o = await Pt(e, t);
400
- if (!a && !o) return;
401
- let s = await Wt(e, {
402
- owner: i,
403
- now: n.now,
404
- durationMs: 0,
405
- outcome: { status: "cancelled" }
406
- }, "running");
407
- if (s.kind !== "committed") throw Error("Child entry cancellation lost its resident owner");
408
- return {
409
- kind: "cancelled",
410
- row: s.row,
411
- previous: r,
412
- terminalEvent: s.terminalEvent
413
- };
414
- }, zt = async (e, t) => {
415
- let n = await Ee(e, t);
416
- return {
417
- ...await Rt(e, n.row, t, n.previous) ?? {
418
- kind: "entered",
419
- row: n.row,
420
- previous: n.previous
421
- },
422
- restartEvent: n.event
423
- };
424
- }, Bt = async (e, t) => {
425
- if ([
426
- t.workflowName,
427
- t.executionId,
428
- t.generation
429
- ].some((e) => e.length === 0) || typeof t.initialRow.id != "string" || t.initialRow.id.length === 0 || !Number.isFinite(t.now)) throw Error("Workflow entry requires allocated identities and a finite timestamp");
430
- let n = (await e.query({
431
- table: It,
432
- predicate: B("executionId", t.executionId),
433
- lock: "update",
434
- order: [],
435
- take: 1,
436
- skip: void 0,
437
- projection: void 0
438
- }))[0], r = R.decodeUnknownSync(Lt)(t.delivery ?? null), i = (r) => Rt(e, r, t, n);
439
- if (n === void 0) {
440
- if (r !== null && r.restartToken !== null) throw Error("Workflow restart delivery has no resident authorization");
441
- if ((await e.query({
442
- table: "_voltro_workflow_parent_closures",
443
- predicate: B("executionId", t.executionId),
444
- lock: "update",
445
- order: [],
446
- take: 1,
447
- skip: void 0,
448
- projection: ["id"]
449
- })).length !== 0) throw Error("Workflow execution is already terminal; restore its engine journal instead of re-entering the body");
450
- let n = await e.insert(It, {
451
- ...t.initialRow,
452
- tag: t.workflowName,
453
- executionId: t.executionId,
454
- runnerGeneration: t.generation,
455
- engineDelivery: r,
456
- status: "running",
457
- runnerEnteredAt: new Date(t.now),
458
- reclaimCount: 0
459
- });
460
- return await i(n) ?? {
461
- kind: "created",
462
- row: n,
463
- previous: void 0
464
- };
465
- }
466
- if (n.tag !== t.workflowName || typeof n.id != "string") throw Error("Workflow entry execution belongs to a different resident run");
467
- let a = R.decodeUnknownSync(Lt)(n.engineDelivery ?? null);
468
- if (a?.requestId !== r?.requestId || a?.restartToken !== r?.restartToken) {
469
- if (n.status === "failed" && r !== null && r.restartToken !== null && a?.requestId === r.requestId) return zt(e, {
470
- runId: n.id,
471
- workflowName: t.workflowName,
472
- executionId: t.executionId,
473
- generation: t.generation,
474
- delivery: r,
475
- now: t.now
476
- });
477
- throw Error("Workflow delivery does not match its resident owner");
478
- }
479
- if (n.status === "cancelled") return {
480
- kind: "already-cancelled",
481
- row: n,
482
- previous: n
483
- };
484
- if (n.status === "succeeded" || n.status === "failed") throw Error("Workflow execution is already terminal; restore its engine journal instead of re-entering the body");
485
- if (n.status === "suspended" && n.runnerEnteredAt === null && typeof n.runnerGeneration == "string") {
486
- let r = {
487
- runId: n.id,
488
- workflowName: t.workflowName,
489
- executionId: t.executionId,
490
- generation: n.runnerGeneration
491
- };
492
- if (await re(e, r)) {
493
- let i = await Wt(e, {
494
- owner: r,
495
- now: t.now,
496
- durationMs: 0,
497
- outcome: { status: "cancelled" }
498
- }, "suspended");
499
- if (i.kind !== "committed") throw Error("Suspended cancellation lost its resident owner");
500
- return {
501
- kind: "cancelled",
502
- row: i.row,
503
- previous: n,
504
- terminalEvent: i.terminalEvent
505
- };
506
- }
507
- }
508
- if (n.runnerGeneration === t.generation) return {
509
- kind: "replayed",
510
- row: n,
511
- previous: void 0
512
- };
513
- let o = n.runnerEnteredAt !== null && n.runnerEnteredAt !== void 0, s = n.reclaimCount;
514
- if (typeof s != "number" || !Number.isSafeInteger(s) || s < 0) throw Error("Workflow entry has an invalid resident reclaim counter");
515
- let c = o ? s + 1 : 0;
516
- if (!Number.isSafeInteger(c)) throw Error("Workflow reclaim counter exhausted");
517
- let l = await e.update(It, n.id, {
518
- runnerGeneration: t.generation,
519
- runnerEnteredAt: new Date(t.now),
520
- reclaimCount: c,
521
- status: "running",
522
- errorTag: null,
523
- errorMessage: null,
524
- output: null,
525
- completedAt: null
526
- });
527
- if (l === null) throw Error("Workflow run disappeared while entering its new generation");
528
- let u = await i(l);
529
- return u === void 0 ? (n.status === "suspended" && n.runnerEnteredAt === null && typeof n.runnerGeneration == "string" && await ke(e, {
530
- runId: n.id,
531
- workflowName: t.workflowName,
532
- executionId: t.executionId,
533
- generation: n.runnerGeneration
534
- }, t.generation, t.now), {
535
- kind: "entered",
536
- row: l,
537
- previous: n
538
- }) : u;
539
- }, Vt = async (e, t) => {
540
- if ([
541
- t.runId,
542
- t.workflowName,
543
- t.executionId,
544
- t.generation
545
- ].some((e) => e.length === 0)) throw Error("Workflow runner ownership requires non-empty identities");
546
- let n = (await e.query({
547
- table: It,
548
- predicate: B("id", t.runId),
549
- lock: "update",
550
- order: [],
551
- take: 1,
552
- skip: void 0,
553
- projection: void 0
554
- }))[0];
555
- if (n === void 0 || n.tag !== t.workflowName || n.executionId !== t.executionId) throw Error("Workflow runner ownership does not match its resident run");
556
- return n;
557
- }, Ht = async (e, t, n) => {
558
- let r = await Vt(e, t);
559
- if (r.runnerGeneration !== t.generation || r.status !== "suspended" || r.runnerEnteredAt !== null || !await re(e, t)) return !1;
560
- if ((await Wt(e, {
561
- owner: t,
562
- now: n,
563
- durationMs: 0,
564
- outcome: { status: "cancelled" }
565
- }, "suspended")).kind !== "committed") throw Error("Suspended cancellation lost its resident owner");
566
- return !0;
567
- }, Ut = async (e, t, n) => {
568
- let r = await Vt(e, t);
569
- if (r.runnerGeneration !== t.generation) return { kind: "superseded" };
570
- if (r.status !== "running") return { kind: "not-running" };
571
- let i = await e.update(It, t.runId, {
572
- status: "suspended",
573
- runnerEnteredAt: null,
574
- errorTag: n.errorTag,
575
- errorMessage: n.errorMessage
576
- });
577
- if (i === null) throw Error("Workflow run disappeared during suspension recording");
578
- return {
579
- kind: "committed",
580
- row: i
581
- };
582
- }, Wt = async (e, t, n) => {
583
- let r = await Vt(e, t.owner);
584
- if (r.runnerGeneration !== t.owner.generation) return { kind: "superseded" };
585
- if (r.status !== n) return { kind: "not-running" };
586
- if (!Number.isFinite(t.now) || !Number.isFinite(t.durationMs) || t.durationMs < 0) throw Error("Workflow completion requires finite time and non-negative duration");
587
- let i = t.outcome, a = null;
588
- if (i.status === "failed" && (a = `wffr_${mt("sha256").update(JSON.stringify([
589
- "run",
590
- t.owner.workflowName,
591
- t.owner.runId,
592
- t.owner.generation
593
- ])).digest("hex").slice(0, 40)}`, await j(e, {
594
- id: a,
595
- sourceKind: "run",
596
- sourceId: t.owner.runId,
597
- workflowName: t.owner.workflowName,
598
- tenantId: i.tenantId,
599
- handler: await k(e, t.owner.executionId, t.owner.workflowName, i.tenantId) ? null : i.handler,
600
- callerContext: i.callerContext,
601
- report: {
602
- workflow: t.owner.workflowName,
603
- payload: r.payload,
604
- errorTag: i.errorTag,
605
- errorMessage: i.errorMessage,
606
- runId: t.owner.runId,
607
- executionId: t.owner.executionId,
608
- reason: "the run failed",
609
- failedAt: t.now
610
- }
611
- }), await fe(e, a, t.now)), i.status === "cancelled") {
612
- let n = (await C((t) => e.query({
613
- ...t,
614
- lock: "update"
615
- }), t.owner)).map((e) => ({
616
- request: e,
617
- cause: he(e)
618
- })).find((e) => e.cause !== void 0);
619
- if (n !== void 0 && n.cause !== void 0) {
620
- let i = R.decodeUnknownOption(R.Struct({ tenantId: R.NullOr(R.String) }))(r.subject), o = n.request.owner?.tenantId ?? (i._tag === "Some" ? i.value.tenantId : null);
621
- a = `wffr_${mt("sha256").update(JSON.stringify([
622
- "finish-timeout",
623
- t.owner.workflowName,
624
- t.owner.runId,
625
- t.owner.generation
626
- ])).digest("hex").slice(0, 40)}`, await j(e, {
627
- id: a,
628
- sourceKind: "run",
629
- sourceId: t.owner.runId,
630
- workflowName: t.owner.workflowName,
631
- tenantId: o,
632
- handler: await k(e, t.owner.executionId, t.owner.workflowName, o) ? null : n.cause.detail.onFailure,
633
- callerContext: {
634
- subject: r.subject ?? null,
635
- traceId: r.traceId ?? null,
636
- source: r.source ?? null,
637
- parentExecutionId: r.parentExecutionId ?? null,
638
- parentGeneration: r.parentGeneration ?? null,
639
- parentClosePolicy: r.parentClosePolicy ?? null
640
- },
641
- report: {
642
- workflow: t.owner.workflowName,
643
- payload: r.payload,
644
- errorTag: null,
645
- errorMessage: null,
646
- runId: t.owner.runId,
647
- executionId: t.owner.executionId,
648
- reason: n.cause.reason,
649
- failedAt: t.now
650
- }
651
- }), await fe(e, a, t.now);
652
- }
653
- }
654
- let o = await e.update(It, t.owner.runId, {
655
- status: i.status,
656
- completedAt: new Date(t.now),
657
- durationMs: t.durationMs,
658
- cancelled: i.status === "cancelled",
659
- runnerEnteredAt: null,
660
- output: i.status === "succeeded" ? _(t.owner.workflowName) ? l(i.output, `workflow '${t.owner.workflowName}' result`) : i.output : null,
661
- errorTag: i.status === "failed" ? i.errorTag : null,
662
- errorMessage: i.status === "failed" ? p(t.owner.workflowName, i.errorMessage) : null
663
- });
664
- if (o === null) throw Error("Workflow run disappeared during terminal recording");
665
- await e.insert("_voltro_workflow_parent_closures", {
666
- id: nt("wfpc", JSON.stringify([t.owner.runId, t.owner.generation])),
667
- runId: t.owner.runId,
668
- workflowName: t.owner.workflowName,
669
- executionId: t.owner.executionId,
670
- generation: t.owner.generation,
671
- parentStatus: i.status,
672
- closedAt: new Date(t.now),
673
- afterChildId: null,
674
- scanHasOpenChildren: !1,
675
- completedAt: null
676
- });
677
- let s = await e.insert("_voltro_workflow_run_events", {
678
- id: nt("wfev", JSON.stringify([
679
- "terminal",
680
- t.owner.runId,
681
- t.owner.generation
682
- ])),
683
- runId: t.owner.runId,
684
- eventType: `run-${i.status}`,
685
- occurredAt: new Date(t.now),
686
- stepName: null,
687
- attempt: null,
688
- payload: {
689
- executionId: t.owner.executionId,
690
- generation: t.owner.generation,
691
- durationMs: t.durationMs,
692
- ...i.status === "failed" ? {
693
- errorTag: i.errorTag,
694
- errorMessage: p(t.owner.workflowName, i.errorMessage)
695
- } : {}
696
- }
697
- });
698
- await pe(e, t), await x(e, t.owner.executionId, t.now);
699
- for await (let n of Ue(e, t.owner.executionId, t.owner.workflowName)) {
700
- let [r] = await e.query({
701
- table: te,
702
- predicate: B("id", n.ledgerId),
703
- lock: "update",
704
- order: [],
705
- take: 1,
706
- skip: void 0,
707
- projection: void 0
708
- });
709
- if (r === void 0 || r.workflowName !== n.workflowName || r.tenantId !== n.tenantId || r.outcome !== "admitted" || r.executionId !== null && r.executionId !== t.owner.executionId) throw Error("Workflow terminal reservation does not match its resident submission");
710
- if (r.releasedAt === null && await e.update("_voltro_workflow_admissions", n.ledgerId, { releasedAt: new Date(t.now) }) === null) throw Error("Workflow terminal reservation disappeared during release");
711
- }
712
- return {
713
- kind: "committed",
714
- row: o,
715
- failureId: a,
716
- terminalEvent: s
717
- };
718
- }, Gt = (e, t) => Wt(e, t, "running"), Kt = K("_voltro_workflow_queued_cancellations", {
719
- id: H({ prefix: "wfqc" }),
720
- receiptId: q(),
721
- workflowName: q(),
722
- tenantId: q().nullable(),
723
- requestedAt: J(),
724
- cause: G().nullable(),
725
- target: G(),
726
- controlBinding: G().nullable()
727
- }).index(["receiptId"]).index(["workflowName", "id"]).nonReactive(), qt = R.NullOr(R.Struct({
728
- reason: R.NonEmptyString,
729
- detail: R.optional(R.Record({
730
- key: R.String,
731
- value: R.Unknown
732
- }))
733
- })), Jt = R.Struct({
734
- id: R.NonEmptyString,
735
- receiptId: R.NonEmptyString,
736
- workflowName: R.NonEmptyString,
737
- tenantId: R.NullOr(R.String),
738
- requestedAt: R.DateFromSelf,
739
- cause: qt,
740
- controlBinding: R.NullOr(R.Struct({
741
- controlId: R.NonEmptyString,
742
- runId: R.NonEmptyString,
743
- executionId: R.NonEmptyString,
744
- generation: R.NonEmptyString
745
- })),
746
- target: R.Union(R.Struct({
747
- kind: R.Literal("submission"),
748
- submissionId: R.NonEmptyString
749
- }), R.Struct({
750
- kind: R.Literal("terminal"),
751
- receipt: R.Unknown
752
- }))
753
- }), Yt = (e) => {
754
- let t = R.decodeUnknownSync(Jt)(e);
755
- if (!Number.isFinite(t.requestedAt.getTime())) throw Error("Queued cancellation request has an invalid timestamp");
756
- if (t.target.kind === "submission") return {
757
- ...t,
758
- target: t.target
759
- };
760
- let n = Fe(t.target.receipt);
761
- if (t.controlBinding !== null) throw Error("A non-executed start cannot have a run control binding");
762
- if (n.id !== t.receiptId || n.workflowName !== t.workflowName || n.tenantId !== t.tenantId || n.terminal === null) throw Error("Queued cancellation terminal evidence belongs to another start or is not terminal");
763
- return {
764
- ...t,
765
- target: {
766
- kind: "terminal",
767
- receipt: n
768
- }
769
- };
770
- }, Xt = async (e, t) => {
771
- let [n] = await e.query({
772
- table: Kt.tableName,
773
- predicate: B("id", t),
774
- lock: "update",
775
- order: [],
776
- take: 1,
777
- skip: void 0,
778
- projection: void 0
779
- });
780
- return n === void 0 ? void 0 : Yt(n);
781
- }, Zt = async (e, t) => {
782
- let n = t.controlBinding;
783
- if (n === null) throw Error("Queued cancellation has no control binding");
784
- let r = await ae(e, n.controlId);
785
- if (r === void 0 || r.operation !== "cancel" || r.workflowName !== t.workflowName || r.runId !== n.runId || r.executionId !== n.executionId || r.generation !== n.generation || r.owner?.tenantId !== t.tenantId || r.result?.status === "running") throw Error("Queued cancellation lost its original resident control owner");
786
- return r;
787
- }, Qt = async (e, t, n) => {
788
- if (t.controlBinding === null) return;
789
- let r = await Zt(e, t);
790
- if (r.result !== null) return;
791
- let [i] = await e.query({
792
- table: "_voltro_workflow_runs",
793
- predicate: B("id", r.runId),
794
- lock: "update",
795
- order: [],
796
- take: 1,
797
- skip: void 0,
798
- projection: void 0
799
- });
800
- i !== void 0 && await Ht(e, {
801
- runId: r.runId,
802
- workflowName: r.workflowName,
803
- executionId: r.executionId,
804
- generation: r.generation
805
- }, n);
806
- }, $t = async (e, t) => {
807
- let n = await Xt(e, t.requestId);
808
- if (n === void 0) return {
809
- kind: "unknown",
810
- reason: "missing-request"
811
- };
812
- if (n.workflowName !== t.workflowName || n.tenantId !== t.tenantId) throw Error("Queued cancellation request belongs to another workflow or tenant");
813
- if (n.target.kind === "terminal") {
814
- let e = n.target.receipt.terminal;
815
- if (e === null) throw Error("Queued cancellation has no terminal evidence");
816
- return {
817
- kind: e.kind === "cancelled" ? "confirmed" : "already-terminal",
818
- request: n,
819
- outcome: e
820
- };
821
- }
822
- if (n.controlBinding !== null) {
823
- let t = await Zt(e, n);
824
- if (t.result !== null) return {
825
- kind: t.result.kind,
826
- request: n,
827
- control: t
828
- };
829
- let [r] = await e.query({
830
- table: "_voltro_workflow_runs",
831
- predicate: B("id", t.runId),
832
- lock: "update",
833
- order: [],
834
- take: 1,
835
- skip: void 0,
836
- projection: void 0
837
- });
838
- if (r === void 0) return {
839
- kind: "unknown",
840
- reason: "missing-run",
841
- request: n,
842
- control: t
843
- };
844
- if (r.tag !== t.workflowName || r.executionId !== t.executionId) throw Error("Queued cancellation control belongs to another resident execution");
845
- return r.runnerGeneration !== t.generation || r.status !== "running" && r.status !== "suspended" ? {
846
- kind: "unknown",
847
- reason: "unconfirmed-generation",
848
- request: n,
849
- control: t
850
- } : {
851
- kind: "accepted",
852
- request: n,
853
- control: t,
854
- run: r
855
- };
856
- }
857
- let r = await M(e, n.target.submissionId);
858
- if (r === void 0 || !r.receiptsBound || r.workflowName !== n.workflowName || r.tenantId !== n.tenantId) throw Error("Queued cancellation has no matching submission evidence");
859
- return r.failureId === null ? r.retry.stoppedAt !== null || r.runId !== null ? {
860
- kind: "unknown",
861
- reason: "unbound-submission",
862
- request: n
863
- } : {
864
- kind: "accepted",
865
- request: n
866
- } : {
867
- kind: "already-terminal",
868
- request: n,
869
- outcome: {
870
- kind: "rejected",
871
- failureId: await Me(e, r)
872
- }
873
- };
874
- }, en = (e, t) => {
875
- let n = "request" in t ? t.request : void 0;
876
- if (n !== void 0 && (n.id !== e.requestId || n.receiptId !== e.receiptId || n.workflowName !== e.workflowName)) throw Error("Queued control result belongs to another request or receipt");
877
- let r = {
878
- operation: "cancel",
879
- workflowName: e.workflowName,
880
- receiptId: e.receiptId,
881
- requestId: n?.id ?? null,
882
- kind: t.kind
883
- }, i = R.decodeUnknownSync($e);
884
- if (t.kind === "unknown") return i({
885
- ...r,
886
- observation: {
887
- kind: "unavailable",
888
- reason: t.reason
889
- }
890
- });
891
- if ("outcome" in t && t.outcome !== void 0) return i({
892
- ...r,
893
- observation: {
894
- kind: "admission",
895
- outcome: t.outcome
896
- }
897
- });
898
- if ("control" in t && t.control !== void 0) {
899
- let e = t.control, n = e.result;
900
- return i({
901
- ...r,
902
- observation: {
903
- kind: "execution",
904
- snapshot: {
905
- id: e.runId,
906
- workflowName: e.workflowName,
907
- executionId: e.executionId,
908
- status: n?.status ?? ("run" in t ? t.run?.status : void 0),
909
- ...n !== null && n.status === "succeeded" ? { output: n.output } : {},
910
- ...n !== null && n.status === "failed" && n.errorMessage !== null ? { error: {
911
- tag: n.errorTag,
912
- message: n.errorMessage
913
- } } : {}
914
- }
915
- }
916
- });
917
- }
918
- return i({
919
- ...r,
920
- observation: { kind: "pending" }
921
- });
922
- }, tn = async (e, t) => {
923
- let n = R.decodeUnknownSync(R.Struct({
924
- id: R.NonEmptyString,
925
- receiptId: R.NonEmptyString,
926
- workflowName: R.NonEmptyString,
927
- tenantId: R.NullOr(R.String),
928
- requestedAt: R.DateFromSelf,
929
- cause: qt
930
- }))({
931
- id: t.requestId,
932
- receiptId: t.receiptId,
933
- workflowName: t.workflowName,
934
- tenantId: t.tenantId,
935
- requestedAt: new Date(t.now),
936
- cause: t.cause ?? null
937
- });
938
- if (!Number.isFinite(n.requestedAt.getTime())) throw Error("Queued cancellation request requires a valid timestamp");
939
- let r = await Xt(e, n.id);
940
- if (r !== void 0) {
941
- if (r.receiptId !== n.receiptId || r.workflowName !== n.workflowName || r.tenantId !== n.tenantId) throw Error("Queued cancellation identity belongs to a different start or owner");
942
- return await Qt(e, r, t.now), r;
943
- }
944
- let i = await At(e, t), a;
945
- if (i.kind === "submitted") a = {
946
- kind: "submission",
947
- submissionId: i.submissionId
948
- };
949
- else {
950
- let n = await Ce(e, t.receiptId);
951
- if (n === void 0) throw Error("Cancelled start receipt disappeared during request acceptance");
952
- a = {
953
- kind: "terminal",
954
- receipt: n
955
- };
956
- }
957
- let o = Yt({
958
- ...n,
959
- target: a,
960
- controlBinding: null
961
- });
962
- if (await e.insert(Kt.tableName, o), a.kind === "submission") {
963
- let n = await M(e, a.submissionId);
964
- if (n === void 0) throw Error("Queued cancellation submission disappeared during acceptance");
965
- if (n.preparedExecutionId !== null && n.dispatchAttempts > 0) {
966
- let [r] = await e.query({
967
- table: "_voltro_workflow_runs",
968
- predicate: B("executionId", n.preparedExecutionId),
969
- lock: "update",
970
- order: [],
971
- take: 1,
972
- skip: void 0,
973
- projection: void 0
974
- });
975
- if (r !== void 0) {
976
- let n = R.decodeUnknownSync(R.Struct({
977
- id: R.NonEmptyString,
978
- tag: R.NonEmptyString,
979
- executionId: R.NonEmptyString,
980
- runnerGeneration: R.NonEmptyString
981
- }))(r), i = {
982
- runId: n.id,
983
- workflowName: n.tag,
984
- executionId: n.executionId,
985
- generation: n.runnerGeneration
986
- }, a = await nn(e, o.id, i);
987
- return await Qt(e, a.request, t.now), a.request;
988
- }
989
- }
990
- }
991
- return o;
992
- }, nn = async (e, t, n) => {
993
- let r = await Xt(e, t);
994
- if (r === void 0) throw Error("Queued cancellation request is missing");
995
- if (r.target.kind === "terminal") return {
996
- kind: "terminal",
997
- request: r
998
- };
999
- if (r.controlBinding !== null) return {
1000
- kind: "bound",
1001
- request: r,
1002
- control: await Zt(e, r)
1003
- };
1004
- let i = await M(e, r.target.submissionId);
1005
- if (i === void 0 || i.workflowName !== r.workflowName || i.tenantId !== r.tenantId || !i.receiptsBound || i.failureId !== null || i.dispatchAttempts === 0 || i.preparedExecutionId !== n.executionId || i.executionId !== null && i.executionId !== n.executionId || i.runId !== null && i.runId !== n.runId || n.workflowName !== r.workflowName) throw Error("Queued cancellation has no dispatched submission for this resident execution");
1006
- let [a] = await e.query({
1007
- table: "_voltro_workflow_runs",
1008
- predicate: B("id", n.runId),
1009
- lock: "update",
1010
- order: [],
1011
- take: 1,
1012
- skip: void 0,
1013
- projection: void 0
1014
- }), o = R.decodeUnknownOption(R.Struct({ tenantId: R.NullOr(R.String) }))(a?.subject);
1015
- if (a === void 0 || a.tag !== n.workflowName || a.executionId !== n.executionId || a.runnerGeneration !== n.generation || o._tag === "None" || o.value.tenantId !== r.tenantId || ![
1016
- "running",
1017
- "suspended",
1018
- "succeeded",
1019
- "failed",
1020
- "cancelled"
1021
- ].includes(String(a.status))) throw Error("Queued cancellation generation or tenant does not match the resident run");
1022
- let s = {
1023
- controlId: nt("wfctl", JSON.stringify(["queued-cancel", r.id])),
1024
- runId: n.runId,
1025
- executionId: n.executionId,
1026
- generation: n.generation
1027
- }, c = await He(e, {
1028
- id: s.controlId,
1029
- ...n,
1030
- operation: "cancel",
1031
- requestedAt: r.requestedAt.getTime(),
1032
- cause: r.cause
1033
- });
1034
- if (await e.update(Kt.tableName, r.id, { controlBinding: s }) === null) throw Error("Queued cancellation request disappeared during run binding");
1035
- return {
1036
- kind: "bound",
1037
- request: {
1038
- ...r,
1039
- controlBinding: s
1040
- },
1041
- control: c
1042
- };
1043
- }, rn = async (e, t) => {
1044
- let n = /* @__PURE__ */ new Set();
1045
- for await (let r of Ue(e, t.executionId, t.workflowName)) n.add(r.id);
1046
- if (n.size === 0) return !1;
1047
- let r, i = !1;
1048
- for (;;) {
1049
- let a = await e.query({
1050
- table: Kt.tableName,
1051
- predicate: z(B("workflowName", t.workflowName), ...r === void 0 ? [] : [V("id", r)]),
1052
- lock: "update",
1053
- order: [{
1054
- column: "id",
1055
- direction: "asc"
1056
- }],
1057
- take: 100,
1058
- skip: void 0,
1059
- projection: void 0
1060
- });
1061
- for (let o of a) {
1062
- let a = Yt(o);
1063
- if (r = a.id, a.target.kind !== "submission" || !n.has(a.target.submissionId)) continue;
1064
- let s = await nn(e, a.id, t);
1065
- if (s.kind === "bound") {
1066
- if (s.control.runId !== t.runId || s.control.executionId !== t.executionId || s.control.workflowName !== t.workflowName) throw Error("Queued cancellation entry does not match its original resident execution");
1067
- s.control.result === null && (i = !0);
1068
- }
1069
- }
1070
- if (a.length < 100) return i;
1071
- }
1072
- }, an = R.Struct({
1073
- requestId: R.NonEmptyString,
1074
- receiptId: R.NonEmptyString,
1075
- workflowName: R.NonEmptyString,
1076
- tenantId: R.NullOr(R.String)
1077
- }), on = async (e, t) => {
1078
- let n = R.decodeUnknownSync(an)(t);
1079
- return await tn(e, {
1080
- ...n,
1081
- now: t.now,
1082
- ...t.cause === void 0 ? {} : { cause: t.cause }
1083
- }), sn(e, n);
1084
- }, sn = async (e, t) => {
1085
- let n = R.decodeUnknownSync(an)(t);
1086
- return en(n, await $t(e, n));
1087
- }, cn = async (e, t) => {
1088
- if (new Set(t.intentIds).size !== t.intentIds.length) throw Error("Admitted transfer requires distinct pending identities");
1089
- let n = await M(e, t.id);
1090
- if (n !== void 0) {
1091
- if (n.workflowName !== t.workflowName || n.tenantId !== t.tenantId || n.ledgerId !== t.ledgerId || !n.receiptsBound) throw Error("Admitted transfer contradicts its existing submission");
1092
- return n;
1093
- }
1094
- for (let n of t.intentIds) {
1095
- let r = await e.query({
1096
- table: O,
1097
- predicate: B("id", n),
1098
- order: [],
1099
- take: 1,
1100
- skip: void 0,
1101
- projection: void 0,
1102
- lock: "update"
1103
- });
1104
- if (r[0] === void 0) throw Error("Admitted transfer lost a selected input");
1105
- let i = P(r[0]);
1106
- if (i.workflowName !== t.workflowName || i.tenantId !== t.tenantId || i.deadLetteredAt !== void 0) throw Error("Admitted transfer selected a foreign or dead-lettered input");
1107
- }
1108
- let r = await ie(e, t);
1109
- await je(e, r.id);
1110
- for (let t of r.intentIds) if (!await e.delete("_voltro_workflow_pending", t)) throw Error("Admitted input disappeared during submission transfer");
1111
- return {
1112
- ...r,
1113
- receiptsBound: !0
1114
- };
1115
- }, ln = async (e, t) => Pe(e, (e) => un(e, t)), un = async (e, t) => {
1116
- if (t.id.length === 0 || t.intentIds.length === 0 || new Set(t.intentIds).size !== t.intentIds.length) throw Error("Queue transfer requires a submission identity and distinct pending identities");
1117
- let n = await M(e, t.id);
1118
- if (n !== void 0) {
1119
- if (n.workflowName !== t.workflowName || n.tenantId !== t.tenantId) throw Error("Admission submission identity belongs to a different workflow or tenant");
1120
- if (!n.receiptsBound) throw Error("Submission exists without completed queue transfer");
1121
- return {
1122
- kind: "reserved",
1123
- submission: n,
1124
- reused: !0
1125
- };
1126
- }
1127
- let r = [];
1128
- for (let n of t.intentIds) {
1129
- let i = await e.query({
1130
- table: O,
1131
- predicate: B("id", n),
1132
- order: [],
1133
- take: 1,
1134
- skip: void 0,
1135
- projection: void 0,
1136
- lock: "update"
1137
- });
1138
- if (i[0] === void 0) return { kind: "selection-unavailable" };
1139
- let a = P(i[0]);
1140
- if (a.workflowName !== t.workflowName || a.tenantId !== t.tenantId) throw Error("Selected pending start belongs to a different workflow or tenant");
1141
- if (a.deadLetteredAt !== void 0 || a.dueAt > t.now) return { kind: "selection-unavailable" };
1142
- r.push(a);
1143
- }
1144
- let i = t.prepare(r);
1145
- if (i.control.workflowName !== t.workflowName) throw Error("Prepared submission belongs to a different workflow");
1146
- let a = await Ae(e, {
1147
- ...i,
1148
- id: t.id,
1149
- tenantId: t.tenantId,
1150
- intentIds: t.intentIds,
1151
- now: t.now
1152
- });
1153
- if (a.kind !== "reserved") return a;
1154
- await je(e, t.id);
1155
- for (let t of r) if (!await e.delete("_voltro_workflow_pending", t.id)) throw Error("Pending start disappeared during queue transfer");
1156
- return {
1157
- ...a,
1158
- submission: {
1159
- ...a.submission,
1160
- receiptsBound: !0
1161
- }
1162
- };
1163
- }, dn = async (e) => {
1164
- let { store: t, control: n, now: r } = e, i = D(n, e.payload), a = await ce({
1165
- store: t,
1166
- control: n,
1167
- keys: i,
1168
- paused: e.paused,
1169
- now: r,
1170
- reconsidering: !1
1171
- });
1172
- if (a.kind === "drop") return await A({
1173
- store: t,
1174
- control: n,
1175
- keys: i,
1176
- outcome: "dropped",
1177
- mode: "rateLimit",
1178
- reason: `rate limit reached; retry after ${a.retryAfterMs}ms`,
1179
- collapsed: 1,
1180
- waitedMs: 0,
1181
- executionId: null,
1182
- runId: null,
1183
- tenantId: e.tenantId,
1184
- now: r
1185
- }), {
1186
- kind: "dropped",
1187
- retryAfterMs: a.retryAfterMs
1188
- };
1189
- if (a.kind === "skip") return await A({
1190
- store: t,
1191
- control: n,
1192
- keys: i,
1193
- outcome: "skipped",
1194
- mode: "singleton",
1195
- reason: `singleton key held by ${a.incumbent.executionId}`,
1196
- collapsed: 1,
1197
- waitedMs: 0,
1198
- executionId: a.incumbent.executionId,
1199
- runId: a.incumbent.runId || null,
1200
- tenantId: e.tenantId,
1201
- now: r
1202
- }), {
1203
- kind: "skipped",
1204
- executionId: a.incumbent.executionId,
1205
- runId: a.incumbent.runId
1206
- };
1207
- if (a.kind === "defer") return {
1208
- kind: "queued",
1209
- intentId: await ue({
1210
- store: t,
1211
- control: n,
1212
- decision: a,
1213
- payload: e.payload,
1214
- callerContext: e.callerContext,
1215
- tenantId: e.tenantId,
1216
- now: r,
1217
- ...e.queuedAppVersion === void 0 ? {} : { queuedAppVersion: e.queuedAppVersion },
1218
- ...e.queuedSchemaFingerprint === void 0 ? {} : { queuedSchemaFingerprint: e.queuedSchemaFingerprint }
1219
- }),
1220
- mode: a.mode,
1221
- dueAt: a.dueAt
1222
- };
1223
- let o = e.payload, s = [], c = 1;
1224
- if (n.batch !== void 0 && i.batchKey !== void 0) {
1225
- let r = await fn(t, n.workflowName, i.batchKey, n.batch.maxSize);
1226
- o = { items: [...r.map((e) => e.payload), e.payload] }, s = r.map((e) => e.id), c = r.length + 1;
1227
- }
1228
- return {
1229
- kind: "start",
1230
- ledgerId: await A({
1231
- store: t,
1232
- control: n,
1233
- keys: i,
1234
- outcome: "admitted",
1235
- mode: e.waiting ? "immediate" : null,
1236
- reason: a.reason,
1237
- collapsed: c,
1238
- waitedMs: 0,
1239
- executionId: null,
1240
- runId: null,
1241
- tenantId: e.tenantId,
1242
- now: r
1243
- }),
1244
- keys: i,
1245
- payload: o,
1246
- consume: s,
1247
- collapsed: c,
1248
- ...a.evict === void 0 ? {} : { evict: {
1249
- executionId: a.evict.executionId,
1250
- runId: a.evict.runId
1251
- } }
1252
- };
1253
- }, fn = async (e, t, n, r) => (await e.query({
1254
- table: "_voltro_workflow_pending",
1255
- predicate: z(B("workflowName", t), B("controlKey", n), B("mode", "batch")),
1256
- order: [{
1257
- column: "firstSeenAt",
1258
- direction: "asc"
1259
- }],
1260
- take: r,
1261
- skip: void 0,
1262
- projection: void 0
1263
- })).map((n) => ({
1264
- id: String(n.id),
1265
- payload: E(e, t, n.payload)
1266
- })), pn = async (e, t, n, r) => {
1267
- await e.update("_voltro_workflow_admissions", t, {
1268
- executionId: n,
1269
- runId: r
1270
- });
1271
- }, mn = K("_voltro_workflow_watermarks", {
1272
- id: H({ prefix: "wfwm" }),
1273
- positionAt: J(),
1274
- updatedAt: J().default("now")
1275
- }), hn = (e) => {
1276
- let t = e instanceof Error ? e.message : String(e);
1277
- return t.length > 400 ? `${t.slice(0, 400)}…` : t;
1278
- }, gn = (e) => {
1279
- let t = [], n = [], r = [], i = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set(), o = e.payloadSchema === void 0 ? (e) => L.right(e) : (t) => {
1280
- let n = R.decodeUnknownEither(e.payloadSchema)(t);
1281
- return L.isRight(n) ? L.right(n.right) : L.left(hn(n.left));
1282
- }, s = e.runs.map((e) => ({
1283
- run: e,
1284
- decoded: o(e.payload)
1285
- })), c = e.intents.map((e) => ({
1286
- intent: e,
1287
- decoded: o(e.payload)
1288
- }));
1289
- for (let o of e.entries) for (let l of e.events) {
1290
- if (l.name !== o.event) continue;
1291
- let u = R.decodeUnknownEither(o.schema)(l.payload);
1292
- if (L.isLeft(u)) {
1293
- r.push({
1294
- kind: "event-decode",
1295
- workflowName: e.workflowName,
1296
- event: o.event,
1297
- subject: l.id,
1298
- detail: hn(u.left)
1299
- });
1300
- continue;
1301
- }
1302
- let d = u.right, f = (e) => e.getTime() > l.occurredAt.getTime() ? !1 : o.withinMs === void 0 || l.occurredAt.getTime() - e.getTime() <= o.withinMs, p = (t, n) => {
1303
- if (L.isLeft(t)) return r.push({
1304
- kind: "payload-decode",
1305
- workflowName: e.workflowName,
1306
- event: o.event,
1307
- subject: n,
1308
- detail: t.left
1309
- }), !1;
1310
- try {
1311
- return o.match(d, t.right) === !0;
1312
- } catch (t) {
1313
- return r.push({
1314
- kind: "match-threw",
1315
- workflowName: e.workflowName,
1316
- event: o.event,
1317
- subject: n,
1318
- detail: hn(t)
1319
- }), !1;
1320
- }
1321
- };
1322
- for (let { run: e, decoded: n } of s) i.has(e.runId) || f(e.startedAt) && p(n, e.runId) && (i.add(e.runId), t.push({
1323
- runId: e.runId,
1324
- executionId: e.executionId,
1325
- reason: o.reason,
1326
- event: o.event,
1327
- eventId: l.id
1328
- }));
1329
- for (let { intent: e, decoded: t } of c) a.has(e.intentId) || f(e.firstSeenAt) && p(t, e.intentId) && (a.add(e.intentId), n.push({
1330
- intentId: e.intentId,
1331
- reason: o.reason,
1332
- event: o.event,
1333
- eventId: l.id
1334
- }));
1335
- }
1336
- return {
1337
- cancels: t,
1338
- discards: n,
1339
- problems: r
1340
- };
1341
- }, _n = (e) => {
1342
- let t;
1343
- for (let n of e) (t === void 0 || n.occurredAt.getTime() > t.getTime()) && (t = n.occurredAt);
1344
- return t;
1345
- }, vn = "_voltro_workflow_watermarks", yn = "_voltro_workflow_events", bn = "cancelOn", xn = 36e5, Sn = 500, Cn = (e) => {
1346
- if (e instanceof Date) return e;
1347
- if (typeof e == "number") return new Date(e);
1348
- if (typeof e == "string") {
1349
- let t = new Date(e);
1350
- if (!Number.isNaN(t.getTime())) return t;
1351
- }
1352
- }, wn = (e) => e instanceof Error ? e.message : String(e), Tn = async (e, t) => Cn((await e.query({
1353
- table: vn,
1354
- predicate: B("id", t),
1355
- order: [],
1356
- take: 1,
1357
- skip: void 0,
1358
- projection: void 0
1359
- }))[0]?.positionAt), En = async (e, t, n) => {
1360
- await e.upsert(vn, {
1361
- id: t,
1362
- positionAt: n,
1363
- updatedAt: /* @__PURE__ */ new Date()
1364
- }, {
1365
- conflictColumns: ["id"],
1366
- update: (e) => {
1367
- let t = Cn(e.positionAt);
1368
- return t !== void 0 && t.getTime() >= n.getTime() ? {
1369
- positionAt: t,
1370
- updatedAt: /* @__PURE__ */ new Date()
1371
- } : {
1372
- positionAt: n,
1373
- updatedAt: /* @__PURE__ */ new Date()
1374
- };
1375
- }
1376
- });
1377
- }, Dn = async (e, t, n) => {
1378
- let r = async (r) => e.query({
1379
- table: "_voltro_workflow_runs",
1380
- predicate: z(B("tag", t), B("status", r)),
1381
- order: [{
1382
- column: "startedAt",
1383
- direction: "asc"
1384
- }],
1385
- take: n,
1386
- skip: void 0,
1387
- projection: void 0
1388
- });
1389
- return [...await r("running"), ...await r("suspended")].flatMap((e) => {
1390
- let t = e, n = Cn(t.startedAt);
1391
- return typeof t.id != "string" || typeof t.executionId != "string" || n === void 0 ? [] : [{
1392
- runId: t.id,
1393
- executionId: t.executionId,
1394
- payload: t.payload,
1395
- startedAt: n
1396
- }];
1397
- });
1398
- }, On = async (e, t, n) => (await e.query({
1399
- table: "_voltro_workflow_pending",
1400
- predicate: B("workflowName", t),
1401
- order: [{
1402
- column: "firstSeenAt",
1403
- direction: "asc"
1404
- }],
1405
- take: n,
1406
- skip: void 0,
1407
- projection: void 0
1408
- })).flatMap((e) => {
1409
- let t = e, n = Cn(t.firstSeenAt);
1410
- return typeof t.id != "string" || n === void 0 ? [] : [{
1411
- intentId: t.id,
1412
- payload: t.payload,
1413
- firstSeenAt: n
1414
- }];
1415
- }), kn = async (e, t) => {
1416
- let n = t.workflows.filter((e) => e.entries.length > 0);
1417
- if (n.length === 0) return {
1418
- examined: !1,
1419
- events: 0,
1420
- cancelled: 0,
1421
- discarded: 0,
1422
- catchingUp: !1,
1423
- sawFullRunPage: !1,
1424
- problems: [],
1425
- failures: [],
1426
- watermark: void 0
1427
- };
1428
- let r = e.now?.() ?? Date.now(), i = t.batch ?? 500, a = t.coldLookbackMs ?? 36e5, o = /* @__PURE__ */ new Set();
1429
- for (let e of n) for (let t of e.entries) o.add(t.event);
1430
- let s = await Tn(e.store, bn), c = s ?? new Date(r - a);
1431
- s === void 0 && (await En(e.store, bn, c), s = c);
1432
- let l = await e.store.query({
1433
- table: yn,
1434
- predicate: it("occurredAt", c),
1435
- order: [{
1436
- column: "occurredAt",
1437
- direction: "asc"
1438
- }],
1439
- take: i,
1440
- skip: void 0,
1441
- projection: void 0
1442
- }), u = [];
1443
- for (let e of l) {
1444
- let t = e, n = Cn(t.occurredAt);
1445
- typeof t.id == "string" && typeof t.name == "string" && n !== void 0 && o.has(t.name) && u.push({
1446
- id: t.id,
1447
- name: t.name,
1448
- payload: t.payload,
1449
- occurredAt: n
1450
- });
1451
- }
1452
- let d = [], f = [], p = 0, m = 0, h = !1, g = !1, _ = t.runPage ?? 2e3;
1453
- if (u.length > 0) for (let t of n) {
1454
- let n = u.filter((e) => t.entries.some((t) => t.event === e.name));
1455
- if (n.length === 0) continue;
1456
- let r = [], i = [];
1457
- try {
1458
- r = await Dn(e.store, t.workflowName, _), i = await On(e.store, t.workflowName, _), (r.length >= _ || i.length >= _) && (h = !0);
1459
- } catch (e) {
1460
- f.push({
1461
- subject: t.workflowName,
1462
- detail: wn(e)
1463
- }), g = !0;
1464
- continue;
1465
- }
1466
- let a = gn({
1467
- workflowName: t.workflowName,
1468
- entries: t.entries,
1469
- payloadSchema: t.payloadSchema,
1470
- events: n,
1471
- runs: r,
1472
- intents: i
1473
- });
1474
- d.push(...a.problems);
1475
- for (let n of a.cancels) try {
1476
- await e.cancelRun({
1477
- ...n,
1478
- workflowName: t.workflowName
1479
- }), p += 1, e.log?.info("workflow.cancelOn: run cancelled", {
1480
- workflow: t.workflowName,
1481
- runId: n.runId,
1482
- event: n.event,
1483
- eventId: n.eventId
1484
- });
1485
- } catch (e) {
1486
- f.push({
1487
- subject: n.runId,
1488
- detail: wn(e)
1489
- }), g = !0;
1490
- }
1491
- for (let n of a.discards) try {
1492
- await e.discardIntent({
1493
- ...n,
1494
- workflowName: t.workflowName
1495
- }), m += 1;
1496
- } catch (e) {
1497
- f.push({
1498
- subject: n.intentId,
1499
- detail: wn(e)
1500
- }), g = !0;
1501
- }
1502
- }
1503
- let v = _n(u), y = s;
1504
- if (g) e.log?.warn("workflow.cancelOn: holding the watermark — evaluation or delivery remains incomplete", { failures: f.length });
1505
- else if (v !== void 0) try {
1506
- await En(e.store, bn, v), y = v;
1507
- } catch (e) {
1508
- f.push({
1509
- subject: bn,
1510
- detail: wn(e)
1511
- });
1512
- }
1513
- return d.length > 0 && e.log?.warn("workflow.cancelOn: some events could not be evaluated", {
1514
- count: d.length,
1515
- first: d[0]
1516
- }), {
1517
- examined: !0,
1518
- events: u.length,
1519
- cancelled: p,
1520
- discarded: m,
1521
- catchingUp: l.length >= i,
1522
- sawFullRunPage: h,
1523
- problems: d,
1524
- failures: f,
1525
- watermark: y
1526
- };
1527
- }, An = 18e5, jn = 200, Mn = 20, Nn = (e) => {
1528
- if (e instanceof Date) return e;
1529
- if (typeof e == "number") return new Date(e);
1530
- if (typeof e == "string") {
1531
- let t = new Date(e);
1532
- if (!Number.isNaN(t.getTime())) return t;
1533
- }
1534
- }, Pn = (e) => e instanceof Error ? e.message : String(e), Fn = async (e, t, n) => (await e.query({
1535
- table: "_voltro_workflow_run_events",
1536
- predicate: B("runId", t),
1537
- order: [{
1538
- column: "occurredAt",
1539
- direction: "desc"
1540
- }],
1541
- take: n,
1542
- skip: void 0,
1543
- projection: void 0
1544
- })).flatMap((e) => {
1545
- let t = e, n = Nn(t.occurredAt);
1546
- return typeof t.eventType != "string" || n === void 0 ? [] : [{
1547
- eventType: t.eventType,
1548
- occurredAt: n,
1549
- payload: t.payload
1550
- }];
1551
- }), In = async (e, t) => {
1552
- let n = (await e.query({
1553
- table: "_voltro_workflow_run_steps",
1554
- predicate: B("runId", t),
1555
- order: [{
1556
- column: "startedAt",
1557
- direction: "desc"
1558
- }],
1559
- take: 1,
1560
- skip: void 0,
1561
- projection: void 0
1562
- }))[0];
1563
- if (n === void 0) return;
1564
- let r = Nn(n.startedAt), i = Nn(n.completedAt);
1565
- return r === void 0 ? i : i === void 0 ? r : i.getTime() > r.getTime() ? i : r;
1566
- }, Ln = (e, t) => {
1567
- for (let n of e) {
1568
- if (n.eventType === "timer-fired") return !1;
1569
- if (n.eventType !== "timer-set") continue;
1570
- let e = Nn(n.payload?.scheduledWakeAt);
1571
- return e !== void 0 && e.getTime() > t;
1572
- }
1573
- return !1;
1574
- }, Rn = (e, t) => {
1575
- if (e !== "suspended") return "no-progress";
1576
- for (let e of t) {
1577
- if (e.eventType === "signal-received" || e.eventType === "signal-sent") return "suspended";
1578
- if (e.eventType === "signal-awaited") return "awaiting-signal";
1579
- }
1580
- return "suspended";
1581
- }, zn = async (e, t = {}) => {
1582
- let n = e.now?.() ?? Date.now(), r = t.stallAfterMs ?? 18e5, i = t.runPage ?? 200, a = t.eventLookback ?? 20, o = new Date(n - r), s = [], c = [], l = 0, u = 0, d, f;
1583
- try {
1584
- if (!Number.isSafeInteger(i) || i < 1) throw Error("Staleness run page must be a positive integer");
1585
- let n = t.afterRun;
1586
- if (n !== void 0 && (!(n.startedAt instanceof Date) || !Number.isFinite(n.startedAt.getTime()) || typeof n.runId != "string" || n.runId.length === 0)) throw Error("Invalid staleness run cursor");
1587
- d = await e.store.query({
1588
- table: "_voltro_workflow_runs",
1589
- predicate: z(at("status", ["running", "suspended"]), st("startedAt", o), ...n === void 0 ? [] : [ct(V("startedAt", n.startedAt), z(B("startedAt", n.startedAt), V("id", n.runId)))]),
1590
- order: [{
1591
- column: "startedAt",
1592
- direction: "asc"
1593
- }, {
1594
- column: "id",
1595
- direction: "asc"
1596
- }],
1597
- take: i,
1598
- skip: void 0,
1599
- projection: void 0
1600
- });
1601
- let r = n;
1602
- for (let e of d) {
1603
- let t = Nn(e.startedAt);
1604
- if (t === void 0 || !Number.isFinite(t.getTime()) || typeof e.id != "string" || e.id.length === 0) throw Error("Staleness candidate has no valid pagination identity");
1605
- if (r !== void 0 && (t.getTime() < r.startedAt.getTime() || t.getTime() === r.startedAt.getTime() && e.id <= r.runId)) throw Error("Staleness candidate page did not advance");
1606
- r = {
1607
- startedAt: t,
1608
- runId: e.id
1609
- };
1610
- }
1611
- d.length >= i && (f = r);
1612
- } catch (e) {
1613
- return {
1614
- examined: 0,
1615
- stalled: [],
1616
- alreadyReported: 0,
1617
- waitingOnTimer: 0,
1618
- sawFullRunPage: !1,
1619
- failures: [{
1620
- subject: "_voltro_workflow_runs",
1621
- detail: Pn(e)
1622
- }]
1623
- };
1624
- }
1625
- for (let t of d) {
1626
- let i = t, o = Nn(i.startedAt);
1627
- if (typeof i.id != "string" || typeof i.tag != "string" || typeof i.executionId != "string" || typeof i.status != "string" || o === void 0) continue;
1628
- let d, f;
1629
- try {
1630
- d = await Fn(e.store, i.id, a), f = await In(e.store, i.id);
1631
- } catch (e) {
1632
- s.push({
1633
- subject: i.id,
1634
- detail: Pn(e)
1635
- });
1636
- continue;
1637
- }
1638
- if (Ln(d, n)) {
1639
- u += 1;
1640
- continue;
1641
- }
1642
- let p = d.find((e) => e.eventType !== "run-stalled")?.occurredAt, m = o;
1643
- for (let e of [f, p]) e !== void 0 && e.getTime() > m.getTime() && (m = e);
1644
- let h = n - m.getTime();
1645
- if (h < r) continue;
1646
- if (d.some((e) => e.eventType === "run-stalled" && e.occurredAt.getTime() > m.getTime())) {
1647
- l += 1;
1648
- continue;
1649
- }
1650
- let g = {
1651
- runId: i.id,
1652
- tag: i.tag,
1653
- executionId: i.executionId,
1654
- status: i.status,
1655
- lastProgressAt: m,
1656
- idleMs: h,
1657
- reason: Rn(i.status, d)
1658
- };
1659
- c.push(g);
1660
- let _ = {};
1661
- if (e.describeRun !== void 0) try {
1662
- _ = await e.describeRun(g) ?? {};
1663
- } catch (e) {
1664
- s.push({
1665
- subject: `${g.runId}:describeRun`,
1666
- detail: Pn(e)
1667
- });
1668
- }
1669
- if (e.log?.warn("workflow.staleness: run has made no progress", {
1670
- workflow: g.tag,
1671
- runId: g.runId,
1672
- idleMs: g.idleMs,
1673
- reason: g.reason,
1674
- ..._
1675
- }), e.recordEvent !== void 0) try {
1676
- await e.recordEvent({
1677
- runId: g.runId,
1678
- eventType: "run-stalled",
1679
- payload: {
1680
- idleMs: g.idleMs,
1681
- stallAfterMs: r,
1682
- lastProgressAt: g.lastProgressAt.toISOString(),
1683
- reason: g.reason,
1684
- tag: g.tag,
1685
- executionId: g.executionId,
1686
- ..._
1687
- }
1688
- });
1689
- } catch (e) {
1690
- s.push({
1691
- subject: g.runId,
1692
- detail: Pn(e)
1693
- });
1694
- }
1695
- if (e.onStalled !== void 0) try {
1696
- await e.onStalled(g);
1697
- } catch (e) {
1698
- s.push({
1699
- subject: `${g.runId}:onStalled`,
1700
- detail: Pn(e)
1701
- });
1702
- }
1703
- }
1704
- return {
1705
- examined: d.length,
1706
- stalled: c,
1707
- alreadyReported: l,
1708
- waitingOnTimer: u,
1709
- sawFullRunPage: d.length >= i,
1710
- failures: s,
1711
- ...f === void 0 ? {} : { nextRun: f }
1712
- };
1713
- }, Bn = async (e, t, n) => {
1714
- let r = await e.transaction((e) => M(e, t.id));
1715
- if (r === void 0 || r.workflowName !== t.workflowName || r.tenantId !== t.tenantId || r.ledgerId !== t.ledgerId) throw Error("Submission dispatch lost its resident owner");
1716
- if (!r.receiptsBound || r.failureId !== null) throw Error("Cannot dispatch an incomplete or rejected submission");
1717
- if (r.preparedExecutionId !== null) {
1718
- if (r.executionId !== null && r.executionId !== r.preparedExecutionId) throw Error("Submission acceptance contradicts its prepared identity");
1719
- return r.preparedExecutionId;
1720
- }
1721
- if (r.dispatchAttempts !== 0 || r.executionId !== null) throw Error("Submission has an unbound prior dispatch; reconciliation required");
1722
- let i = await e.resolveExecutionId(t.workflowName, n), a = await e.transaction((e) => Be(e, t.id, i));
1723
- if (a.preparedExecutionId === null) throw Error("Submission preparation returned no execution identity");
1724
- return a.preparedExecutionId;
1725
- }, Vn = /* @__PURE__ */ new WeakMap(), Hn = async (e, t, n, r) => {
1726
- let i = Vn.get(e), a = await w(e.store, n, i?.afterId), o = 0, s = 0, c = 0, l = 0, u = i?.nextDueAt, d = (e) => {
1727
- u = Math.min(u ?? e, e);
1728
- };
1729
- for (let n of a) {
1730
- let i;
1731
- try {
1732
- i = Re(n);
1733
- } catch {
1734
- o++, c++, d(t + Ie(1)), e.log?.warn?.("workflow submission metadata is invalid", { submissionId: typeof n.id == "string" ? n.id : null });
1735
- continue;
1736
- }
1737
- o++;
1738
- let a = i.dispatchAttempts === 0 ? 0 : void 0;
1739
- try {
1740
- let n = i.preparedExecutionId, r = n === null || i.dispatchAttempts === 0 ? void 0 : await e.transaction(async (e) => {
1741
- let t = await ne(e, i.workflowName, n);
1742
- return t === void 0 ? void 0 : {
1743
- executionId: n,
1744
- runId: t.runId
1745
- };
1746
- });
1747
- if (r === void 0 && i.retry.stoppedAt !== null) {
1748
- o--;
1749
- continue;
1750
- }
1751
- if (r === void 0 && i.retry.after > t) {
1752
- o--, d(i.retry.after);
1753
- continue;
1754
- }
1755
- if (r === void 0 && e.acquireSubmissionCapacity !== void 0 && !await e.acquireSubmissionCapacity(i)) {
1756
- d(t + 1e3);
1757
- continue;
1758
- }
1759
- let c = r ?? await (async () => {
1760
- let n = e.controls.get(i.workflowName)?.batch === void 0 ? E(e.store, i.workflowName, i.payload) : { items: R.decodeUnknownSync(R.Struct({ items: R.Array(R.Unknown) }))(i.payload).items.map((t) => E(e.store, i.workflowName, t)) }, r = await Bn(e, i, n), o = await e.transaction((e) => xe(e, i.id, t));
1761
- if (o === null) return;
1762
- a = o.dispatchAttempts === 1 ? 1 : void 0;
1763
- let s = await e.startAdmitted(i.workflowName, n, i.callerContext, r);
1764
- if (a = void 0, s.executionId !== r) throw Error("Engine returned a different prepared execution identity");
1765
- return s;
1766
- })();
1767
- if (c === void 0) continue;
1768
- a = void 0, i.eviction !== null && (await e.cancelRun({
1769
- workflowName: i.workflowName,
1770
- ...i.eviction,
1771
- reason: "cancelled to make room for a newer start (singleton mode 'cancel')",
1772
- detail: {
1773
- source: "flow-control",
1774
- mode: "singleton"
1775
- }
1776
- }), await x(e.store, i.eviction.executionId, t)), await e.transaction((e) => we(e, i.id, {
1777
- executionId: c.executionId,
1778
- runId: c.runId ?? null
1779
- })), s++;
1780
- } catch (n) {
1781
- c++;
1782
- let o;
1783
- try {
1784
- if (a !== void 0 && e.isPermanentStartError?.(n) === !0) {
1785
- let r = a, o = await e.transaction((a) => S(a, i.id, r, {
1786
- handler: e.controls.get(i.workflowName)?.onFailure ?? null,
1787
- errorMessage: String(n),
1788
- now: t
1789
- }));
1790
- if (o !== void 0) {
1791
- l++, e.log?.warn?.("workflow submission rejected; failure report retained", {
1792
- workflow: i.workflowName,
1793
- submissionId: i.id,
1794
- failureId: o.id
1795
- });
1796
- continue;
1797
- }
1798
- }
1799
- o = await e.transaction((e) => Ve(e, i.id, String(n), t, r));
1800
- } catch (r) {
1801
- d(t), e.log?.warn?.("workflow submission retry state could not be recorded", {
1802
- workflow: i.workflowName,
1803
- submissionId: i.id,
1804
- cause: y(i.workflowName, n),
1805
- recordingCause: String(r)
1806
- });
1807
- continue;
1808
- }
1809
- o.retry.stoppedAt === null && d(o.retry.after), e.log?.warn?.("workflow submission remains unacknowledged", {
1810
- workflow: i.workflowName,
1811
- submissionId: i.id,
1812
- cause: y(i.workflowName, n),
1813
- retryStoppedAt: o.retry.stoppedAt,
1814
- acceptance: "unknown"
1815
- });
1816
- }
1817
- }
1818
- let f = a.at(-1);
1819
- return a.length === n && f !== void 0 && typeof f.id == "string" ? (Vn.set(e, {
1820
- afterId: f.id,
1821
- nextDueAt: u
1822
- }), {
1823
- scanned: o,
1824
- admitted: s,
1825
- failed: c,
1826
- rejected: l,
1827
- nextDueAt: t,
1828
- examined: !0
1829
- }) : (Vn.delete(e), {
1830
- scanned: o,
1831
- admitted: s,
1832
- failed: c,
1833
- rejected: l,
1834
- nextDueAt: u,
1835
- examined: a.length > 0
1836
- });
1837
- }, Un = /* @__PURE__ */ new WeakMap(), Wn = async (e, t, n) => {
1838
- let r = Un.get(e), i = await e.store.query({
1839
- table: le,
1840
- predicate: z(ot("handler"), W("acceptedExecutionId"), ...r === void 0 ? [] : [V("id", r.afterId)]),
1841
- order: [{
1842
- column: "id",
1843
- direction: "asc"
1844
- }],
1845
- take: n,
1846
- skip: void 0,
1847
- projection: void 0
1848
- }), a = 0, o = !1, s = r?.nextDueAt, c = () => {
1849
- let e = t + Ie(1, () => 1);
1850
- s = Math.min(s ?? e, e);
1851
- };
1852
- for (let n of i) try {
1853
- if (typeof n.id != "string" || n.id.length === 0) throw Error("Failure report has no identity");
1854
- let r = n.id;
1855
- (await e.transaction((e) => se(e, r, t))).kind === "queued" && (o = !0, c());
1856
- } catch (t) {
1857
- a++, c(), e.log?.warn?.("workflow failure delivery could not be reconciled", {
1858
- failureId: typeof n.id == "string" ? n.id : null,
1859
- ...t instanceof Oe ? { reason: t.reason } : {}
1860
- });
1861
- }
1862
- let l = i.at(-1);
1863
- return i.length === n && l !== void 0 && typeof l.id == "string" ? (Un.set(e, {
1864
- afterId: l.id,
1865
- nextDueAt: s
1866
- }), {
1867
- scanned: i.length,
1868
- failed: a,
1869
- hasPending: o,
1870
- nextDueAt: t,
1871
- examined: !0
1872
- }) : (Un.delete(e), {
1873
- scanned: i.length,
1874
- failed: a,
1875
- hasPending: o,
1876
- nextDueAt: s,
1877
- examined: i.length > 0
1878
- });
1879
- }, Gn = "_voltro_workflow_parent_closures", Kn = /* @__PURE__ */ new WeakMap(), qn = async (e, t, n) => {
1880
- let r = Kn.get(e), i = await e.store.query({
1881
- table: Gn,
1882
- predicate: z(W("completedAt"), ...r === void 0 ? [] : [V("id", r.afterId)]),
1883
- order: [{
1884
- column: "id",
1885
- direction: "asc"
1886
- }],
1887
- take: n,
1888
- skip: void 0,
1889
- projection: void 0
1890
- }), a = 0, o = r?.nextDueAt, s = () => {
1891
- o = Math.min(o ?? t + 1e3, t + 1e3);
1892
- };
1893
- for (let n of i) try {
1894
- if (typeof n.id != "string" || n.id.length === 0) throw Error("Parent closure has no identity");
1895
- let r = n.id;
1896
- await e.transaction(async (e) => {
1897
- await Ft(e, r, t);
1898
- let [n] = await e.query({
1899
- table: Gn,
1900
- predicate: B("id", r),
1901
- order: [],
1902
- take: 1,
1903
- skip: void 0,
1904
- projection: ["completedAt"]
1905
- });
1906
- if (n === void 0) throw Error("Parent closure disappeared");
1907
- return n.completedAt instanceof Date && Number.isFinite(n.completedAt.getTime());
1908
- }) || s();
1909
- } catch {
1910
- a++, s(), e.log?.warn?.("workflow parent closure could not be reconciled", { closureId: typeof n.id == "string" ? n.id : null });
1911
- }
1912
- let c = i.at(-1);
1913
- return i.length === n && typeof c?.id == "string" ? (Kn.set(e, {
1914
- afterId: c.id,
1915
- nextDueAt: o
1916
- }), {
1917
- scanned: i.length,
1918
- failed: a,
1919
- nextDueAt: t,
1920
- examined: !0
1921
- }) : (Kn.delete(e), {
1922
- scanned: i.length,
1923
- failed: a,
1924
- nextDueAt: o,
1925
- examined: i.length > 0
1926
- });
1927
- }, Jn = async (e, t) => {
1928
- if (t.from === t.to) throw Error("Queue transfer requires distinct source and target");
1929
- let n = await e.query({
1930
- table: O,
1931
- predicate: B("id", t.to),
1932
- order: [],
1933
- take: 1,
1934
- skip: void 0,
1935
- projection: void 0
1936
- }), r = R.decodeUnknownSync(R.Struct({
1937
- workflowName: R.String,
1938
- tenantId: R.NullOr(R.String)
1939
- }))(n[0]);
1940
- if (r.workflowName !== t.workflowName || r.tenantId !== t.tenantId) throw Error("Receipt target belongs to a different workflow or tenant");
1941
- for (;;) {
1942
- let n = await e.query({
1943
- table: De,
1944
- predicate: z(B("pendingId", t.from), W("submissionId"), W("terminal")),
1945
- order: [{
1946
- column: "id",
1947
- direction: "asc"
1948
- }],
1949
- take: 100,
1950
- skip: void 0,
1951
- projection: void 0
1952
- });
1953
- if (n.length === 0) return;
1954
- for (let r of n) {
1955
- let n = Fe(r);
1956
- if (n.workflowName !== t.workflowName || n.tenantId !== t.tenantId) throw Error("Forwarded receipt belongs to a different workflow or tenant");
1957
- if (await e.update("_voltro_workflow_start_receipts", n.id, { pendingId: t.to }) === null) throw Error("Start receipt disappeared during queue transfer");
1958
- }
1959
- }
1960
- }, Yn = {
1961
- scanned: 0,
1962
- admitted: 0,
1963
- deferred: 0,
1964
- dropped: 0,
1965
- skipped: 0,
1966
- expired: 0,
1967
- evicted: 0,
1968
- failed: 0,
1969
- deadLettered: 0,
1970
- timedOut: 0,
1971
- examined: !1
1972
- }, Xn = 200, Zn = class extends Error {
1973
- submissionId;
1974
- rejected;
1975
- constructor(e, t, n = !1) {
1976
- super(n ? `Submission ${e} rejected; failure report retained` : `Submission ${e} remains unacknowledged`, { cause: t }), this.submissionId = e, this.rejected = n;
1977
- }
1978
- }, Qn = (e) => e instanceof Zn && !e.rejected, $n = async (e, t = {}) => {
1979
- let n = e.now ?? (() => Date.now()), r = e.log, i = t.batchSize ?? 200, a, o, s, c, l, u;
1980
- try {
1981
- c = await Hn(e, n(), i, e.deadLetterAfterAttempts ?? 50), l = await Wn(e, n(), i), u = await qn(e, n(), i), a = await (e.readPauses?.() ?? be(e.store));
1982
- let r = t.skipPending === !0 && !l.hasPending ? {
1983
- due: [],
1984
- nextDueAt: void 0
1985
- } : await Ne(e.store, n(), i);
1986
- o = r.due, s = c.nextDueAt === void 0 ? r.nextDueAt : Math.min(r.nextDueAt ?? c.nextDueAt, c.nextDueAt), l.nextDueAt !== void 0 && (s = Math.min(s ?? l.nextDueAt, l.nextDueAt)), u.nextDueAt !== void 0 && (s = Math.min(s ?? u.nextDueAt, u.nextDueAt));
1987
- } catch (e) {
1988
- return r?.warn?.("workflow flow control: could not read the admission queue", { cause: String(e) }), {
1989
- ...Yn,
1990
- scanned: (c?.scanned ?? 0) + (l?.scanned ?? 0) + (u?.scanned ?? 0),
1991
- admitted: c?.admitted ?? 0,
1992
- deadLettered: c?.rejected ?? 0,
1993
- failed: (c?.failed ?? 0) + (l?.failed ?? 0) + (u?.failed ?? 0) + 1,
1994
- nextDueAt: n()
1995
- };
1996
- }
1997
- let d = {
1998
- scanned: o.length + c.scanned + l.scanned + u.scanned,
1999
- admitted: c.admitted,
2000
- deferred: 0,
2001
- dropped: 0,
2002
- skipped: 0,
2003
- expired: 0,
2004
- evicted: 0,
2005
- failed: c.failed + l.failed + u.failed,
2006
- deadLettered: c.rejected,
2007
- timedOut: 0
2008
- }, f = /* @__PURE__ */ new Map(), m = [];
2009
- for (let e of o) {
2010
- if (e.mode === "batch") {
2011
- let t = `${e.workflowName}\u0000${e.controlKey}`, n = f.get(t);
2012
- n === void 0 ? f.set(t, [e]) : n.push(e);
2013
- continue;
2014
- }
2015
- m.push(e);
2016
- }
2017
- let h = e.deadLetterAfterAttempts === void 0 ? 50 : e.deadLetterAfterAttempts, g = (t, n, r) => {
2018
- if (e.isPermanentStartError?.(n) === !0) return `pending ${r} was dead-lettered after a permanent start failure: ${String(n)}`;
2019
- if (h !== !1 && t.attempts + 1 >= h) return `pending ${r} was dead-lettered after ${t.attempts + 1} failed attempts: ${String(n)}`;
2020
- };
2021
- for (let t of m) try {
2022
- await rr(e, t, a, d, n());
2023
- } catch (i) {
2024
- if (d.failed++, i instanceof Zn) {
2025
- i.rejected && d.deadLettered++, r?.warn?.(i.message, {
2026
- submissionId: i.submissionId,
2027
- cause: y(t.workflowName, i.cause)
2028
- });
2029
- continue;
2030
- }
2031
- let a = g(t, i, "intent");
2032
- if (a !== void 0) {
2033
- let o = n(), s = String(i);
2034
- if (await tr(e, [t], a, s, o, !1).catch((e) => (r?.warn?.("workflow flow control: intent could not be dead-lettered with its report", {
2035
- workflow: t.workflowName,
2036
- intent: t.id,
2037
- cause: String(e)
2038
- }), 0)) > 0) {
2039
- d.deadLettered++, r?.warn?.("workflow flow control: intent dead-lettered", {
2040
- workflow: t.workflowName,
2041
- intent: t.id,
2042
- cause: y(t.workflowName, s)
2043
- });
2044
- continue;
2045
- }
2046
- }
2047
- r?.warn?.("workflow flow control: an intent failed to drain", {
2048
- workflow: t.workflowName,
2049
- intent: t.id,
2050
- cause: y(t.workflowName, i)
2051
- }), await _e(e.store, t, String(i), n()).catch(() => {});
2052
- }
2053
- for (let t of f.values()) try {
2054
- await ar(e, t, a, d, n());
2055
- } catch (i) {
2056
- if (d.failed++, i instanceof Zn) {
2057
- i.rejected && d.deadLettered++, r?.warn?.(i.message, {
2058
- submissionId: i.submissionId,
2059
- cause: y(t[0]?.workflowName, i.cause)
2060
- });
2061
- continue;
2062
- }
2063
- let a = t[0], o = a === void 0 ? void 0 : g(a, i, "batch");
2064
- if (a !== void 0 && o !== void 0) {
2065
- let s = n(), c = String(i);
2066
- if (await tr(e, t, o, c, s, !0).catch((e) => (r?.warn?.("workflow flow control: batch could not be dead-lettered with its report", {
2067
- workflow: a.workflowName,
2068
- intents: t.map((e) => e.id),
2069
- size: t.length,
2070
- cause: String(e)
2071
- }), 0)) === t.length) {
2072
- d.deadLettered += t.length, r?.warn?.("workflow flow control: batch dead-lettered", {
2073
- workflow: a.workflowName,
2074
- intents: t.map((e) => e.id),
2075
- size: t.length,
2076
- cause: y(a.workflowName, c)
2077
- });
2078
- continue;
2079
- }
2080
- }
2081
- r?.warn?.("workflow flow control: a batch failed to drain", {
2082
- workflow: a?.workflowName,
2083
- size: t.length,
2084
- cause: y(a?.workflowName, i)
2085
- });
2086
- let s = n(), c = Math.random();
2087
- await e.transaction(async (e) => {
2088
- let n = [];
2089
- for (let r of t) {
2090
- let t = await e.query({
2091
- table: O,
2092
- predicate: B("id", r.id),
2093
- order: [],
2094
- take: 1,
2095
- skip: void 0,
2096
- projection: void 0,
2097
- lock: "update"
2098
- });
2099
- if (t[0] === void 0) return;
2100
- let i = P(t[0]);
2101
- if (i.workflowName !== r.workflowName || i.tenantId !== r.tenantId || i.mode !== r.mode || i.firstSeenAt !== r.firstSeenAt || i.dueAt !== r.dueAt || i.deadLetteredAt !== void 0) return;
2102
- n.push(i);
2103
- }
2104
- let r = new Date(s + Ie(Math.max(...n.map((e) => e.attempts + 1)), () => c));
2105
- for (let t of n) if (await e.update("_voltro_workflow_pending", t.id, {
2106
- attempts: t.attempts + 1,
2107
- lastError: p(t.workflowName, String(i).slice(0, 500)),
2108
- dueAt: r,
2109
- updatedAt: new Date(s)
2110
- }) === null) throw Error("Batch input disappeared while recording the shared retry deadline");
2111
- }).catch((e) => r?.warn?.("workflow flow control: batch retry could not be persisted", {
2112
- workflow: a?.workflowName,
2113
- intents: t.map((e) => e.id),
2114
- cause: String(e)
2115
- }));
2116
- }
2117
- let _ = await lr(e, n()).catch(() => ({ cancelled: 0 }));
2118
- return d.timedOut = _.cancelled, _.nextDeadlineAt !== void 0 && (s === void 0 || _.nextDeadlineAt < s) && (s = _.nextDeadlineAt), {
2119
- ...d,
2120
- examined: t.skipPending !== !0 || c.examined || l.examined || u.examined,
2121
- ...s === void 0 ? {} : { nextDueAt: s }
2122
- };
2123
- }, er = async (e, t, n) => {
2124
- let r = t.map((e) => ({
2125
- intent: e,
2126
- failureId: `wff_${ht()}`
2127
- }));
2128
- return e.transaction(async (e) => {
2129
- let t = 0;
2130
- for (let { intent: i, failureId: a } of r) {
2131
- let r = (await e.query({
2132
- table: O,
2133
- predicate: B("id", i.id),
2134
- order: [],
2135
- take: 1,
2136
- skip: void 0,
2137
- projection: void 0,
2138
- lock: "update"
2139
- }))[0];
2140
- if (r === void 0) continue;
2141
- let o = P(r);
2142
- if (o.workflowName !== i.workflowName || o.tenantId !== i.tenantId) throw Error("Abandoned queue selection belongs to another workflow or tenant");
2143
- if (o.dueAt > n || o.deadLetteredAt !== void 0) continue;
2144
- let s = `workflow '${o.workflowName}' no longer has its queued declaration`;
2145
- if (await j(e, {
2146
- id: a,
2147
- sourceKind: "intent",
2148
- sourceId: o.id,
2149
- workflowName: o.workflowName,
2150
- tenantId: o.tenantId,
2151
- handler: null,
2152
- callerContext: o.callerContext,
2153
- report: {
2154
- workflow: o.workflowName,
2155
- payload: o.payload,
2156
- reason: s,
2157
- failedAt: n,
2158
- errorTag: null,
2159
- errorMessage: null,
2160
- runId: null,
2161
- executionId: null
2162
- }
2163
- }), await N(e, {
2164
- pendingId: o.id,
2165
- workflowName: o.workflowName,
2166
- tenantId: o.tenantId,
2167
- terminal: {
2168
- kind: "abandoned",
2169
- at: n,
2170
- failureId: a
2171
- }
2172
- }), !await e.delete("_voltro_workflow_pending", o.id)) throw Error("Abandoned queue row disappeared before deletion");
2173
- t++;
2174
- }
2175
- return t;
2176
- });
2177
- }, tr = async (e, t, n, r, i, a) => {
2178
- let o = `wff_${ht()}`;
2179
- return e.transaction(async (s) => {
2180
- let c = [];
2181
- for (let e of t) {
2182
- let t = await s.query({
2183
- table: O,
2184
- predicate: B("id", e.id),
2185
- order: [],
2186
- take: 1,
2187
- skip: void 0,
2188
- projection: void 0,
2189
- lock: "update"
2190
- });
2191
- if (t[0] === void 0) return 0;
2192
- let n = P(t[0]);
2193
- if (n.workflowName !== e.workflowName || n.tenantId !== e.tenantId) throw Error("Dead-letter selection belongs to another workflow or tenant");
2194
- if (n.deadLetteredAt !== void 0) return 0;
2195
- c.push(n);
2196
- }
2197
- let l = c[0];
2198
- if (l === void 0) return 0;
2199
- let u = await Promise.all(c.map((e) => me(s, e.id)));
2200
- if (u.some(Boolean) && !u.every(Boolean)) throw Error("Dead-lettered batch mixes failure delivery and ordinary callers; reconciliation required");
2201
- let d = e.controls.get(l.workflowName);
2202
- await j(s, {
2203
- id: o,
2204
- sourceKind: "intent",
2205
- sourceId: l.id,
2206
- workflowName: l.workflowName,
2207
- tenantId: l.tenantId,
2208
- handler: u.every(Boolean) ? null : d?.onFailure ?? null,
2209
- callerContext: l.callerContext,
2210
- report: {
2211
- workflow: l.workflowName,
2212
- payload: a ? { items: c.map((e) => e.payload) } : l.payload,
2213
- reason: n,
2214
- failedAt: i,
2215
- errorTag: null,
2216
- errorMessage: r.slice(0, 500),
2217
- runId: null,
2218
- executionId: null
2219
- }
2220
- });
2221
- for (let e of c) if (await N(s, {
2222
- pendingId: e.id,
2223
- workflowName: e.workflowName,
2224
- tenantId: e.tenantId,
2225
- terminal: {
2226
- kind: "abandoned",
2227
- at: i,
2228
- failureId: o
2229
- }
2230
- }), !await oe(s, e, r, i)) throw Error("Dead-lettered queue row disappeared before marking");
2231
- return await fe(s, o, i), c.length;
2232
- });
2233
- }, nr = async (e, t, n, r, i) => {
2234
- let a = `wff_${ht()}`;
2235
- return e.transaction(async (e) => {
2236
- let o = [];
2237
- for (let i of t) {
2238
- let t = await e.query({
2239
- table: O,
2240
- predicate: B("id", i.id),
2241
- order: [],
2242
- take: 1,
2243
- skip: void 0,
2244
- projection: void 0,
2245
- lock: "update"
2246
- });
2247
- if (t[0] === void 0) return 0;
2248
- let a = P(t[0]);
2249
- if (a.workflowName !== n.workflowName || a.tenantId !== i.tenantId) throw Error("Expired queue selection belongs to another workflow or tenant");
2250
- if (a.mode !== i.mode || a.dueAt > r || a.deadLetteredAt !== void 0) return 0;
2251
- o.push(a);
2252
- }
2253
- o.sort((e, t) => e.firstSeenAt - t.firstSeenAt || e.id.localeCompare(t.id));
2254
- let s = o[0];
2255
- if (s === void 0 || !ve(n, s, r)) return 0;
2256
- let c = await Promise.all(o.map((t) => me(e, t.id)));
2257
- if (c.some(Boolean) && !c.every(Boolean)) throw Error("Expired batch mixes failure delivery and ordinary callers; reconciliation required");
2258
- let l = `timeouts.start (${n.timeouts?.startMs}ms) elapsed while ${o.length} queued input(s) waited`;
2259
- await j(e, {
2260
- id: a,
2261
- sourceKind: "intent",
2262
- sourceId: s.id,
2263
- workflowName: s.workflowName,
2264
- tenantId: s.tenantId,
2265
- handler: c.every(Boolean) ? null : n.onFailure ?? null,
2266
- callerContext: s.callerContext,
2267
- report: {
2268
- workflow: s.workflowName,
2269
- payload: i ? { items: o.map((e) => e.payload) } : s.payload,
2270
- reason: l,
2271
- failedAt: r,
2272
- errorTag: null,
2273
- errorMessage: null,
2274
- runId: null,
2275
- executionId: null
2276
- }
2277
- }), await A({
2278
- store: e,
2279
- control: n,
2280
- keys: D(n, E(e, s.workflowName, s.payload)),
2281
- outcome: "expired",
2282
- mode: s.mode,
2283
- reason: l,
2284
- collapsed: o.reduce((e, t) => e + t.collapsed, 0),
2285
- waitedMs: r - s.firstSeenAt,
2286
- executionId: null,
2287
- runId: null,
2288
- tenantId: s.tenantId,
2289
- now: r
2290
- });
2291
- for (let t of o) if (await N(e, {
2292
- pendingId: t.id,
2293
- workflowName: t.workflowName,
2294
- tenantId: t.tenantId,
2295
- terminal: {
2296
- kind: "abandoned",
2297
- at: r,
2298
- failureId: a
2299
- }
2300
- }), !await e.delete("_voltro_workflow_pending", t.id)) throw Error("Expired queue row disappeared before deletion");
2301
- return await fe(e, a, r), o.length;
2302
- });
2303
- }, rr = async (e, t, n, r, i) => {
2304
- if (t = {
2305
- ...t,
2306
- payload: E(e.store, t.workflowName, t.payload)
2307
- }, t.mode === "delayed") return ir(e, t, n, r, i);
2308
- let a = e.controls.get(t.workflowName);
2309
- if (a === void 0) {
2310
- r.expired += await er(e, [t], i);
2311
- return;
2312
- }
2313
- if (ve(a, t, i)) {
2314
- r.expired += await nr(e, [t], a, i, !1);
2315
- return;
2316
- }
2317
- let o = D(a, t.payload), s = await ce({
2318
- store: e.store,
2319
- control: a,
2320
- keys: o,
2321
- paused: n.has(t.workflowName),
2322
- now: i,
2323
- reconsidering: !0
2324
- });
2325
- await or(e, {
2326
- control: a,
2327
- intent: t,
2328
- decision: s,
2329
- keys: o,
2330
- counters: r,
2331
- now: i,
2332
- paused: n,
2333
- items: void 0
2334
- });
2335
- }, ir = async (e, t, n, r, i) => {
2336
- if (e.registeredWorkflows !== void 0 && !e.registeredWorkflows.has(t.workflowName)) {
2337
- r.expired += await er(e, [t], i);
2338
- return;
2339
- }
2340
- let a = e.controls.get(t.workflowName) ?? { workflowName: t.workflowName }, o = Se(), s = await e.transaction(async (e) => {
2341
- let r = await e.query({
2342
- table: O,
2343
- predicate: B("id", t.id),
2344
- lock: "update",
2345
- order: [],
2346
- take: 1,
2347
- skip: void 0,
2348
- projection: void 0
2349
- });
2350
- if (r[0] === void 0) return;
2351
- let s = P(r[0]);
2352
- if (s.workflowName !== t.workflowName || s.tenantId !== t.tenantId) throw Error("Delayed arrival belongs to a different workflow or tenant");
2353
- if (s.mode !== "delayed" || s.deadLetteredAt !== void 0 || s.dueAt > i) return;
2354
- let c = await dn({
2355
- store: e,
2356
- control: a,
2357
- payload: E(e, s.workflowName, s.payload),
2358
- callerContext: s.callerContext,
2359
- tenantId: s.tenantId,
2360
- paused: n.has(s.workflowName),
2361
- now: i,
2362
- waiting: !1
2363
- });
2364
- if (c.kind === "queued" && (await Jn(e, {
2365
- from: s.id,
2366
- to: c.intentId,
2367
- workflowName: s.workflowName,
2368
- tenantId: s.tenantId
2369
- }), !await de(e, s.id))) throw Error("Delayed arrival disappeared during queue transfer");
2370
- if (c.kind === "start") {
2371
- if (c.ledgerId === void 0) throw Error("Delayed arrival has no admission reservation");
2372
- let t = a.batch === void 0 ? ye(e, s.workflowName, c.payload) : { items: R.decodeUnknownSync(R.Struct({ items: R.Array(R.Unknown) }))(c.payload).items.map((t) => ye(e, s.workflowName, t)) };
2373
- return {
2374
- kind: "submission",
2375
- submission: await cn(e, {
2376
- id: o,
2377
- workflowName: s.workflowName,
2378
- tenantId: s.tenantId,
2379
- ledgerId: c.ledgerId,
2380
- payload: t,
2381
- callerContext: s.callerContext,
2382
- intentIds: [.../* @__PURE__ */ new Set([s.id, ...c.consume])],
2383
- eviction: c.evict ?? null
2384
- }),
2385
- keys: c.keys
2386
- };
2387
- }
2388
- if ((c.kind === "dropped" || c.kind === "skipped") && (await N(e, {
2389
- pendingId: s.id,
2390
- workflowName: s.workflowName,
2391
- tenantId: s.tenantId,
2392
- terminal: {
2393
- ...c,
2394
- at: i
2395
- }
2396
- }), !await de(e, s.id))) throw Error("Delayed arrival disappeared while recording its outcome");
2397
- return c;
2398
- });
2399
- if (s !== void 0) {
2400
- if (s.kind === "queued") {
2401
- r.deferred++;
2402
- return;
2403
- }
2404
- if (s.kind === "dropped") {
2405
- r.dropped++;
2406
- return;
2407
- }
2408
- if (s.kind === "skipped") {
2409
- r.skipped++;
2410
- return;
2411
- }
2412
- await cr(e, s.submission, a, r, i, a.batch !== void 0, s.keys);
2413
- }
2414
- }, ar = async (e, t, n, r, i) => {
2415
- t = t.map((t) => ({
2416
- ...t,
2417
- payload: E(e.store, t.workflowName, t.payload)
2418
- }));
2419
- let a = t[0];
2420
- if (a === void 0) return;
2421
- let o = e.controls.get(a.workflowName);
2422
- if (o === void 0 || o.batch === void 0) {
2423
- r.expired += await er(e, t, i);
2424
- return;
2425
- }
2426
- let s = [...t].sort((e, t) => e.firstSeenAt - t.firstSeenAt), c = s[0];
2427
- if (ve(o, c, i)) {
2428
- r.expired += await nr(e, s, o, i, !0);
2429
- return;
2430
- }
2431
- let l = D(o, c.payload);
2432
- await or(e, {
2433
- control: o,
2434
- intent: c,
2435
- decision: await ce({
2436
- store: e.store,
2437
- control: o,
2438
- keys: l,
2439
- paused: n.has(a.workflowName),
2440
- now: i,
2441
- reconsidering: !0
2442
- }),
2443
- keys: l,
2444
- counters: r,
2445
- now: i,
2446
- paused: n,
2447
- items: s
2448
- });
2449
- }, or = async (e, t) => {
2450
- let { control: n, intent: r, decision: i, keys: a, counters: o, now: s, items: c, paused: l } = t;
2451
- if (i.kind === "defer") {
2452
- await ue({
2453
- store: e.store,
2454
- control: n,
2455
- decision: i,
2456
- payload: r.payload,
2457
- callerContext: r.callerContext,
2458
- tenantId: r.tenantId,
2459
- now: s,
2460
- existingId: r.id
2461
- }), o.deferred++;
2462
- return;
2463
- }
2464
- if (i.kind === "drop" || i.kind === "skip") {
2465
- let t = await e.transaction(async (e) => {
2466
- let t = [];
2467
- for (let i of c ?? [r]) {
2468
- let a = await e.query({
2469
- table: O,
2470
- predicate: B("id", i.id),
2471
- lock: "update",
2472
- order: [],
2473
- take: 1,
2474
- skip: void 0,
2475
- projection: void 0
2476
- });
2477
- if (a[0] === void 0) return;
2478
- let o = P(a[0]);
2479
- if (o.workflowName !== n.workflowName || o.tenantId !== r.tenantId) throw Error("Terminal queue selection belongs to a different workflow or tenant");
2480
- if (o.dueAt > s || o.deadLetteredAt !== void 0 || o.mode !== i.mode) return;
2481
- t.push(o);
2482
- }
2483
- t.sort((e, t) => e.firstSeenAt - t.firstSeenAt);
2484
- let i = t[0], a = D(n, E(e, n.workflowName, i.payload)), o = await ce({
2485
- store: e,
2486
- control: n,
2487
- keys: a,
2488
- paused: l.has(n.workflowName) || (await be(e)).has(n.workflowName),
2489
- now: s,
2490
- reconsidering: !0
2491
- });
2492
- if (o.kind !== "drop" && o.kind !== "skip") return;
2493
- let u = o.kind === "drop" ? {
2494
- kind: "dropped",
2495
- at: s,
2496
- retryAfterMs: o.retryAfterMs
2497
- } : {
2498
- kind: "skipped",
2499
- at: s,
2500
- executionId: o.incumbent.executionId,
2501
- runId: o.incumbent.runId
2502
- };
2503
- await A({
2504
- store: e,
2505
- control: n,
2506
- keys: a,
2507
- outcome: u.kind,
2508
- mode: u.kind === "dropped" ? "rateLimit" : "singleton",
2509
- reason: u.kind === "dropped" ? `rate limit reached while queued; retry after ${u.retryAfterMs}ms` : `singleton key held by ${u.executionId}`,
2510
- collapsed: t.reduce((e, t) => e + t.collapsed, 0),
2511
- waitedMs: s - i.firstSeenAt,
2512
- executionId: u.kind === "skipped" ? u.executionId : null,
2513
- runId: u.kind === "skipped" && u.runId || null,
2514
- tenantId: r.tenantId,
2515
- now: s
2516
- });
2517
- for (let n of t) if (await N(e, {
2518
- pendingId: n.id,
2519
- workflowName: n.workflowName,
2520
- tenantId: n.tenantId,
2521
- terminal: u
2522
- }), !await de(e, n.id)) throw Error("Queued input disappeared while recording its terminal outcome");
2523
- return u.kind;
2524
- });
2525
- t !== void 0 && o[t]++;
2526
- return;
2527
- }
2528
- let u = Se(), d = await e.transaction((t) => un(t, {
2529
- id: u,
2530
- workflowName: n.workflowName,
2531
- tenantId: r.tenantId,
2532
- intentIds: (c ?? [r]).map((e) => e.id),
2533
- now: s,
2534
- prepare: (t) => {
2535
- let r = [...t].sort((e, t) => e.firstSeenAt - t.firstSeenAt), i = r[0], a = E(e.store, n.workflowName, i.payload);
2536
- return {
2537
- control: n,
2538
- keyPayload: a,
2539
- encodedPayload: c === void 0 ? i.payload : { items: r.map((e) => e.payload) },
2540
- callerContext: i.callerContext,
2541
- paused: l.has(n.workflowName),
2542
- firstSeenAt: i.firstSeenAt,
2543
- collapsed: r.reduce((e, t) => e + t.collapsed, 0),
2544
- mode: i.mode
2545
- };
2546
- }
2547
- }));
2548
- if (d.kind !== "selection-unavailable") {
2549
- if (d.kind === "not-admitted") {
2550
- o.deferred++;
2551
- return;
2552
- }
2553
- await cr(e, d.submission, n, o, s, c !== void 0, a);
2554
- }
2555
- }, sr = async (e, t, n, r, i) => {
2556
- let a = await e.transaction((e) => M(e, t.id));
2557
- if (a === void 0 || !a.receiptsBound || a.workflowName !== n.workflowName || a.workflowName !== t.workflowName || a.tenantId !== t.tenantId || a.ledgerId !== t.ledgerId) throw Error("Admission acceptance callback no longer has its resident submission owner");
2558
- if (a.executionId !== null) {
2559
- if (a.failureId !== null || a.executionId.length === 0 || a.executionId !== a.preparedExecutionId) throw Error("Admission acceptance has contradictory resident execution evidence");
2560
- return a.executionId;
2561
- }
2562
- await cr(e, a, n, {
2563
- admitted: 0,
2564
- deferred: 0,
2565
- dropped: 0,
2566
- skipped: 0,
2567
- expired: 0,
2568
- evicted: 0
2569
- }, i, n.batch !== void 0, r);
2570
- let o = await e.transaction((e) => M(e, t.id));
2571
- if (o?.executionId == null || o.executionId !== o.preparedExecutionId) throw Error("Admission submission has no confirmed engine acceptance");
2572
- return o.executionId;
2573
- }, cr = async (e, t, n, r, i, a, o) => {
2574
- let s = t.dispatchAttempts === 0 ? 0 : void 0;
2575
- try {
2576
- if (e.acquireSubmissionCapacity !== void 0 && !await e.acquireSubmissionCapacity(t)) {
2577
- r.deferred++;
2578
- return;
2579
- }
2580
- let c = a ? { items: R.decodeUnknownSync(R.Struct({ items: R.Array(R.Unknown) }))(t.payload).items.map((t) => E(e.store, n.workflowName, t)) } : E(e.store, n.workflowName, t.payload), l = await Bn(e, t, c), u = await e.transaction((e) => xe(e, t.id, i));
2581
- if (u === null) return;
2582
- s = u.dispatchAttempts === 1 ? 1 : void 0;
2583
- let d = await e.startAdmitted(n.workflowName, c, t.callerContext, l);
2584
- if (s = void 0, d.executionId !== l) throw Error("Engine returned a different prepared execution identity");
2585
- t.eviction !== null && (await e.cancelRun({
2586
- workflowName: n.workflowName,
2587
- runId: t.eviction.runId,
2588
- executionId: t.eviction.executionId,
2589
- reason: "cancelled to make room for a newer start (singleton mode 'cancel')",
2590
- detail: {
2591
- source: "flow-control",
2592
- mode: "singleton"
2593
- }
2594
- }), await x(e.store, t.eviction.executionId, i), await A({
2595
- store: e.store,
2596
- control: n,
2597
- keys: o,
2598
- outcome: "evicted",
2599
- mode: "singleton",
2600
- reason: "cancelled to make room for a newer start (singleton mode 'cancel')",
2601
- collapsed: 1,
2602
- waitedMs: null,
2603
- executionId: t.eviction.executionId,
2604
- runId: t.eviction.runId || null,
2605
- tenantId: t.tenantId,
2606
- now: i
2607
- }), r.evicted++), await e.transaction((e) => we(e, t.id, {
2608
- executionId: d.executionId,
2609
- runId: d.runId ?? null
2610
- })), r.admitted++;
2611
- } catch (r) {
2612
- let a = !1;
2613
- try {
2614
- if (s !== void 0 && e.isPermanentStartError?.(r) === !0) {
2615
- let o = s;
2616
- a = await e.transaction((e) => S(e, t.id, o, {
2617
- handler: n.onFailure ?? null,
2618
- errorMessage: String(r),
2619
- now: i
2620
- })) !== void 0;
2621
- }
2622
- if (!a) {
2623
- let n = await e.transaction((n) => Ve(n, t.id, String(r), i, e.deadLetterAfterAttempts ?? 50));
2624
- n.retry.stoppedAt !== null && e.log?.warn?.("workflow submission automatic retry stopped; engine acceptance unknown", {
2625
- submissionId: t.id,
2626
- workflow: t.workflowName,
2627
- attempts: n.retry.attempts
2628
- });
2629
- }
2630
- } catch (e) {
2631
- throw new Zn(t.id, AggregateError([r, e], "Submission and retry recording failed"));
2632
- }
2633
- throw new Zn(t.id, r, a);
2634
- }
2635
- }, lr = async (e, t) => {
2636
- if (e.listRunningRuns === void 0) return { cancelled: 0 };
2637
- let n = 0, r;
2638
- for (let i of e.controls.values()) {
2639
- if (i.timeouts?.finishMs === void 0) continue;
2640
- let a = await e.listRunningRuns(i.workflowName);
2641
- for (let o of a) {
2642
- if (!T(i, {
2643
- startedAt: o.startedAt,
2644
- terminal: !1
2645
- }, t)) {
2646
- let e = o.startedAt + i.timeouts.finishMs;
2647
- (r === void 0 || e < r) && (r = e);
2648
- continue;
2649
- }
2650
- let a = `timeouts.finish (${i.timeouts.finishMs}ms) elapsed; the run was cancelled after ${t - o.startedAt}ms`;
2651
- await e.cancelRun({
2652
- workflowName: o.workflowName,
2653
- runId: o.runId,
2654
- executionId: o.executionId,
2655
- reason: a,
2656
- detail: {
2657
- ...Le,
2658
- onFailure: i.onFailure ?? null
2659
- }
2660
- }) && (await x(e.store, o.executionId, t), n++);
2661
- }
2662
- }
2663
- return {
2664
- cancelled: n,
2665
- ...r === void 0 ? {} : { nextDeadlineAt: r }
2666
- };
2667
- }, ur = 3e5, dr, fr = (e) => {
2668
- dr = e !== void 0 && Number.isFinite(e) && e > 0 ? e : void 0;
2669
- }, pr = () => {
2670
- let e = process.env.VOLTRO_WORKFLOW_SUSPEND_HINT_MS;
2671
- if (e !== void 0) {
2672
- let t = Number(e);
2673
- if (Number.isFinite(t) && t > 0) return t;
2674
- }
2675
- return dr ?? 3e5;
2676
- }, mr = /* @__PURE__ */ new Set(), hr = () => {
2677
- mr.clear();
2678
- }, gr = (e) => {
2679
- let t = pr();
2680
- if (!(e.timeoutMs > t)) return !1;
2681
- let n = `${e.workflowName ?? ""}\u0000${e.signalName}`;
2682
- if (mr.has(n)) return !1;
2683
- mr.add(n);
2684
- let r = e.workflowName === void 0 ? "" : ` in workflow '${e.workflowName}'`;
2685
- return (e.warn ?? ((e) => console.warn(e)))(`awaitSignal('${e.signalName}')${r} declares a ${Math.round(e.timeoutMs / 1e3)}s timeout — a wait that long holds a worker fiber for its whole duration. For human-approval-length waits, awaitSignalSuspending (same call shape, from @voltro/workflow) SUSPENDS the run and frees the slot until the signal arrives. This is a hint, not a behaviour change; it is logged once per workflow. Threshold: workflows.suspendSignalHintMs in app.config.ts, or VOLTRO_WORKFLOW_SUSPEND_HINT_MS.`), !0;
2686
- }, _r = async (e, t) => {
2687
- if (e) try {
2688
- await e.recordEvent(t);
2689
- } catch {}
2690
- }, vr = (e, n) => {
2691
- let r = I.gen(function* () {
2692
- let r = n.pollIntervalMs ?? 200, i = n.maxPollIntervalMs ?? 5e3, a = n.timeoutMs ?? 864e5, s = yield* I.serviceOption(Y), c;
2693
- gr({
2694
- workflowName: s._tag === "Some" ? s.value.workflow.name : void 0,
2695
- signalName: n.name,
2696
- timeoutMs: a,
2697
- warn: (e) => {
2698
- c = e;
2699
- }
2700
- }), c !== void 0 && (yield* I.logWarning(c));
2701
- let l = yield* t, u = yield* I.serviceOption(o), d = u._tag === "Some" ? u.value : void 0;
2702
- if (l === void 0) return yield* I.die(/* @__PURE__ */ Error("awaitSignal: no active workflow run id in scope"));
2703
- let f = l;
2704
- yield* I.promise(() => _r(d, {
2705
- runId: f,
2706
- eventType: "signal-awaited",
2707
- payload: { signalName: n.name }
2708
- }));
2709
- let p = Date.now(), m = r;
2710
- for (;;) {
2711
- let t = Date.now() - p;
2712
- if (t > a) return yield* I.die(/* @__PURE__ */ Error(`awaitSignal('${n.name}') timed out after ${t}ms`));
2713
- let r = {
2714
- table: "_voltro_workflow_run_events",
2715
- order: [{
2716
- column: "occurredAt",
2717
- direction: "asc"
2718
- }],
2719
- predicate: z(B("runId", f), B("eventType", "signal-sent")),
2720
- projection: void 0,
2721
- skip: void 0,
2722
- take: 1e3
2723
- }, o = (yield* I.tryPromise({
2724
- try: () => e.store.query(r),
2725
- catch: (e) => e
2726
- })).find((e) => e.payload?.signalName === n.name);
2727
- if (o !== void 0) {
2728
- let e = h(o.payload)?.value, t = yield* R.decodeUnknown(n.schema)(e);
2729
- return yield* I.promise(() => _r(d, {
2730
- runId: f,
2731
- eventType: "signal-received",
2732
- payload: {
2733
- signalName: n.name,
2734
- value: e
2735
- }
2736
- })), t;
2737
- }
2738
- yield* I.sleep(`${m} millis`), m = Math.min(m * 2, i);
2739
- }
2740
- });
2741
- return f({
2742
- name: `await-signal:${n.name}`,
2743
- success: n.schema,
2744
- execute: r
2745
- });
2746
- }, yr = async (e, t) => {
2747
- if (e !== void 0) try {
2748
- await e.recordEvent(t);
2749
- } catch {}
2750
- }, br = (e, n) => {
2751
- let r = I.gen(function* () {
2752
- let r = n.pollIntervalMs ?? 200, i = n.maxPollIntervalMs ?? 5e3, a = n.timeoutMs ?? 864e5, s = n.take ?? 500, c = yield* t, l = yield* I.serviceOption(o), u = l._tag === "Some" ? l.value : void 0;
2753
- if (c === void 0) return yield* I.die(/* @__PURE__ */ Error("awaitEvent: no active workflow run id in scope"));
2754
- let d = c, f = yield* n.since === "run-start" ? xr(e, d) : I.succeed(/* @__PURE__ */ new Date());
2755
- yield* I.promise(() => yr(u, {
2756
- runId: d,
2757
- eventType: "event-awaited",
2758
- payload: {
2759
- event: n.event,
2760
- since: n.since ?? "wait-start",
2761
- cutoff: f.toISOString()
2762
- }
2763
- }));
2764
- let p = Date.now(), m = r, h = 0;
2765
- for (;;) {
2766
- let t = Date.now() - p;
2767
- if (t > a) return yield* I.die(/* @__PURE__ */ Error(`awaitEvent('${n.event}') timed out after ${t}ms having examined ${h} candidate event(s). ${h === 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."}`));
2768
- let r = {
2769
- table: "_voltro_workflow_events",
2770
- predicate: z(B("name", n.event), it("occurredAt", f)),
2771
- order: [{
2772
- column: "occurredAt",
2773
- direction: "asc"
2774
- }],
2775
- take: s,
2776
- skip: void 0,
2777
- projection: void 0
2778
- }, o = yield* I.tryPromise({
2779
- try: () => e.store.query(r),
2780
- catch: (e) => e
2781
- });
2782
- h = o.length;
2783
- for (let e of o) {
2784
- let t = yield* R.decodeUnknown(n.schema)(e.payload);
2785
- if (n.match(t)) return yield* I.promise(() => yr(u, {
2786
- runId: d,
2787
- eventType: "event-received",
2788
- payload: {
2789
- event: n.event,
2790
- eventId: e.id
2791
- }
2792
- })), t;
2793
- }
2794
- yield* I.sleep(`${m} millis`), m = Math.min(m * 2, i);
2795
- }
2796
- });
2797
- return f({
2798
- name: `awaitEvent:${n.event}`,
2799
- success: n.schema,
2800
- execute: r
2801
- });
2802
- }, xr = (e, t) => I.gen(function* () {
2803
- let n = (yield* I.tryPromise({
2804
- try: () => e.store.query({
2805
- table: "_voltro_workflow_runs",
2806
- predicate: B("id", t),
2807
- order: [],
2808
- take: 1,
2809
- skip: void 0,
2810
- projection: void 0
2811
- }),
2812
- catch: (e) => e
2813
- }))[0]?.startedAt;
2814
- if (n instanceof Date) return n;
2815
- if (typeof n == "string" || typeof n == "number") {
2816
- let e = new Date(n);
2817
- if (!Number.isNaN(e.getTime())) return e;
2818
- }
2819
- return /* @__PURE__ */ new Date(0);
2820
- }), Sr = class extends Je.Reference()("@voltro/workflow/SuspensionUnavailable", { defaultValue: () => void 0 }) {}, Cr = class extends Error {
2821
- constructor(e, t) {
2822
- super(`${e} cannot wait for a durable result here: ${t}`), this.name = "WorkflowCannotPark";
2823
- }
2824
- }, wr = (e) => new Promise((t) => setTimeout(t, e)), Tr = () => {
2825
- let e = globalThis.crypto;
2826
- return typeof e?.randomUUID == "function" ? e.randomUUID() : `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`;
2827
- }, Er = () => `wfu_${Tr()}`, Dr = async (e, t) => {
2828
- let n = t.id ?? t.executionId;
2829
- if (!n) throw Error("workflow message target requires target.id or target.executionId");
2830
- let r = await e.query({
2831
- table: "_voltro_workflow_runs",
2832
- order: [],
2833
- predicate: B("id", n),
2834
- projection: void 0,
2835
- skip: void 0,
2836
- take: 1
2837
- });
2838
- if (r[0]) return r[0];
2839
- let i = (await e.query({
2840
- table: "_voltro_workflow_runs",
2841
- order: [],
2842
- predicate: B("executionId", n),
2843
- projection: void 0,
2844
- skip: void 0,
2845
- take: 1
2846
- }))[0];
2847
- if (!i) throw Error(`workflow message target not found: ${n}`);
2848
- return i;
2849
- }, Or = class extends Error {
2850
- runId;
2851
- eventType;
2852
- eventId;
2853
- _tag = "WorkflowMessageNotRecorded";
2854
- constructor(e, t, n) {
2855
- super(`workflow ${t} for run ${e} was NOT recorded (event ${n}): the run will not see it — the store refused the row, see the recorder's warning`), this.runId = e, this.eventType = t, this.eventId = n, this.name = "WorkflowMessageNotRecorded";
2856
- }
2857
- }, kr = async (e) => {
2858
- let t = await Dr(e.store, e.target), n = await e.recorder.recordEvent({
2859
- runId: t.id,
2860
- eventType: "signal-sent",
2861
- payload: {
2862
- signalName: e.signalName,
2863
- value: e.payload
2864
- }
2865
- });
2866
- if (n.recorded === !1) throw new Or(t.id, "signal-sent", n.id);
2867
- return { eventId: n.id };
2868
- }, Ar = async (e) => {
2869
- let t = await Dr(e.store, e.target), n = Er(), r = await e.recorder.recordEvent({
2870
- runId: t.id,
2871
- eventType: "update-requested",
2872
- payload: {
2873
- updateId: n,
2874
- updateName: e.updateName,
2875
- value: e.payload
2876
- }
2877
- });
2878
- if (r.recorded === !1) throw new Or(t.id, "update-requested", r.id);
2879
- let i = Date.now(), a = e.options?.timeoutMs ?? 3e4, o = e.options?.pollIntervalMs ?? 100;
2880
- for (;;) {
2881
- let s = {
2882
- table: "_voltro_workflow_run_events",
2883
- order: [{
2884
- column: "occurredAt",
2885
- direction: "asc"
2886
- }],
2887
- predicate: B("runId", t.id),
2888
- projection: void 0,
2889
- skip: void 0,
2890
- take: 1e3
2891
- }, c = await e.store.query(s), l = c.find((e) => e.eventType === "update-completed" && e.payload?.updateId === n);
2892
- if (l) return {
2893
- eventId: r.id,
2894
- updateId: n,
2895
- completedEventId: l.id,
2896
- result: h(l.payload)?.result
2897
- };
2898
- let u = c.find((e) => e.eventType === "update-failed" && e.payload?.updateId === n);
2899
- if (u) {
2900
- let t = Error(h(u.payload)?.errorMessage ?? `workflow update '${e.updateName}' failed`);
2901
- throw Object.assign(t, {
2902
- updateId: n,
2903
- eventId: r.id,
2904
- errorTag: u.payload?.errorTag ?? null
2905
- }), t;
2906
- }
2907
- if (Date.now() - i >= a) throw Error(`Timed out waiting for workflow update '${e.updateName}' (${n})`);
2908
- await wr(o);
2909
- }
2910
- }, jr = 864e5, Mr = "voltro/suspending-signal", Nr = (e, t) => `${Mr}/${e}/${t}`, Pr = (e, t) => Ge.make(e, { success: _(t) ? u(R.Unknown, `signal '${e}' value`) : R.Unknown }), Fr = async (e, t) => {
2911
- if (e) try {
2912
- await e.recordEvent(t);
2913
- } catch {}
2914
- }, Ir = (e, n) => I.gen(function* () {
2915
- let e = yield* Sr;
2916
- if (e !== void 0) return yield* I.die(new Cr(`awaitSignalSuspending('${n.name}')`, e));
2917
- let r = n.timeoutMs ?? jr, i = yield* qe.WorkflowInstance, a = Pr(Nr(i.workflow.name, n.name), i.workflow.name), s = yield* t, c = yield* I.serviceOption(o), l = c._tag === "Some" ? c.value : void 0;
2918
- s !== void 0 && (yield* I.promise(() => Fr(l, {
2919
- runId: s,
2920
- eventType: "signal-awaited",
2921
- payload: { signalName: n.name }
2922
- })));
2923
- let u = Ge.await(a), d = Number.isFinite(r) ? yield* I.race(u, We.sleep({
2924
- name: `await-signal-timeout/${n.name}`,
2925
- inMemoryThreshold: "0 millis",
2926
- duration: `${r} millis`
2927
- }).pipe(I.andThen(I.die(/* @__PURE__ */ Error(`awaitSignalSuspending('${n.name}') timed out after ${r}ms`))))).pipe(I.catchAllCause((e) => i.suspended ? F.isInterruptedOnly(e) ? Ke.suspend(i) : I.failCause(F.filter(e, (e) => !F.isInterruptType(e))) : I.failCause(e))) : yield* u, f = yield* R.decodeUnknown(n.schema)(d);
2928
- return s !== void 0 && (yield* I.promise(() => Fr(l, {
2929
- runId: s,
2930
- eventType: "signal-received",
2931
- payload: {
2932
- signalName: n.name,
2933
- value: f
2934
- }
2935
- }))), f;
2936
- }), Lr = (e) => I.gen(function* () {
2937
- let t = e.target.executionId, n = e.target.workflowName;
2938
- if (t === void 0 || n === void 0) {
2939
- let r = e.store;
2940
- if (r === void 0) return yield* I.die(/* @__PURE__ */ Error("completeSuspendingSignal: provide a store, or target.executionId AND target.workflowName"));
2941
- let i = yield* I.tryPromise({
2942
- try: () => Dr(r, e.target),
2943
- catch: (e) => e
2944
- });
2945
- t ??= i.executionId, n ??= i.tag;
2946
- }
2947
- if (t === void 0 || n === void 0) return { completed: !1 };
2948
- let r = Nr(n, e.signalName), i = Pr(r, n), a = new Ge.TokenParsed({
2949
- workflowName: n,
2950
- executionId: t,
2951
- deferredName: r
2952
- }).asToken;
2953
- return yield* Ge.done(i, {
2954
- token: a,
2955
- exit: Ye.succeed(e.payload)
2956
- }), { completed: !0 };
2957
- }), Z = "_voltro_budget_holds", Rr = "budget-hold", zr = (e) => `${Rr}:${e}`, Br = (e) => `${e.executionId}/${e.stepName}/${e.budget}#${e.generation}`, Vr = async (e, t) => (await e.query({
2958
- table: Z,
2959
- predicate: z(B("executionId", t.executionId), B("stepName", t.stepName), B("budget", t.budget)),
2960
- order: []
2961
- })).length, Hr = K(Z, {
2962
- id: H({ prefix: "bhd" }),
2963
- holdKey: q().maxLength(191).unique(),
2964
- budget: q(),
2965
- tenantId: q().nullable(),
2966
- executionId: q(),
2967
- workflowName: q(),
2968
- signalName: q(),
2969
- stepName: q(),
2970
- spentMicroUsd: q().nullable(),
2971
- limitMicroUsd: q().nullable(),
2972
- heldAt: J().default("now"),
2973
- releasedAt: J().nullable(),
2974
- outcome: q().nullable()
2975
- }).index(["budget", "releasedAt"]), Ur = () => {
2976
- ft({
2977
- source: "framework",
2978
- table: Z,
2979
- timeColumn: "releasedAt",
2980
- ttlMs: pt(process.env.VOLTRO_BUDGET_HOLDS_TTL_HOURS, 720)
2981
- });
2982
- }, Wr = class extends Error {
2983
- budget;
2984
- holdKey;
2985
- constructor(e, t, n) {
2986
- super(`budget '${e}': the run was suspended waiting for headroom and gave up after ${n}ms (hold ${t}). Nothing was spent. Raise the budget, reset its window, or lift the hold, then re-drive the run.`), this.name = "BudgetHoldExpired", this.budget = e, this.holdKey = t;
2987
- }
2988
- }, Gr = 6048e5, Kr = (e) => I.gen(function* () {
2989
- Ur();
2990
- let t = e.timeoutMs ?? 6048e5, n = e.recheckEveryMs ?? 9e5, r = {
2991
- executionId: e.executionId,
2992
- stepName: e.stepName,
2993
- budget: e.budget
2994
- };
2995
- for (let i = 0;; i++) {
2996
- let a = yield* I.promise(() => Jr(e.store, r)), o = a.length === 0 ? Date.now() : qr(a[0]?.heldAt), s = Number.isFinite(t) ? t - (Date.now() - o) : Infinity, c = Br({
2997
- ...r,
2998
- generation: i
2999
- });
3000
- if (s <= 0) return yield* I.promise(() => Yr(e.store, r, "expired")), yield* I.fail(new Wr(e.budget, c, t));
3001
- let l = zr(c);
3002
- yield* I.promise(() => e.store.insertIgnore(Z, {
3003
- id: rt({
3004
- kind: "typeid",
3005
- prefix: "bhd"
3006
- }, Z),
3007
- holdKey: c,
3008
- budget: e.budget,
3009
- tenantId: e.tenantId,
3010
- executionId: e.executionId,
3011
- workflowName: e.workflowName,
3012
- signalName: l,
3013
- stepName: e.stepName,
3014
- spentMicroUsd: e.spentMicroUsd === void 0 ? null : String(Math.round(e.spentMicroUsd)),
3015
- limitMicroUsd: e.limitMicroUsd === void 0 ? null : String(Math.round(e.limitMicroUsd)),
3016
- heldAt: /* @__PURE__ */ new Date(),
3017
- releasedAt: null,
3018
- outcome: null
3019
- }, { conflictColumns: ["holdKey"] }));
3020
- let u = Math.min(n, s);
3021
- if (yield* Ir({ store: e.store }, {
3022
- name: l,
3023
- schema: R.Unknown,
3024
- timeoutMs: u
3025
- }).pipe(I.catchAllCause((e) => F.isInterruptedOnly(e) ? I.failCause(e) : I.void)), yield* I.promise(() => e.store.updateMany(Z, {
3026
- releasedAt: /* @__PURE__ */ new Date(),
3027
- outcome: "recheck"
3028
- }, { where: z(B("holdKey", c), W("releasedAt")) })), yield* e.hasHeadroom) return;
3029
- }
3030
- }), qr = (e) => e instanceof Date ? e.getTime() : typeof e == "string" ? Date.parse(e) : Date.now(), Jr = async (e, t) => [...await e.query({
3031
- table: Z,
3032
- predicate: z(B("executionId", t.executionId), B("stepName", t.stepName), B("budget", t.budget)),
3033
- order: []
3034
- })].sort((e, t) => String(e.id).localeCompare(String(t.id))), Yr = async (e, t, n) => {
3035
- await e.updateMany(Z, {
3036
- releasedAt: /* @__PURE__ */ new Date(),
3037
- outcome: n
3038
- }, { where: z(B("executionId", t.executionId), B("stepName", t.stepName), B("budget", t.budget), W("releasedAt")) });
3039
- }, Xr = (e) => I.gen(function* () {
3040
- let t = e.tenantId === void 0 ? z(B("budget", e.budget), W("releasedAt")) : z(B("budget", e.budget), B("tenantId", e.tenantId), W("releasedAt")), n = yield* I.promise(() => e.store.query({
3041
- table: Z,
3042
- predicate: t,
3043
- order: []
3044
- })), r = 0;
3045
- for (let t of n) (yield* I.promise(() => e.store.updateMany("_voltro_budget_holds", {
3046
- releasedAt: /* @__PURE__ */ new Date(),
3047
- outcome: e.outcome ?? "released"
3048
- }, { where: z(B("id", String(t.id)), W("releasedAt")) }))) === 1 && (yield* Lr({
3049
- target: {
3050
- executionId: String(t.executionId),
3051
- workflowName: String(t.workflowName)
3052
- },
3053
- signalName: String(t.signalName),
3054
- payload: {
3055
- released: !0,
3056
- budget: e.budget
3057
- }
3058
- }).pipe(I.catchAll(() => I.succeed({ completed: !1 }))), r += 1);
3059
- return { released: r };
3060
- }), Zr = async (e, t) => {
3061
- let n = t?.budget === void 0 ? W("releasedAt") : z(B("budget", t.budget), W("releasedAt"));
3062
- return (await e.query({
3063
- table: Z,
3064
- predicate: n,
3065
- order: []
3066
- })).map((e) => ({
3067
- id: String(e.id),
3068
- holdKey: String(e.holdKey),
3069
- budget: String(e.budget),
3070
- tenantId: e.tenantId ?? null,
3071
- executionId: String(e.executionId),
3072
- workflowName: String(e.workflowName),
3073
- stepName: String(e.stepName),
3074
- heldAt: e.heldAt instanceof Date ? e.heldAt.toISOString() : String(e.heldAt ?? "")
3075
- }));
3076
- }, Qr = async (e) => {
3077
- let t = await Zr(e), n = /* @__PURE__ */ new Map();
3078
- for (let e of t) {
3079
- let t = `${e.budget}\u0000${e.tenantId ?? ""}`;
3080
- n.has(t) || n.set(t, {
3081
- budget: e.budget,
3082
- tenantId: e.tenantId
3083
- });
3084
- }
3085
- return [...n.values()];
3086
- }, $r = async (e, t) => {
3087
- if (e) try {
3088
- await e.recordEvent(t);
3089
- } catch {}
3090
- }, ei = (e) => {
3091
- let t = F.failureOption(e), n = Array.from(F.defects(e)), r = t._tag === "Some" ? t.value : n[0] ?? F.squash(e);
3092
- return {
3093
- errorTag: r && typeof r == "object" && "_tag" in r ? String(r._tag) : null,
3094
- errorMessage: r?.message ?? String(r)
3095
- };
3096
- }, ti = (e, n) => {
3097
- let r = I.gen(function* () {
3098
- let r = n.pollIntervalMs ?? 200, i = n.maxPollIntervalMs ?? 5e3, a = n.timeoutMs ?? 3e4, s = yield* t, c = yield* I.serviceOption(o), l = c._tag === "Some" ? c.value : void 0;
3099
- if (s === void 0) return yield* I.die(/* @__PURE__ */ Error("awaitUpdate: no active workflow run id in scope"));
3100
- let u = s, d = Date.now(), f = r;
3101
- for (;;) {
3102
- let t = Date.now() - d;
3103
- if (t > a) return yield* I.die(/* @__PURE__ */ Error(`awaitUpdate('${n.name}') timed out after ${t}ms`));
3104
- let r = {
3105
- table: "_voltro_workflow_run_events",
3106
- order: [{
3107
- column: "occurredAt",
3108
- direction: "asc"
3109
- }],
3110
- predicate: B("runId", u),
3111
- projection: void 0,
3112
- skip: void 0,
3113
- take: 1e3
3114
- }, o = yield* I.tryPromise({
3115
- try: () => e.store.query(r),
3116
- catch: (e) => e
3117
- }), s = new Set(o.filter((e) => e.eventType === "update-completed" || e.eventType === "update-failed").map((e) => e.payload?.updateId).filter((e) => typeof e == "string" && e.length > 0)), c = o.find((e) => e.eventType === "update-requested" && e.payload?.updateName === n.name && typeof e.payload.updateId == "string" && !s.has(e.payload.updateId));
3118
- if (c !== void 0) {
3119
- let e = c.payload.updateId;
3120
- yield* I.promise(() => $r(l, {
3121
- runId: u,
3122
- eventType: "update-received",
3123
- payload: {
3124
- updateId: e,
3125
- updateName: n.name
3126
- }
3127
- }));
3128
- let t = yield* R.decodeUnknown(n.schema)(h(c.payload)?.value).pipe(I.tapErrorCause((t) => I.promise(() => $r(l, {
3129
- runId: u,
3130
- eventType: "update-failed",
3131
- payload: {
3132
- updateId: e,
3133
- updateName: n.name,
3134
- ...ei(t)
3135
- }
3136
- })))), r = yield* (n.handle ? n.handle(t) : I.succeed(t)).pipe(I.flatMap((e) => n.success ? R.decodeUnknown(n.success)(e) : I.succeed(e))).pipe(I.tapErrorCause((t) => I.promise(() => $r(l, {
3137
- runId: u,
3138
- eventType: "update-failed",
3139
- payload: {
3140
- updateId: e,
3141
- updateName: n.name,
3142
- ...ei(t)
3143
- }
3144
- }))));
3145
- return yield* I.promise(() => $r(l, {
3146
- runId: u,
3147
- eventType: "update-completed",
3148
- payload: {
3149
- updateId: e,
3150
- updateName: n.name,
3151
- result: r
3152
- }
3153
- })), r;
3154
- }
3155
- yield* I.sleep(`${f} millis`), f = Math.min(f * 2, i);
3156
- }
3157
- });
3158
- return f({
3159
- name: `await-update:${n.name}`,
3160
- success: n.success ?? n.schema,
3161
- execute: r
3162
- });
3163
- }, ni = (e) => {
3164
- if (e == null) return null;
3165
- if (e instanceof Date) return e;
3166
- if (typeof e == "string" || typeof e == "number") {
3167
- let t = new Date(e);
3168
- return Number.isNaN(t.getTime()) ? null : t;
3169
- }
3170
- return null;
3171
- }, ri = (e) => typeof e == "number" ? e : e == null ? null : Number(e), Q = (e) => e == null ? null : String(e), ii = (e) => {
3172
- let t = /* @__PURE__ */ new Map();
3173
- for (let n of e) {
3174
- let e = String(n.stepName), r = t.get(e);
3175
- r === void 0 ? t.set(e, [n]) : r.push(n);
3176
- }
3177
- let n = [];
3178
- for (let [e, r] of t) {
3179
- r.sort((e, t) => (ri(e.attempt) ?? 0) - (ri(t.attempt) ?? 0));
3180
- let t = r[r.length - 1], i = Q(t.errorTag), a = Q(t.errorMessage), o = i !== null || a !== null ? {
3181
- tag: i,
3182
- message: a ?? ""
3183
- } : null;
3184
- n.push({
3185
- name: e,
3186
- attempt: ri(t.attempt) ?? r.length,
3187
- attempts: r.length,
3188
- status: t.status ?? "running",
3189
- input: t.input ?? null,
3190
- output: t.output ?? null,
3191
- error: o,
3192
- durationMs: ri(t.durationMs)
3193
- });
3194
- }
3195
- return n.sort((t, n) => {
3196
- let r = e.find((e) => String(e.stepName) === t.name), i = e.find((e) => String(e.stepName) === n.name);
3197
- return (ni(r?.startedAt)?.getTime() ?? 0) - (ni(i?.startedAt)?.getTime() ?? 0);
3198
- }), n;
3199
- }, ai = (e) => {
3200
- if (e == null) return null;
3201
- if (typeof e == "string") try {
3202
- return JSON.parse(e);
3203
- } catch {
3204
- return null;
3205
- }
3206
- return typeof e == "object" ? e : null;
3207
- }, oi = async (e, t) => {
3208
- let n = lt(_t), r = (await t.query(n.where(ct(B("id", e), B("executionId", e))).limit(1).descriptor))[0];
3209
- if (r === void 0) return null;
3210
- let i = String(r.id), a = lt(vt), o = await t.query(a.where(B("runId", i)).descriptor);
3211
- return {
3212
- id: i,
3213
- executionId: Q(r.executionId) ?? "",
3214
- name: Q(r.tag) ?? "",
3215
- status: r.status ?? "running",
3216
- input: d(r.payload ?? null, "workflow run payload"),
3217
- output: m(r.output ?? null, "workflow run result"),
3218
- subject: ai(r.subject),
3219
- source: Q(r.source),
3220
- steps: ii(o),
3221
- startedAt: ni(r.startedAt) ?? /* @__PURE__ */ new Date(0),
3222
- finishedAt: ni(r.completedAt),
3223
- traceId: Q(r.traceId),
3224
- parentExecutionId: Q(r.parentExecutionId),
3225
- parentClosePolicy: Q(r.parentClosePolicy)
3226
- };
3227
- }, si = () => {
3228
- let e = [], t = [], n = 0, r = 0;
3229
- return {
3230
- layer: Qe.succeed(o, {
3231
- startStep: async ({ runId: t, stepName: r, attempt: i, stepInput: a, retryPolicy: o }) => {
3232
- let s = `wfstep_mem_${++n}`;
3233
- return e.push({
3234
- id: s,
3235
- runId: t,
3236
- stepName: r,
3237
- attempt: i,
3238
- status: "running",
3239
- input: a ?? null,
3240
- retryPolicy: o ?? null,
3241
- output: null,
3242
- errorTag: null,
3243
- errorMessage: null,
3244
- errorCause: null,
3245
- startedAt: /* @__PURE__ */ new Date(),
3246
- completedAt: null,
3247
- durationMs: null
3248
- }), s;
3249
- },
3250
- endStepSuccess: async ({ stepRecordId: t, output: n, durationMs: r }) => {
3251
- let i = e.find((e) => e.id === t);
3252
- i !== void 0 && (i.status = "succeeded", i.output = n, i.completedAt = /* @__PURE__ */ new Date(), i.durationMs = r);
3253
- },
3254
- endStepFailure: async ({ stepRecordId: t, errorTag: n, errorMessage: r, errorCause: i, durationMs: a }) => {
3255
- let o = e.find((e) => e.id === t);
3256
- o !== void 0 && (o.status = "failed", o.errorTag = n, o.errorMessage = r, o.errorCause = i ?? null, o.completedAt = /* @__PURE__ */ new Date(), o.durationMs = a);
3257
- },
3258
- recordEvent: async ({ runId: e, eventType: n, payload: i, stepName: a, attempt: o }) => {
3259
- let s = `wfev_mem_${++r}`;
3260
- return t.push({
3261
- id: s,
3262
- runId: e,
3263
- eventType: n,
3264
- payload: i ?? null,
3265
- stepName: a ?? null,
3266
- attempt: o ?? null,
3267
- occurredAt: /* @__PURE__ */ new Date()
3268
- }), {
3269
- id: s,
3270
- recorded: !0
3271
- };
3272
- }
3273
- }),
3274
- readSteps: () => e,
3275
- readEvents: () => t
3276
- };
3277
- }, ci = (e, t, n) => I.gen(function* () {
3278
- let r = yield* Y;
3279
- for (;;) {
3280
- if (yield* I.tryPromise(() => ge(t, e)).pipe(I.catchAll(() => I.sync(() => (n(), !1))))) return r.interrupted = !0, yield* I.interrupt;
3281
- yield* I.sleep(1e3);
3282
- }
3283
- }), li = 8192, ui = 3, di = 2e3, fi = () => {
3284
- let e = (e) => {
3285
- if (e === void 0) return;
3286
- let t = Number(e);
3287
- return Number.isFinite(t) && t > 0 ? Math.floor(t) : void 0;
3288
- }, t = e(process.env.VOLTRO_WORKFLOW_MAX_RECLAIMS), n = e(process.env.VOLTRO_WORKFLOW_REPLAY_SHAPE_LIMIT);
3289
- return {
3290
- ...t === void 0 ? {} : { maxRunReclaims: t },
3291
- ...n === void 0 ? {} : { replayShapeLimit: n }
3292
- };
3293
- }, pi = (e) => {
3294
- let t = typeof e == "string" ? (() => {
3295
- try {
3296
- return JSON.parse(e);
3297
- } catch {
3298
- return;
3299
- }
3300
- })() : e;
3301
- if (Array.isArray(t)) return t.filter((e) => typeof e == "string");
3302
- }, mi = () => {
3303
- let e = globalThis.crypto;
3304
- return typeof e?.randomUUID == "function" ? e.randomUUID() : `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`;
3305
- }, hi = (e) => `${e}_${mi()}`, gi = (e, t = li) => {
3306
- if (e == null) return e;
3307
- try {
3308
- let n = JSON.stringify(e);
3309
- return n.length <= t ? e : {
3310
- __truncated: !0,
3311
- bytes: n.length,
3312
- sample: n.slice(0, t)
3313
- };
3314
- } catch {
3315
- return { __unserialisable: String(e) };
3316
- }
3317
- }, _i = async (e, t, n) => {
3318
- if (n === null || !g() || !("value" in n || "result" in n || "errorMessage" in n) || e.query === void 0) return n;
3319
- let [r] = await e.query({
3320
- table: "_voltro_workflow_runs",
3321
- predicate: B("id", t),
3322
- order: [],
3323
- take: 1,
3324
- skip: void 0,
3325
- projection: void 0
3326
- });
3327
- return typeof r?.tag == "string" ? b(r.tag, n) : n;
3328
- }, $ = (e) => {
3329
- let t = {};
3330
- for (let [n, r] of Object.entries(e)) t[n] = r instanceof Date ? r.toISOString() : r;
3331
- return ee(t);
3332
- }, vi = (e) => {
3333
- let t = e.truncateBytes ?? li, n = e.makeId ?? hi, r = (t, n) => e.log?.warn(t, n), i = (e, t) => t === !0 ? l(e, "workflow step value", v) : e, a = e.emit, o = e.recording === "coarse";
3334
- return {
3335
- startStep: async ({ runId: s, stepName: c, attempt: l, stepInput: u, retryPolicy: d, sealed: f }) => {
3336
- if (!o) try {
3337
- let r = await e.store.insert("_voltro_workflow_run_steps", {
3338
- id: n("ws"),
3339
- runId: s,
3340
- stepName: c,
3341
- attempt: l,
3342
- status: "running",
3343
- input: u === void 0 ? null : i(gi(u, t), f),
3344
- retryPolicy: d ?? null,
3345
- output: null,
3346
- errorTag: null,
3347
- errorMessage: null,
3348
- startedAt: /* @__PURE__ */ new Date(),
3349
- completedAt: null,
3350
- durationMs: null
3351
- });
3352
- return a?.("workflowSteps", {
3353
- op: "insert",
3354
- row: $(r)
3355
- }), r.id;
3356
- } catch (e) {
3357
- r("failed to record step start (continuing)", {
3358
- runId: s,
3359
- stepName: c,
3360
- attempt: l,
3361
- reason: e?.message ?? String(e)
3362
- });
3363
- return;
3364
- }
3365
- },
3366
- endStepSuccess: async ({ stepRecordId: n, output: s, durationMs: c, sealed: l }) => {
3367
- if (!o) try {
3368
- let r = await e.store.update("_voltro_workflow_run_steps", n, {
3369
- status: "succeeded",
3370
- output: i(gi(s, t), l),
3371
- completedAt: /* @__PURE__ */ new Date(),
3372
- durationMs: c
3373
- });
3374
- r && a?.("workflowSteps", {
3375
- op: "update",
3376
- row: $(r)
3377
- });
3378
- } catch (e) {
3379
- r("failed to record step success", {
3380
- stepRecordId: n,
3381
- reason: e?.message ?? String(e)
3382
- });
3383
- }
3384
- },
3385
- endStepFailure: async ({ stepRecordId: n, errorTag: s, errorMessage: c, errorCause: l, durationMs: u, sealed: d }) => {
3386
- if (!o) try {
3387
- let r = await e.store.update("_voltro_workflow_run_steps", n, {
3388
- status: "failed",
3389
- errorTag: s,
3390
- errorMessage: c == null ? c : i(c, d),
3391
- errorCause: l === void 0 ? null : i(gi(l, t), d),
3392
- completedAt: /* @__PURE__ */ new Date(),
3393
- durationMs: u
3394
- });
3395
- r && a?.("workflowSteps", {
3396
- op: "update",
3397
- row: $(r)
3398
- });
3399
- } catch (e) {
3400
- r("failed to record step failure", {
3401
- stepRecordId: n,
3402
- reason: e?.message ?? String(e)
3403
- });
3404
- }
3405
- },
3406
- recordEvent: async ({ runId: t, eventType: i, payload: o, stepName: s, attempt: c }) => {
3407
- let l = n("wfev"), u = !0;
3408
- try {
3409
- let n = await e.store.insert("_voltro_workflow_run_events", {
3410
- id: l,
3411
- runId: t,
3412
- eventType: i,
3413
- payload: await _i(e.store, t, o ?? null),
3414
- occurredAt: /* @__PURE__ */ new Date(),
3415
- stepName: s ?? null,
3416
- attempt: c ?? null
3417
- });
3418
- a?.("workflowEvents", {
3419
- op: "insert",
3420
- row: $(n)
3421
- });
3422
- } catch (e) {
3423
- u = !1, r("failed to record workflow event (continuing)", {
3424
- runId: t,
3425
- eventType: i,
3426
- reason: e?.message ?? String(e)
3427
- });
3428
- }
3429
- if (e.wakeups !== void 0) {
3430
- let n = o?.scheduledWakeAt, r = typeof n == "string" ? new Date(n) : void 0, a = o?.tenantId, s = typeof a == "string" ? a : void 0;
3431
- 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(() => {});
3432
- }
3433
- return {
3434
- id: l,
3435
- recorded: u
3436
- };
3437
- }
3438
- };
3439
- }, yi = (e, t, n) => I.gen(function* () {
3440
- let r = e.store.query;
3441
- if (r === void 0) return;
3442
- let i = e.replayShapeLimit ?? 2e3, a = yield* I.promise(() => r.call(e.store, {
3443
- table: "_voltro_workflow_run_steps",
3444
- order: [{
3445
- column: "startedAt",
3446
- direction: "asc"
3447
- }],
3448
- predicate: B("runId", t),
3449
- projection: ["stepName"],
3450
- skip: void 0,
3451
- take: i + 1
3452
- }).catch((e) => (n("failed to read the replay shape (nondeterminism tripwire disabled for this attempt)", {
3453
- runId: t,
3454
- reason: e?.message ?? String(e)
3455
- }), [])));
3456
- if (a.length === 0) return;
3457
- if (a.length > i) {
3458
- n("replay shape exceeds the step limit — nondeterminism tripwire disabled for this run", {
3459
- runId: t,
3460
- limit: i
3461
- });
3462
- return;
3463
- }
3464
- let o = a.flatMap((e) => {
3465
- let t = e.stepName;
3466
- return typeof t == "string" ? [{ stepName: t }] : [];
3467
- });
3468
- return o.length === 0 ? void 0 : s(o);
3469
- }), bi = (s, l) => {
3470
- let u = s.truncateBytes ?? li, d = s.makeId ?? hi, f = s.recorder ?? vi(s), p = (e, t) => s.log?.warn(e, t), m = s.emit, h = (e) => I.gen(function* () {
3471
- yield* I.sync(() => m?.("workflowEvents", {
3472
- op: "insert",
3473
- row: $(e)
3474
- }));
3475
- let t = s.wakeups, n = e.runId;
3476
- if (t !== void 0 && typeof n == "string") {
3477
- let e = s.subject?.tenantId;
3478
- yield* I.promise(() => t.cancel(n, typeof e == "string" ? e : void 0).catch(() => {
3479
- p("failed to clear terminal workflow wakeup", { runId: n });
3480
- }));
3481
- }
3482
- }), g = (e, t, n) => I.promise(async () => {
3483
- if (s.onParentClose) try {
3484
- await s.onParentClose({
3485
- workflowName: s.name,
3486
- executionId: e,
3487
- ...n === void 0 ? {} : { runId: n },
3488
- status: t
3489
- });
3490
- } catch (n) {
3491
- p("failed to apply workflow parent-close policy", {
3492
- tag: s.name,
3493
- executionId: e,
3494
- status: t,
3495
- reason: n?.message ?? String(n)
3496
- });
3497
- }
3498
- }), v = (e, t, n, r) => I.promise(async () => {
3499
- if (s.onTerminal) try {
3500
- await s.onTerminal({
3501
- workflowName: s.name,
3502
- executionId: e,
3503
- ...n === void 0 ? {} : { runId: n },
3504
- status: t,
3505
- ...r === void 0 ? {} : r
3506
- });
3507
- } catch (n) {
3508
- p("workflow terminal observer failed", {
3509
- tag: s.name,
3510
- executionId: e,
3511
- status: t,
3512
- reason: n?.message ?? String(n)
3513
- });
3514
- }
3515
- });
3516
- return (ee, b) => I.gen(function* () {
3517
- let x = Date.now(), te = yield* Ze.get(r), ne = yield* Ze.get(i), re = s.parentExecutionId ?? te ?? null, ie = s.parentGeneration ?? (s.parentExecutionId == null ? ne : void 0) ?? null, ae = s.parentClosePolicy ?? null, S, C = (e, t) => t.pipe(I.catchAllCause((t) => F.isInterrupted(t) ? I.failCause(t) : I.sync(() => {
3518
- let n = F.squash(t);
3519
- p(e, {
3520
- tag: s.name,
3521
- executionId: b,
3522
- reason: n?.message ?? String(n)
3523
- });
3524
- }))), w = `wfrg_${mi()}`, oe = yield* I.serviceOption(Te), se = d("wr"), ce = yield* I.sync(() => s.encodePayload === void 0 ? ee : s.encodePayload(ee)), T = yield* I.promise(() => s.transaction((e) => Bt(e, {
3525
- workflowName: s.name,
3526
- executionId: b,
3527
- generation: w,
3528
- now: x,
3529
- delivery: oe._tag === "Some" ? oe.value : null,
3530
- initialRow: {
3531
- id: se,
3532
- payload: ce,
3533
- workflowVersion: s.workflowVersion ?? null,
3534
- workflowPatches: s.workflowPatches ?? null,
3535
- output: null,
3536
- subject: s.subject ?? null,
3537
- source: s.source ?? null,
3538
- errorTag: null,
3539
- errorMessage: null,
3540
- cancelled: !1,
3541
- startedAt: new Date(x),
3542
- completedAt: null,
3543
- durationMs: null,
3544
- traceId: s.traceId ?? null,
3545
- parentExecutionId: re,
3546
- parentGeneration: ie,
3547
- parentClosePolicy: ae
3548
- }
3549
- })));
3550
- if (typeof T.row.id != "string") return yield* I.die(/* @__PURE__ */ Error("Recorded workflow entry has no run identity"));
3551
- if (S = T.row.id, T.restartEvent !== void 0) {
3552
- let e = T.restartEvent;
3553
- yield* C("failed to observe recorded workflow restart", I.sync(() => {
3554
- m?.("workflowEvents", {
3555
- op: "insert",
3556
- row: $(e)
3557
- });
3558
- }));
3559
- }
3560
- if (T.kind === "cancelled" || T.kind === "already-cancelled") {
3561
- let e = yield* Y;
3562
- return e.interrupted = !0, T.kind === "cancelled" && (yield* C("failed to observe suspended workflow cancellation", I.gen(function* () {
3563
- if (m?.("workflowRuns", {
3564
- op: "update",
3565
- row: $(T.row)
3566
- }), T.terminalEvent === void 0) return yield* I.die(/* @__PURE__ */ Error("Cancelled entry has no terminal event"));
3567
- yield* h(T.terminalEvent), yield* g(b, "cancelled", S);
3568
- })), yield* v(b, "cancelled", S), yield* I.sync(() => s.recordRun?.({
3569
- name: s.name,
3570
- status: "cancelled",
3571
- durationMs: 0
3572
- }))), yield* I.interrupt;
3573
- }
3574
- let E = T.previous, le = E?.workflowVersion ?? null;
3575
- if (E?.id !== void 0 && le !== null && s.workflowCompatibleVersions !== void 0 && s.workflowCompatibleVersions !== null && !s.workflowCompatibleVersions.includes(le)) {
3576
- let e = `Workflow '${s.name}' run '${b}' was started on version ${le}, but current code is compatible with ${s.workflowCompatibleVersions.join(", ")}`, t = s.failureContext ?? {
3577
- handler: null,
3578
- callerContext: null,
3579
- tenantId: null
3580
- }, n = yield* I.promise(() => s.transaction((n) => Gt(n, {
3581
- owner: {
3582
- runId: S,
3583
- workflowName: s.name,
3584
- executionId: b,
3585
- generation: w
3586
- },
3587
- now: Date.now(),
3588
- durationMs: 0,
3589
- outcome: {
3590
- status: "failed",
3591
- errorTag: "WorkflowVersionIncompatible",
3592
- errorMessage: e,
3593
- ...t
3594
- }
3595
- })));
3596
- return n.kind === "committed" && (yield* C("failed to observe workflow version rejection", I.gen(function* () {
3597
- m?.("workflowRuns", {
3598
- op: "update",
3599
- row: $(n.row)
3600
- }), yield* h(n.terminalEvent), yield* g(b, "failed", S);
3601
- })), yield* v(b, "failed", S, {
3602
- payload: T.row.payload,
3603
- errorTag: "WorkflowVersionIncompatible",
3604
- errorMessage: e
3605
- }), yield* I.sync(() => s.recordRun?.({
3606
- name: s.name,
3607
- status: "failed",
3608
- durationMs: 0
3609
- })), p("workflow run failed", {
3610
- workflow: s.name,
3611
- executionId: b,
3612
- runId: S,
3613
- errorTag: "WorkflowVersionIncompatible",
3614
- cause: e
3615
- })), yield* I.fail(Error(e));
3616
- }
3617
- let ue = s.workflowPatches ?? [], D;
3618
- if (E?.id !== void 0) {
3619
- S = E.id, ue = pi(E.workflowPatches) ?? ue;
3620
- let e = T.row.reclaimCount;
3621
- if (typeof e != "number" || !Number.isSafeInteger(e) || e < 0) return yield* I.die(/* @__PURE__ */ Error("Recorded workflow entry has an invalid reclaim counter"));
3622
- let t = e > 0, n = s.maxRunReclaims ?? 3;
3623
- if (t && e >= n) {
3624
- let t = `Workflow '${s.name}' run '${b}' killed its runner ${e} times in a row; parked instead of reclaimed again (maxRunReclaims=${n}).`, r = yield* I.promise(() => s.transaction((e) => Ut(e, {
3625
- runId: S,
3626
- workflowName: s.name,
3627
- executionId: b,
3628
- generation: w
3629
- }, {
3630
- errorTag: "WorkflowCrashLooped",
3631
- errorMessage: t
3632
- })));
3633
- r.kind === "committed" && (yield* C("failed to observe workflow crash-loop park", I.gen(function* () {
3634
- m?.("workflowRuns", {
3635
- op: "update",
3636
- row: $(r.row)
3637
- }), yield* I.promise(() => f.recordEvent({
3638
- runId: S,
3639
- eventType: "run-crashlooped",
3640
- payload: {
3641
- reclaimCount: e,
3642
- maxRunReclaims: n,
3643
- executionId: b,
3644
- tag: s.name
3645
- }
3646
- }));
3647
- })), p("workflow run parked after repeated runner deaths", {
3648
- tag: s.name,
3649
- executionId: b,
3650
- runId: S,
3651
- reclaimCount: e,
3652
- maxRunReclaims: n
3653
- }));
3654
- let i = yield* Y;
3655
- return yield* Ke.suspend(i);
3656
- }
3657
- D = yield* yi(s, S, p), yield* C("failed to record workflow re-entry", I.gen(function* () {
3658
- m?.("workflowRuns", {
3659
- op: "update",
3660
- row: $(T.row)
3661
- }), t && (yield* I.promise(() => f.recordEvent({
3662
- runId: S,
3663
- eventType: "run-resumed",
3664
- payload: {
3665
- reason: "runner-reclaim",
3666
- reclaimCount: e,
3667
- maxRunReclaims: n
3668
- }
3669
- })));
3670
- }));
3671
- } else yield* C("failed to emit recorded workflow start", I.gen(function* () {
3672
- if (m?.("workflowRuns", {
3673
- op: "insert",
3674
- row: $(T.row)
3675
- }), S) {
3676
- let e = S;
3677
- yield* I.promise(() => f.recordEvent({
3678
- runId: e,
3679
- eventType: "run-started",
3680
- payload: {
3681
- tag: s.name,
3682
- executionId: b,
3683
- source: s.source ?? null,
3684
- workflowVersion: s.workflowVersion ?? null,
3685
- workflowPatches: s.workflowPatches ?? null,
3686
- parentExecutionId: re,
3687
- parentClosePolicy: ae
3688
- }
3689
- }));
3690
- }
3691
- }));
3692
- let de = s.subject?.tenantId, fe = I.suspend(() => l(ee, b, w)).pipe(I.locally(t, S), I.locally(r, b), I.locally(i, w), I.locally(n, typeof de == "string" ? de : void 0), I.locally(a, ue), I.locally(c, D), I.provideService(o, f)), O = s.pluginWorkflowStepLayer ? fe.pipe(I.provide(s.pluginWorkflowStepLayer)) : fe, k = yield* Ke.intoResult(I.raceWith(O, ci({
3693
- runId: S,
3694
- workflowName: s.name,
3695
- executionId: b,
3696
- generation: w
3697
- }, async (e) => s.store.query(e), () => p("workflow control read failed; retrying without claiming cancellation", {
3698
- executionId: b,
3699
- runId: S
3700
- })).pipe(I.interruptible), {
3701
- onSelfDone: (e, t) => Xe.interrupt(t).pipe(I.zipRight(e)),
3702
- onOtherDone: (e, t) => Xe.interrupt(t).pipe(I.zipRight(e))
3703
- }));
3704
- if (Ke.isResult(k) && k._tag === "Suspended") {
3705
- let e = k.cause, t = e !== void 0 && !F.isEmpty(e), n = t ? F.squash(e) : void 0, r = n && typeof n == "object" && "_tag" in n ? String(n._tag) : null, i = t ? n?.message ?? String(n) : null, a = yield* I.promise(() => s.transaction((e) => Ut(e, {
3706
- runId: S,
3707
- workflowName: s.name,
3708
- executionId: b,
3709
- generation: w
3710
- }, {
3711
- errorTag: r,
3712
- errorMessage: i
3713
- })));
3714
- a.kind === "committed" && t && (yield* I.sync(() => et({
3715
- error: n,
3716
- source: "workflow",
3717
- name: s.name,
3718
- contentSensitive: _(s.name),
3719
- ...s.traceId ? { traceId: s.traceId } : {},
3720
- fields: {
3721
- executionId: b,
3722
- suspendedOnFailure: !0,
3723
- ...r ? { errorTag: r } : {},
3724
- ...S ? { runId: S } : {}
3725
- }
3726
- }))), a.kind === "committed" && (yield* C("failed to observe workflow suspend", I.gen(function* () {
3727
- m?.("workflowRuns", {
3728
- op: "update",
3729
- row: $(a.row)
3730
- }), yield* I.promise(() => f.recordEvent({
3731
- runId: S,
3732
- eventType: "run-suspended",
3733
- payload: t ? {
3734
- reason: "suspend-on-failure",
3735
- errorTag: r,
3736
- errorMessage: i
3737
- } : { reason: "workflow-suspend" }
3738
- }));
3739
- })));
3740
- let o = yield* Y;
3741
- return yield* Ke.suspend(o);
3742
- }
3743
- let pe = k;
3744
- if (D !== void 0 && S !== void 0) {
3745
- let t = D.settle();
3746
- if (t.length > 0) {
3747
- let n = S;
3748
- p("workflow replay reached a different step shape than this run recorded", {
3749
- tag: s.name,
3750
- executionId: b,
3751
- runId: n,
3752
- findings: t.map((e) => `${e.kind}:${e.stepName}`)
3753
- }), yield* C("failed to record nondeterminism findings", I.promise(async () => {
3754
- for (let r of t) await f.recordEvent({
3755
- runId: n,
3756
- eventType: "nondeterminism-suspected",
3757
- payload: e(r)
3758
- }).catch(() => void 0);
3759
- }));
3760
- }
3761
- }
3762
- if (Ye.isFailure(pe.exit)) {
3763
- let e = pe.exit.cause;
3764
- if ((yield* Y).interrupted && F.isInterruptedOnly(e)) {
3765
- let t = Date.now(), n = yield* I.promise(() => s.transaction((e) => Gt(e, {
3766
- owner: {
3767
- runId: S,
3768
- workflowName: s.name,
3769
- executionId: b,
3770
- generation: w
3771
- },
3772
- now: t,
3773
- durationMs: t - x,
3774
- outcome: { status: "cancelled" }
3775
- })));
3776
- return n.kind === "committed" && (yield* C("failed to observe workflow cancellation", I.gen(function* () {
3777
- m?.("workflowRuns", {
3778
- op: "update",
3779
- row: $(n.row)
3780
- }), yield* h(n.terminalEvent), yield* g(b, "cancelled", S);
3781
- })), yield* v(b, "cancelled", S), yield* I.sync(() => s.recordRun?.({
3782
- name: s.name,
3783
- status: "cancelled",
3784
- durationMs: t - x
3785
- }))), yield* I.failCause(e);
3786
- }
3787
- let t = F.failureOption(e), n = t._tag === "Some" ? t.value : F.squash(e), r = n && typeof n == "object" && "_tag" in n ? String(n._tag) : null, i = n?.message ?? String(n), a = Date.now(), o = s.failureContext ?? {
3788
- handler: null,
3789
- callerContext: null,
3790
- tenantId: null
3791
- }, c = yield* I.promise(() => s.transaction((e) => Gt(e, {
3792
- owner: {
3793
- runId: S,
3794
- workflowName: s.name,
3795
- executionId: b,
3796
- generation: w
3797
- },
3798
- now: a,
3799
- durationMs: a - x,
3800
- outcome: {
3801
- status: "failed",
3802
- errorTag: r,
3803
- errorMessage: i,
3804
- ...o
3805
- }
3806
- })));
3807
- return c.kind === "committed" ? (p("workflow run failed", {
3808
- workflow: s.name,
3809
- executionId: b,
3810
- runId: S,
3811
- ...r ? { errorTag: r } : {},
3812
- cause: y(s.name, n)
3813
- }), yield* I.sync(() => et({
3814
- error: n,
3815
- source: "workflow",
3816
- name: s.name,
3817
- contentSensitive: _(s.name),
3818
- ...s.traceId ? { traceId: s.traceId } : {},
3819
- fields: {
3820
- executionId: b,
3821
- ...r ? { errorTag: r } : {},
3822
- ...S ? { runId: S } : {}
3823
- }
3824
- })), S && (yield* C("failed to record workflow failure", I.gen(function* () {
3825
- m?.("workflowRuns", {
3826
- op: "update",
3827
- row: $(c.row)
3828
- }), yield* h(c.terminalEvent), yield* g(b, "failed", S);
3829
- }))), yield* v(b, "failed", S, {
3830
- payload: ee,
3831
- errorTag: r,
3832
- errorMessage: i
3833
- }), yield* I.sync(() => s.recordRun?.({
3834
- name: s.name,
3835
- status: "failed",
3836
- durationMs: Date.now() - x
3837
- })), yield* I.failCause(e)) : yield* I.failCause(e);
3838
- }
3839
- let me = pe.exit.value, A = Date.now(), j = yield* I.promise(() => s.transaction((e) => Gt(e, {
3840
- owner: {
3841
- runId: S,
3842
- workflowName: s.name,
3843
- executionId: b,
3844
- generation: w
3845
- },
3846
- now: A,
3847
- durationMs: A - x,
3848
- outcome: {
3849
- status: "succeeded",
3850
- output: gi(me, u)
3851
- }
3852
- })));
3853
- return j.kind === "committed" ? (S && (yield* C("failed to record workflow success", I.gen(function* () {
3854
- m?.("workflowRuns", {
3855
- op: "update",
3856
- row: $(j.row)
3857
- }), yield* h(j.terminalEvent), yield* g(b, "succeeded", S);
3858
- }))), yield* v(b, "succeeded", S), yield* I.sync(() => s.recordRun?.({
3859
- name: s.name,
3860
- status: "succeeded",
3861
- durationMs: Date.now() - x,
3862
- completedAtSec: Date.now() / 1e3
3863
- })), me) : me;
3864
- });
3865
- };
3866
- //#endregion
3867
- export { kn as $, Sr as A, sr as B, Ir as C, Tt as Ct, Dr as D, _t as Dt, Er as E, vt as Et, gr as F, jn as G, Qn as H, hr as I, xn as J, zn as K, pr as L, br as M, vr as N, kr as O, gt as Ot, ur as P, Tn as Q, fr as R, Kr as S, Et as St, Nr as T, yt as Tt, An as U, $n as V, Mn as W, yn as X, Sn as Y, vn as Z, Br as _, Ct as _t, fi as a, pn as at, Zr as b, kt as bt, bi as c, on as ct, ti as d, Ht as dt, En as et, Z as f, Gt as ft, Vr as g, Ot as gt, Hr as h, xt as ht, pi as i, dn as it, Cr as j, Ar as k, si as l, sn as lt, Gr as m, Ft as mt, di as n, gn as nt, $ as o, cn as ot, Wr as p, Bt as pt, bn as q, vi as r, mn as rt, gi as s, ln as st, ui as t, _n as tt, oi as u, Kt as ut, zr as v, wt as vt, Lr as w, bt as wt, Xr as x, Dt as xt, Qr as y, St as yt, Xn as z };