@voltro/workflow 0.85.0 → 0.87.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 (103) hide show
  1. package/CHANGELOG.md +5987 -0
  2. package/THIRD-PARTY-NOTICES.md +1122 -31
  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 +111 -27
  16. package/dist/cluster.js +12 -2
  17. package/dist/clusterCron.js +19 -0
  18. package/dist/clusterDiagnostics.js +20 -0
  19. package/dist/clusterDiagnosticsSql.js +145 -0
  20. package/dist/clusterLayer.js +145 -0
  21. package/dist/clusterMigrationGate.js +61 -0
  22. package/dist/clusterRunnerLayer.js +31 -0
  23. package/dist/clusterShardGroups.js +33 -0
  24. package/dist/clusterTestSuite.d.ts +23 -0
  25. package/dist/clusterTestSuite.js +209 -179
  26. package/dist/controlMonitor.js +13 -0
  27. package/dist/controlRequest.js +367 -0
  28. package/dist/executionRefusal.js +162 -0
  29. package/dist/failureHandoff.js +183 -0
  30. package/dist/failureMessage.js +12 -0
  31. package/dist/failureRecovery.js +50 -0
  32. package/dist/failureReportStore.js +60 -0
  33. package/dist/flowControl.js +142 -0
  34. package/dist/forwardStartReceipts.js +41 -0
  35. package/dist/inMemoryLayer.js +7 -0
  36. package/dist/inMemoryRecorder.js +56 -0
  37. package/dist/index.d.ts +129 -30
  38. package/dist/index.js +50 -5
  39. package/dist/inspectWorkflow.js +101 -0
  40. package/dist/{journalEncryption-DTyhUzaS.js → journalEncryption.js} +30 -37
  41. package/dist/journalRoutingGuard.js +50 -0
  42. package/dist/journalRoutingLayout.js +47 -0
  43. package/dist/journalRoutingLock.js +39 -0
  44. package/dist/journalRoutingMaintenance.js +24 -0
  45. package/dist/journalRoutingMessageStorage.js +32 -0
  46. package/dist/journalRoutingNamespace.js +23 -0
  47. package/dist/journalRoutingRuntime.js +33 -0
  48. package/dist/journalRoutingSharding.js +28 -0
  49. package/dist/journalRoutingState.js +93 -0
  50. package/dist/journalRoutingTable.js +11 -0
  51. package/dist/journalRoutingTransaction.js +16 -0
  52. package/dist/messages.js +92 -0
  53. package/dist/nondeterminism.js +51 -0
  54. package/dist/parentClosure.js +141 -0
  55. package/dist/parentClosureRecovery.js +54 -0
  56. package/dist/pendingSubmission.js +85 -0
  57. package/dist/prepareSubmissionDispatch.js +17 -0
  58. package/dist/preparedExecution.js +14 -0
  59. package/dist/primitives.js +225 -2
  60. package/dist/queuedCancellationRequest.js +364 -0
  61. package/dist/queuedControl.js +21 -0
  62. package/dist/recorder.js +11 -0
  63. package/dist/residentExecutionEvidence.js +64 -0
  64. package/dist/retryPolicy.js +57 -0
  65. package/dist/runEventsTable.js +17 -0
  66. package/dist/runGeneration.js +345 -0
  67. package/dist/runRecording.js +615 -0
  68. package/dist/runStepsTable.js +28 -0
  69. package/dist/runnerStorageGuard.js +29 -0
  70. package/dist/runsTable.js +42 -0
  71. package/dist/scheduleDeclaration.js +44 -0
  72. package/dist/signalHint.js +23 -0
  73. package/dist/signals.js +70 -0
  74. package/dist/signalsSuspending.js +57 -0
  75. package/dist/sqliteWorkflowOwnership.js +26 -0
  76. package/dist/stalenessSweep.js +191 -0
  77. package/dist/startContextsTable.js +20 -0
  78. package/dist/startReceipt.js +143 -0
  79. package/dist/submissionRecovery.js +122 -0
  80. package/dist/submissionRejection.js +10 -0
  81. package/dist/submissionRetry.js +71 -0
  82. package/dist/suspensionUnavailable.js +9 -0
  83. package/dist/updates.js +87 -0
  84. package/dist/watermarkTable.js +9 -0
  85. package/dist/webCrypto.js +17 -0
  86. package/dist/workflowDelivery.js +24 -0
  87. package/dist/workflowExecutorRouting.js +33 -0
  88. package/dist/workflowJournal.js +124 -0
  89. package/dist/workflowJournalReset.js +111 -0
  90. package/dist/workflowReadSelections.js +12 -0
  91. package/dist/workflowRestartDispatch.js +35 -0
  92. package/dist/workflowRestartObservation.js +60 -0
  93. package/dist/workflowRestartPreparation.js +109 -0
  94. package/dist/workflowRestartReservation.js +427 -0
  95. package/dist/workflowResumeDispatch.js +30 -0
  96. package/dist/workflowRuntimeReadiness.js +12 -0
  97. package/dist/workflowShardRelocation.js +58 -0
  98. package/dist/workflowShardRelocationSql.js +72 -0
  99. package/package.json +4 -4
  100. package/dist/cluster-F_bhqVP7.js +0 -679
  101. package/dist/primitives-DX04WTWh.js +0 -507
  102. package/dist/src-C2NEyUM8.js +0 -3925
  103. package/dist/workflowReadSelections-CZAUjP7f.js +0 -2096
@@ -0,0 +1,364 @@
1
+ import { dispatchedExecutionSubmissions as e, readAdmissionSubmission as t } from "./admissionSubmission.js";
2
+ import { readProvenSubmissionRejection as n } from "./submissionRejection.js";
3
+ import { decodeWorkflowStartReceipt as r, readWorkflowStartReceipt as i } from "./startReceipt.js";
4
+ import { cancelPendingWorkflowStartInTransaction as a } from "./cancelPendingStart.js";
5
+ import { acceptWorkflowControlInTransaction as o, readWorkflowControlInTransaction as s } from "./controlRequest.js";
6
+ import { cancelSuspendedWorkflowRunInTransaction as c } from "./runGeneration.js";
7
+ import { Schema as l } from "effect";
8
+ import { WorkflowQueuedCancellationResultSchema as u } from "@voltro/protocol";
9
+ import { and as d, derivedRowId as f, eq as p, gt as m, id as h, json as g, table as _, text as v, timestamp as y } from "@voltro/database";
10
+ //#region src/queuedCancellationRequest.ts
11
+ var b = _("_voltro_workflow_queued_cancellations", {
12
+ id: h({ prefix: "wfqc" }),
13
+ receiptId: v(),
14
+ workflowName: v(),
15
+ tenantId: v().nullable(),
16
+ requestedAt: y(),
17
+ cause: g().nullable(),
18
+ target: g(),
19
+ controlBinding: g().nullable()
20
+ }).index(["receiptId"]).index(["workflowName", "id"]).nonReactive(), x = l.NullOr(l.Struct({
21
+ reason: l.NonEmptyString,
22
+ detail: l.optional(l.Record(l.String, l.Unknown))
23
+ })), S = l.Struct({
24
+ id: l.NonEmptyString,
25
+ receiptId: l.NonEmptyString,
26
+ workflowName: l.NonEmptyString,
27
+ tenantId: l.NullOr(l.String),
28
+ requestedAt: l.Date,
29
+ cause: x,
30
+ controlBinding: l.NullOr(l.Struct({
31
+ controlId: l.NonEmptyString,
32
+ runId: l.NonEmptyString,
33
+ executionId: l.NonEmptyString,
34
+ generation: l.NonEmptyString
35
+ })),
36
+ target: l.Union([l.Struct({
37
+ kind: l.Literal("submission"),
38
+ submissionId: l.NonEmptyString
39
+ }), l.Struct({
40
+ kind: l.Literal("terminal"),
41
+ receipt: l.Unknown
42
+ })])
43
+ }), C = (e) => {
44
+ let t = l.decodeUnknownSync(S)(e);
45
+ if (!Number.isFinite(t.requestedAt.getTime())) throw Error("Queued cancellation request has an invalid timestamp");
46
+ if (t.target.kind === "submission") return {
47
+ ...t,
48
+ target: t.target
49
+ };
50
+ let n = r(t.target.receipt);
51
+ if (t.controlBinding !== null) throw Error("A non-executed start cannot have a run control binding");
52
+ 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");
53
+ return {
54
+ ...t,
55
+ target: {
56
+ kind: "terminal",
57
+ receipt: n
58
+ }
59
+ };
60
+ }, w = async (e, t) => {
61
+ let [n] = await e.query({
62
+ table: b.tableName,
63
+ predicate: p("id", t),
64
+ lock: "update",
65
+ order: [],
66
+ take: 1,
67
+ skip: void 0,
68
+ projection: void 0
69
+ });
70
+ return n === void 0 ? void 0 : C(n);
71
+ }, T = async (e, t) => {
72
+ let n = t.controlBinding;
73
+ if (n === null) throw Error("Queued cancellation has no control binding");
74
+ let r = await s(e, n.controlId);
75
+ 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");
76
+ return r;
77
+ }, E = async (e, t, n) => {
78
+ if (t.controlBinding === null) return;
79
+ let r = await T(e, t);
80
+ if (r.result !== null) return;
81
+ let [i] = await e.query({
82
+ table: "_voltro_workflow_runs",
83
+ predicate: p("id", r.runId),
84
+ lock: "update",
85
+ order: [],
86
+ take: 1,
87
+ skip: void 0,
88
+ projection: void 0
89
+ });
90
+ i !== void 0 && await c(e, {
91
+ runId: r.runId,
92
+ workflowName: r.workflowName,
93
+ executionId: r.executionId,
94
+ generation: r.generation
95
+ }, n);
96
+ }, D = async (e, r) => {
97
+ let i = await w(e, r.requestId);
98
+ if (i === void 0) return {
99
+ kind: "unknown",
100
+ reason: "missing-request"
101
+ };
102
+ if (i.workflowName !== r.workflowName || i.tenantId !== r.tenantId) throw Error("Queued cancellation request belongs to another workflow or tenant");
103
+ if (i.target.kind === "terminal") {
104
+ let e = i.target.receipt.terminal;
105
+ if (e === null) throw Error("Queued cancellation has no terminal evidence");
106
+ return {
107
+ kind: e.kind === "cancelled" ? "confirmed" : "already-terminal",
108
+ request: i,
109
+ outcome: e
110
+ };
111
+ }
112
+ if (i.controlBinding !== null) {
113
+ let t = await T(e, i);
114
+ if (t.result !== null) return {
115
+ kind: t.result.kind,
116
+ request: i,
117
+ control: t
118
+ };
119
+ let [n] = await e.query({
120
+ table: "_voltro_workflow_runs",
121
+ predicate: p("id", t.runId),
122
+ lock: "update",
123
+ order: [],
124
+ take: 1,
125
+ skip: void 0,
126
+ projection: void 0
127
+ });
128
+ if (n === void 0) return {
129
+ kind: "unknown",
130
+ reason: "missing-run",
131
+ request: i,
132
+ control: t
133
+ };
134
+ if (n.tag !== t.workflowName || n.executionId !== t.executionId) throw Error("Queued cancellation control belongs to another resident execution");
135
+ return n.runnerGeneration !== t.generation || n.status !== "running" && n.status !== "suspended" ? {
136
+ kind: "unknown",
137
+ reason: "unconfirmed-generation",
138
+ request: i,
139
+ control: t
140
+ } : {
141
+ kind: "accepted",
142
+ request: i,
143
+ control: t,
144
+ run: n
145
+ };
146
+ }
147
+ let a = await t(e, i.target.submissionId);
148
+ if (a === void 0 || !a.receiptsBound || a.workflowName !== i.workflowName || a.tenantId !== i.tenantId) throw Error("Queued cancellation has no matching submission evidence");
149
+ return a.failureId === null ? a.retry.stoppedAt !== null || a.runId !== null ? {
150
+ kind: "unknown",
151
+ reason: "unbound-submission",
152
+ request: i
153
+ } : {
154
+ kind: "accepted",
155
+ request: i
156
+ } : {
157
+ kind: "already-terminal",
158
+ request: i,
159
+ outcome: {
160
+ kind: "rejected",
161
+ failureId: await n(e, a)
162
+ }
163
+ };
164
+ }, O = (e, t) => {
165
+ let n = "request" in t ? t.request : void 0;
166
+ 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");
167
+ let r = {
168
+ operation: "cancel",
169
+ workflowName: e.workflowName,
170
+ receiptId: e.receiptId,
171
+ requestId: n?.id ?? null,
172
+ kind: t.kind
173
+ }, i = l.decodeUnknownSync(u);
174
+ if (t.kind === "unknown") return i({
175
+ ...r,
176
+ observation: {
177
+ kind: "unavailable",
178
+ reason: t.reason
179
+ }
180
+ });
181
+ if ("outcome" in t && t.outcome !== void 0) return i({
182
+ ...r,
183
+ observation: {
184
+ kind: "admission",
185
+ outcome: t.outcome
186
+ }
187
+ });
188
+ if ("control" in t && t.control !== void 0) {
189
+ let e = t.control, n = e.result;
190
+ return i({
191
+ ...r,
192
+ observation: {
193
+ kind: "execution",
194
+ snapshot: {
195
+ id: e.runId,
196
+ workflowName: e.workflowName,
197
+ executionId: e.executionId,
198
+ status: n?.status ?? ("run" in t ? t.run?.status : void 0),
199
+ ...n !== null && n.status === "succeeded" ? { output: n.output } : {},
200
+ ...n !== null && n.status === "failed" && n.errorMessage !== null ? { error: {
201
+ tag: n.errorTag,
202
+ message: n.errorMessage
203
+ } } : {}
204
+ }
205
+ }
206
+ });
207
+ }
208
+ return i({
209
+ ...r,
210
+ observation: { kind: "pending" }
211
+ });
212
+ }, k = async (e, n) => {
213
+ let r = l.decodeUnknownSync(l.Struct({
214
+ id: l.NonEmptyString,
215
+ receiptId: l.NonEmptyString,
216
+ workflowName: l.NonEmptyString,
217
+ tenantId: l.NullOr(l.String),
218
+ requestedAt: l.Date,
219
+ cause: x
220
+ }))({
221
+ id: n.requestId,
222
+ receiptId: n.receiptId,
223
+ workflowName: n.workflowName,
224
+ tenantId: n.tenantId,
225
+ requestedAt: new Date(n.now),
226
+ cause: n.cause ?? null
227
+ });
228
+ if (!Number.isFinite(r.requestedAt.getTime())) throw Error("Queued cancellation request requires a valid timestamp");
229
+ let o = await w(e, r.id);
230
+ if (o !== void 0) {
231
+ if (o.receiptId !== r.receiptId || o.workflowName !== r.workflowName || o.tenantId !== r.tenantId) throw Error("Queued cancellation identity belongs to a different start or owner");
232
+ return await E(e, o, n.now), o;
233
+ }
234
+ let s = await a(e, n), c;
235
+ if (s.kind === "submitted") c = {
236
+ kind: "submission",
237
+ submissionId: s.submissionId
238
+ };
239
+ else {
240
+ let t = await i(e, n.receiptId);
241
+ if (t === void 0) throw Error("Cancelled start receipt disappeared during request acceptance");
242
+ c = {
243
+ kind: "terminal",
244
+ receipt: t
245
+ };
246
+ }
247
+ let u = C({
248
+ ...r,
249
+ target: c,
250
+ controlBinding: null
251
+ });
252
+ if (await e.insert(b.tableName, u), c.kind === "submission") {
253
+ let r = await t(e, c.submissionId);
254
+ if (r === void 0) throw Error("Queued cancellation submission disappeared during acceptance");
255
+ if (r.preparedExecutionId !== null && r.dispatchAttempts > 0) {
256
+ let [t] = await e.query({
257
+ table: "_voltro_workflow_runs",
258
+ predicate: p("executionId", r.preparedExecutionId),
259
+ lock: "update",
260
+ order: [],
261
+ take: 1,
262
+ skip: void 0,
263
+ projection: void 0
264
+ });
265
+ if (t !== void 0) {
266
+ let r = l.decodeUnknownSync(l.Struct({
267
+ id: l.NonEmptyString,
268
+ tag: l.NonEmptyString,
269
+ executionId: l.NonEmptyString,
270
+ runnerGeneration: l.NonEmptyString
271
+ }))(t), i = {
272
+ runId: r.id,
273
+ workflowName: r.tag,
274
+ executionId: r.executionId,
275
+ generation: r.runnerGeneration
276
+ }, a = await A(e, u.id, i);
277
+ return await E(e, a.request, n.now), a.request;
278
+ }
279
+ }
280
+ }
281
+ return u;
282
+ }, A = async (e, n, r) => {
283
+ let i = await w(e, n);
284
+ if (i === void 0) throw Error("Queued cancellation request is missing");
285
+ if (i.target.kind === "terminal") return {
286
+ kind: "terminal",
287
+ request: i
288
+ };
289
+ if (i.controlBinding !== null) return {
290
+ kind: "bound",
291
+ request: i,
292
+ control: await T(e, i)
293
+ };
294
+ let a = await t(e, i.target.submissionId);
295
+ if (a === void 0 || a.workflowName !== i.workflowName || a.tenantId !== i.tenantId || !a.receiptsBound || a.failureId !== null || a.dispatchAttempts === 0 || a.preparedExecutionId !== r.executionId || a.executionId !== null && a.executionId !== r.executionId || a.runId !== null && a.runId !== r.runId || r.workflowName !== i.workflowName) throw Error("Queued cancellation has no dispatched submission for this resident execution");
296
+ let [s] = await e.query({
297
+ table: "_voltro_workflow_runs",
298
+ predicate: p("id", r.runId),
299
+ lock: "update",
300
+ order: [],
301
+ take: 1,
302
+ skip: void 0,
303
+ projection: void 0
304
+ }), c = l.decodeUnknownOption(l.Struct({ tenantId: l.NullOr(l.String) }))(s?.subject);
305
+ if (s === void 0 || s.tag !== r.workflowName || s.executionId !== r.executionId || s.runnerGeneration !== r.generation || c._tag === "None" || c.value.tenantId !== i.tenantId || ![
306
+ "running",
307
+ "suspended",
308
+ "succeeded",
309
+ "failed",
310
+ "cancelled"
311
+ ].includes(String(s.status))) throw Error("Queued cancellation generation or tenant does not match the resident run");
312
+ let u = {
313
+ controlId: f("wfctl", JSON.stringify(["queued-cancel", i.id])),
314
+ runId: r.runId,
315
+ executionId: r.executionId,
316
+ generation: r.generation
317
+ }, d = await o(e, {
318
+ id: u.controlId,
319
+ ...r,
320
+ operation: "cancel",
321
+ requestedAt: i.requestedAt.getTime(),
322
+ cause: i.cause
323
+ });
324
+ if (await e.update(b.tableName, i.id, { controlBinding: u }) === null) throw Error("Queued cancellation request disappeared during run binding");
325
+ return {
326
+ kind: "bound",
327
+ request: {
328
+ ...i,
329
+ controlBinding: u
330
+ },
331
+ control: d
332
+ };
333
+ }, j = async (t, n) => {
334
+ let r = /* @__PURE__ */ new Set();
335
+ for await (let i of e(t, n.executionId, n.workflowName)) r.add(i.id);
336
+ if (r.size === 0) return !1;
337
+ let i, a = !1;
338
+ for (;;) {
339
+ let e = await t.query({
340
+ table: b.tableName,
341
+ predicate: d(p("workflowName", n.workflowName), ...i === void 0 ? [] : [m("id", i)]),
342
+ lock: "update",
343
+ order: [{
344
+ column: "id",
345
+ direction: "asc"
346
+ }],
347
+ take: 100,
348
+ skip: void 0,
349
+ projection: void 0
350
+ });
351
+ for (let o of e) {
352
+ let e = C(o);
353
+ if (i = e.id, e.target.kind !== "submission" || !r.has(e.target.submissionId)) continue;
354
+ let s = await A(t, e.id, n);
355
+ if (s.kind === "bound") {
356
+ if (s.control.runId !== n.runId || s.control.executionId !== n.executionId || s.control.workflowName !== n.workflowName) throw Error("Queued cancellation entry does not match its original resident execution");
357
+ s.control.result === null && (a = !0);
358
+ }
359
+ }
360
+ if (e.length < 100) return a;
361
+ }
362
+ };
363
+ //#endregion
364
+ export { k as acceptQueuedCancellationInTransaction, A as bindQueuedCancellationRunInTransaction, D as observeQueuedCancellationInTransaction, b as queuedCancellationRequestsTable, O as queuedCancellationResult, w as readQueuedCancellationRequestInTransaction, j as stageQueuedCancellationsAtRunEntry };
@@ -0,0 +1,21 @@
1
+ import { acceptQueuedCancellationInTransaction as e, observeQueuedCancellationInTransaction as t, queuedCancellationResult as n } from "./queuedCancellationRequest.js";
2
+ import { Schema as r } from "effect";
3
+ //#region src/queuedControl.ts
4
+ var i = r.Struct({
5
+ requestId: r.NonEmptyString,
6
+ receiptId: r.NonEmptyString,
7
+ workflowName: r.NonEmptyString,
8
+ tenantId: r.NullOr(r.String)
9
+ }), a = async (t, n) => {
10
+ let a = r.decodeUnknownSync(i)(n);
11
+ return await e(t, {
12
+ ...a,
13
+ now: n.now,
14
+ ...n.cause === void 0 ? {} : { cause: n.cause }
15
+ }), o(t, a);
16
+ }, o = async (e, a) => {
17
+ let o = r.decodeUnknownSync(i)(a);
18
+ return n(o, await t(e, o));
19
+ };
20
+ //#endregion
21
+ export { a as cancelQueuedWorkflowStartInTransaction, o as readQueuedWorkflowCancellationInTransaction };
@@ -0,0 +1,11 @@
1
+ import { Context as e, Effect as t } from "effect";
2
+ //#region src/recorder.ts
3
+ var n = class extends e.Service()("@voltro/WorkflowRunRecorder") {}, r = e.Reference("@voltro/workflow/CurrentWorkflowRunId", { defaultValue: () => void 0 }), i = e.Reference("@voltro/workflow/CurrentWorkflowExecutionId", { defaultValue: () => void 0 }), a = e.Reference("@voltro/workflow/CurrentWorkflowStep", { defaultValue: () => void 0 }), o = t.gen(function* () {
4
+ let e = yield* i, t = yield* a;
5
+ return e === void 0 || t === void 0 ? void 0 : {
6
+ executionId: e,
7
+ step: t
8
+ };
9
+ }), s = e.Reference("@voltro/workflow/CurrentWorkflowGeneration", { defaultValue: () => void 0 }), c = e.Reference("@voltro/workflow/CurrentWorkflowWakeTenant", { defaultValue: () => void 0 }), l = e.Reference("@voltro/workflow/CurrentWorkflowPatches", { defaultValue: () => [] }), u = () => r, d = () => i, f = class extends e.Service()("@voltro/WorkflowStepInterceptor") {};
10
+ //#endregion
11
+ export { i as CurrentWorkflowExecutionId, s as CurrentWorkflowGeneration, l as CurrentWorkflowPatches, r as CurrentWorkflowRunId, a as CurrentWorkflowStep, c as CurrentWorkflowWakeTenant, n as WorkflowRunRecorder, f as WorkflowStepInterceptorTag, o as currentWorkflowStep, d as getCurrentWorkflowExecutionId, u as getCurrentWorkflowRunId };
@@ -0,0 +1,64 @@
1
+ import { Schema as e } from "effect";
2
+ import { eq as t } from "@voltro/database";
3
+ //#region src/residentExecutionEvidence.ts
4
+ var n = e.Struct({
5
+ runId: e.NonEmptyString,
6
+ workflowName: e.NonEmptyString,
7
+ executionId: e.NonEmptyString,
8
+ generation: e.NonEmptyString,
9
+ parentStatus: e.Literals([
10
+ "succeeded",
11
+ "failed",
12
+ "cancelled"
13
+ ]),
14
+ closedAt: e.Date
15
+ }), r = async (r, i, a) => {
16
+ let [o] = await r.query({
17
+ table: "_voltro_workflow_runs",
18
+ predicate: t("executionId", a),
19
+ lock: "update",
20
+ order: [],
21
+ take: 1,
22
+ skip: void 0,
23
+ projection: void 0
24
+ });
25
+ if (o !== void 0) {
26
+ if (o.tag !== i) throw Error("Admission acknowledgement belongs to a different resident workflow");
27
+ if (typeof o.id != "string" || o.id.length === 0) throw Error("Resident execution has no run identity");
28
+ if (o.status === "running" || o.status === "suspended") return {
29
+ runId: o.id,
30
+ completedAt: null
31
+ };
32
+ if (o.status !== "succeeded" && o.status !== "failed" && o.status !== "cancelled") throw Error("Resident execution has an unrecognized status");
33
+ if (!(o.completedAt instanceof Date) || !Number.isFinite(o.completedAt.getTime())) throw Error("Terminal workflow has no valid completion timestamp for lease release");
34
+ return {
35
+ runId: o.id,
36
+ completedAt: o.completedAt
37
+ };
38
+ }
39
+ let [s] = await r.query({
40
+ table: "_voltro_workflow_parent_closures",
41
+ predicate: t("executionId", a),
42
+ lock: "update",
43
+ order: [{
44
+ column: "closedAt",
45
+ direction: "desc"
46
+ }, {
47
+ column: "id",
48
+ direction: "desc"
49
+ }],
50
+ take: 1,
51
+ skip: void 0,
52
+ projection: void 0
53
+ });
54
+ if (s === void 0) return;
55
+ let c = e.decodeUnknownSync(n)(s);
56
+ if (c.workflowName !== i || c.executionId !== a) throw Error("Admission acknowledgement belongs to a different resident workflow");
57
+ if (!Number.isFinite(c.closedAt.getTime())) throw Error("Workflow closure has no valid completion timestamp");
58
+ return {
59
+ runId: c.runId,
60
+ completedAt: c.closedAt
61
+ };
62
+ };
63
+ //#endregion
64
+ export { r as readResidentExecutionEvidence };
@@ -0,0 +1,57 @@
1
+ import { Cause as e, Duration as t, Effect as n, Exit as r, Option as i, Schedule as a } from "effect";
2
+ //#region src/retryPolicy.ts
3
+ var o = (e) => {
4
+ if (typeof e != "object" || !e) return;
5
+ let n = e.retryAfterMillis;
6
+ if (typeof n == "number" && Number.isFinite(n) && n >= 0) return t.millis(n);
7
+ let r = e.retryAfter;
8
+ if (typeof r == "number" && Number.isFinite(r) && r >= 0) return t.seconds(r);
9
+ }, s = (e) => t.fromInputUnsafe(e), c = (e) => typeof e == "object" && e && "_tag" in e ? String(e._tag) : void 0, l = (e) => e !== void 0 && (e.maxAttempts ?? 3) > 1, u = (e) => {
10
+ if (e.retryable) return e.retryable;
11
+ if (e.retryableErrors && e.retryableErrors.length > 0) {
12
+ let t = new Set(e.retryableErrors);
13
+ return (e) => {
14
+ let n = c(e);
15
+ return n !== void 0 && t.has(n);
16
+ };
17
+ }
18
+ return () => !0;
19
+ }, d = (e) => {
20
+ let r = e.baseDelay ?? "200 millis", i = e.strategy ?? "exponential", o = e.maxAttempts ?? 3, c = i === "linear" ? a.modifyDelay(a.spaced(s(e.step ?? r)), (i) => n.succeed(t.times(s(e.step ?? r), i.attempt))) : i === "fixed" ? a.spaced(s(r)) : a.exponential(s(r), e.factor ?? 2);
21
+ if (e.maxDelay !== void 0) {
22
+ let r = s(e.maxDelay);
23
+ c = a.modifyDelay(c, (e) => n.succeed(t.min(e.duration, r)));
24
+ }
25
+ (e.jitter ?? !0) === !0 && (c = a.jittered(c));
26
+ let l = a.max([c, a.recurs(Math.max(0, o - 1))]);
27
+ return e.maxElapsed !== void 0 && (l = a.upTo({ duration: s(e.maxElapsed) })(l)), l;
28
+ }, f = (e, n) => {
29
+ let r = t.toMillis(s(e.baseDelay ?? "200 millis")), i = e.strategy ?? "exponential", a = i === "fixed" ? r : i === "linear" ? r + t.toMillis(s(e.step ?? e.baseDelay ?? "200 millis")) * (n - 1) : r * (e.factor ?? 2) ** (n - 1);
30
+ return e.maxDelay !== void 0 && (a = Math.min(a, t.toMillis(s(e.maxDelay)))), (e.jitter ?? !0) === !0 && (a *= Math.random()), a;
31
+ }, p = (a, c, l, u) => n.gen(function* () {
32
+ let d = c.maxAttempts ?? 3, p = c.maxElapsed === void 0 ? Infinity : t.toMillis(s(c.maxElapsed)), m = yield* n.sync(() => Date.now()), h = 0;
33
+ for (;;) {
34
+ let s = yield* n.exit(a);
35
+ if (r.isSuccess(s)) return s.value;
36
+ let g = s.cause, _ = e.findErrorOption(g), v = i.isSome(_) ? _.value : e.squash(g);
37
+ h += 1;
38
+ let y = (yield* n.sync(() => Date.now())) - m;
39
+ if (h >= d || !l(v) || y >= p) return yield* n.failCause(g);
40
+ u?.(v);
41
+ let b = o(v), x = b === void 0 ? f(c, h) : t.toMillis(b);
42
+ yield* n.sleep(t.millis(x));
43
+ }
44
+ }), m = (e, t, r) => {
45
+ if (!l(t)) return e;
46
+ let i = u(t);
47
+ if (t.respectRetryAfter === !0) return p(e, t, i, r);
48
+ let a = d(t), o = r ? n.tapError(e, (e) => n.sync(() => {
49
+ i(e) && r(e);
50
+ })) : e;
51
+ return n.retry(o, {
52
+ schedule: a,
53
+ while: i
54
+ });
55
+ };
56
+ //#endregion
57
+ export { m as applyRetryPolicy, l as retryPolicyIsActive };
@@ -0,0 +1,17 @@
1
+ import { _voltroWorkflowRunsTable as e } from "./runsTable.js";
2
+ import { id as t, integer as n, json as r, reference as i, table as a, text as o, timestamp as s } from "@voltro/database";
3
+ //#region src/runEventsTable.ts
4
+ var c = a("_voltro_workflow_run_events", {
5
+ id: t({ prefix: "wfev" }),
6
+ runId: i(() => e, {
7
+ index: !1,
8
+ onDelete: "cascade"
9
+ }),
10
+ eventType: o(),
11
+ payload: r().nullable(),
12
+ occurredAt: s().default("now"),
13
+ stepName: o().nullable(),
14
+ attempt: n().nullable()
15
+ }).index(["runId", "occurredAt"]).index(["eventType"]);
16
+ //#endregion
17
+ export { c as _voltroWorkflowRunEventsTable };