@voltro/workflow 0.81.0 → 0.82.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,395 +0,0 @@
1
- import { Context as e, Effect as t, Schema as n } from "effect";
2
- import { and as r, derivedRowId as i, eq as a, gt as o, or as s } from "@voltro/database";
3
- //#region src/controlRequest.ts
4
- var c = "_voltro_workflow_control_requests", l = n.String.pipe(n.minLength(1)), u = n.Struct({
5
- kind: n.Literal("confirmed", "already-terminal"),
6
- status: n.Literal("succeeded", "failed", "cancelled"),
7
- completedAt: n.Number.pipe(n.finite()),
8
- output: n.Unknown,
9
- errorTag: n.NullOr(n.String),
10
- errorMessage: n.NullOr(n.String)
11
- }), d = n.Struct({
12
- kind: n.Literal("confirmed"),
13
- status: n.Literal("running"),
14
- enteredAt: n.Number.pipe(n.finite()),
15
- generation: l
16
- }), f = n.Union(u, d), p = n.Struct({
17
- reason: n.NonEmptyString,
18
- detail: n.optional(n.Record({
19
- key: n.String,
20
- value: n.Unknown
21
- }))
22
- }), m = n.Struct({ tenantId: n.NullOr(n.String) }), h = n.Struct({
23
- requestId: n.String.pipe(n.pattern(/^[1-9]\d*$/)),
24
- replyId: n.String.pipe(n.pattern(/^[1-9]\d*$/)),
25
- restartToken: n.NullOr(n.NonEmptyString)
26
- }), g = n.Struct({
27
- id: l,
28
- runId: l,
29
- workflowName: l,
30
- executionId: l,
31
- generation: l,
32
- operation: n.Literal("cancel", "terminate", "resume"),
33
- requestedAt: n.Number.pipe(n.finite()),
34
- owner: n.NullOr(m),
35
- cause: n.optional(n.NullOr(p)),
36
- dispatchAttempts: n.Number.pipe(n.int(), n.nonNegative()),
37
- resumeJournal: n.NullOr(h),
38
- result: n.NullOr(f)
39
- }), _ = n.Struct({
40
- ...g.fields,
41
- requestedAt: n.DateFromSelf
42
- }), v = (e) => {
43
- let t = n.decodeUnknownSync(_)(e);
44
- return n.decodeUnknownSync(g)({
45
- ...t,
46
- requestedAt: t.requestedAt.getTime()
47
- });
48
- }, y = async (e, t, n, r) => {
49
- if (await e.update("_voltro_workflow_control_requests", t.id, { result: n }) === null) throw Error("Workflow control request disappeared during settlement");
50
- await e.insert("_voltro_workflow_run_events", {
51
- id: i("wfev", JSON.stringify(["control-settled", t.id])),
52
- runId: t.runId,
53
- eventType: "control-settled",
54
- occurredAt: new Date(r),
55
- stepName: null,
56
- attempt: null,
57
- payload: {
58
- requestId: t.id,
59
- operation: t.operation,
60
- workflowName: t.workflowName,
61
- executionId: t.executionId,
62
- generation: t.generation,
63
- cause: t.cause ?? null,
64
- kind: n.kind,
65
- status: n.status,
66
- ..."generation" in n ? { enteredGeneration: n.generation } : {}
67
- }
68
- });
69
- }, b = async (e, t) => {
70
- let n = [], i;
71
- for (;;) {
72
- let l = await e({
73
- table: c,
74
- predicate: r(a("runId", t.runId), a("workflowName", t.workflowName), a("executionId", t.executionId), a("generation", t.generation), s(a("operation", "cancel"), a("operation", "terminate")), ...i === void 0 ? [] : [o("id", i)]),
75
- order: [{
76
- column: "id",
77
- direction: "asc"
78
- }],
79
- take: 100,
80
- skip: void 0,
81
- projection: void 0
82
- });
83
- for (let e of l) {
84
- let t = v(e);
85
- t.result === null && n.push(t);
86
- }
87
- if (l.length < 100) return n;
88
- i = v(l[l.length - 1]).id;
89
- }
90
- }, x = async (e, t) => (await b(e, t)).length > 0, S = (e, t) => x((t) => e.query({
91
- ...t,
92
- lock: "update"
93
- }), t), C = {
94
- source: "flow-control",
95
- timeout: "finish"
96
- }, w = n.Struct({
97
- reason: n.NonEmptyString,
98
- detail: n.Struct({
99
- source: n.Literal("flow-control"),
100
- timeout: n.Literal("finish"),
101
- onFailure: n.NullOr(n.NonEmptyString)
102
- })
103
- }), T = (e) => {
104
- let t = n.decodeUnknownOption(w)(e.cause);
105
- return t._tag === "Some" ? t.value : void 0;
106
- }, E = async (e, t) => {
107
- let [n] = await e.query({
108
- table: c,
109
- predicate: a("id", t),
110
- lock: "update",
111
- order: [],
112
- take: 1,
113
- skip: void 0,
114
- projection: void 0
115
- });
116
- if (n !== void 0) return v(n);
117
- }, D = async (e, t) => {
118
- let n;
119
- for (;;) {
120
- let i = await e.query({
121
- table: c,
122
- predicate: r(a("parentClosureId", t), ...n === void 0 ? [] : [o("id", n)]),
123
- lock: "update",
124
- order: [{
125
- column: "id",
126
- direction: "asc"
127
- }],
128
- take: 100,
129
- skip: void 0,
130
- projection: void 0
131
- });
132
- for (let e of i) {
133
- let r = v(e);
134
- if (r.cause?.reason !== "parent-close" || r.cause.detail?.closureId !== t || r.operation === "resume") throw Error("Parent closure control has contradictory ownership");
135
- if (r.result === null) return !0;
136
- n = r.id;
137
- }
138
- if (i.length < 100) return !1;
139
- }
140
- }, O = async (e, t) => {
141
- let r = n.decodeUnknownSync(g)({
142
- ...t,
143
- owner: null,
144
- cause: t.cause ?? null,
145
- dispatchAttempts: 0,
146
- resumeJournal: null,
147
- result: null
148
- }), i = await E(e, r.id);
149
- if (i !== void 0) {
150
- if (i.runId !== r.runId || i.workflowName !== r.workflowName || i.executionId !== r.executionId || i.generation !== r.generation || i.operation !== r.operation) throw Error("Workflow control identity belongs to a different target or operation");
151
- return i;
152
- }
153
- let o = new Date(r.requestedAt);
154
- if (!Number.isFinite(o.getTime())) throw Error("Workflow control timestamp is outside the supported date range");
155
- let [s] = await e.query({
156
- table: "_voltro_workflow_runs",
157
- predicate: a("id", r.runId),
158
- lock: "update",
159
- order: [],
160
- take: 1,
161
- skip: void 0,
162
- projection: void 0
163
- });
164
- if (s !== void 0 && (s.tag !== r.workflowName || s.executionId !== r.executionId)) throw Error("Workflow control target does not match its resident run");
165
- let l = n.decodeUnknownOption(m)(s?.runnerGeneration === r.generation ? s.subject : void 0), u = {
166
- ...r,
167
- owner: l._tag === "Some" ? l.value : null
168
- }, d = s !== void 0 && s.runnerGeneration === r.generation && (s.status === "succeeded" || s.status === "failed" || s.status === "cancelled") ? {
169
- ...u,
170
- result: n.decodeUnknownSync(f)({
171
- kind: "already-terminal",
172
- status: s.status,
173
- completedAt: n.decodeUnknownSync(n.DateFromSelf)(s.completedAt).getTime(),
174
- output: s.output,
175
- errorTag: s.errorTag,
176
- errorMessage: s.errorMessage
177
- })
178
- } : u, p = d.cause?.reason === "parent-close" ? n.decodeUnknownSync(n.NonEmptyString)(d.cause.detail?.closureId) : null;
179
- return await e.insert(c, {
180
- ...d,
181
- requestedAt: o,
182
- parentClosureId: p
183
- }), d.result !== null && await y(e, d, d.result, r.requestedAt), d;
184
- }, k = async (e, t, r) => {
185
- let i = await E(e, t);
186
- if (i === void 0) throw Error("Workflow control request is missing");
187
- if (i.operation !== "resume") throw Error("Only resume controls can bind a suspension journal");
188
- if (i.result !== null) return {
189
- kind: "settled",
190
- request: i
191
- };
192
- let [o] = await e.query({
193
- table: "_voltro_workflow_runs",
194
- predicate: a("id", i.runId),
195
- lock: "update",
196
- order: [],
197
- take: 1,
198
- skip: void 0,
199
- projection: void 0
200
- });
201
- if (o === void 0) return {
202
- kind: "unknown",
203
- request: i
204
- };
205
- if (o.tag !== i.workflowName || o.executionId !== i.executionId) throw Error("Workflow control target does not match its resident run");
206
- if (o.runnerGeneration !== i.generation) return {
207
- kind: "superseded",
208
- request: i
209
- };
210
- if (o.status !== "suspended" || o.runnerEnteredAt !== null) return {
211
- kind: "not-suspended",
212
- request: i
213
- };
214
- let s = n.decodeUnknownSync(n.NullOr(n.Struct({
215
- requestId: h.fields.requestId,
216
- restartToken: h.fields.restartToken
217
- })))(o.engineDelivery);
218
- if (s === null) return {
219
- kind: "unknown",
220
- request: i
221
- };
222
- if (i.resumeJournal !== null) {
223
- if (i.resumeJournal.requestId !== s.requestId || i.resumeJournal.restartToken !== s.restartToken) throw Error("Resume journal binding does not match its resident delivery");
224
- return {
225
- kind: "bound",
226
- request: i
227
- };
228
- }
229
- if (i.dispatchAttempts !== 0) return {
230
- kind: "unknown",
231
- request: i
232
- };
233
- let c = await r({
234
- workflowName: i.workflowName,
235
- executionId: i.executionId,
236
- ...s
237
- });
238
- if (c === void 0) return {
239
- kind: "waiting-journal",
240
- request: i
241
- };
242
- let l = n.decodeUnknownSync(h)(c);
243
- if (l.requestId !== s.requestId || l.restartToken !== s.restartToken) throw Error("Observed suspension belongs to another engine delivery");
244
- if (await e.update("_voltro_workflow_control_requests", i.id, { resumeJournal: l }) === null) throw Error("Workflow control request disappeared during suspension binding");
245
- return {
246
- kind: "bound",
247
- request: {
248
- ...i,
249
- resumeJournal: l
250
- }
251
- };
252
- }, A = async (e, t) => {
253
- let n = await E(e, t);
254
- if (n === void 0) throw Error("Workflow control request is missing");
255
- if (n.result !== null) return {
256
- kind: "settled",
257
- request: n
258
- };
259
- let [r] = await e.query({
260
- table: "_voltro_workflow_runs",
261
- predicate: a("id", n.runId),
262
- lock: "update",
263
- order: [],
264
- take: 1,
265
- skip: void 0,
266
- projection: void 0
267
- });
268
- if (r === void 0) return {
269
- kind: "unknown",
270
- request: n
271
- };
272
- if (r.tag !== n.workflowName || r.executionId !== n.executionId) throw Error("Workflow control target does not match its resident run");
273
- if (r.runnerGeneration !== n.generation) return {
274
- kind: "superseded",
275
- request: n
276
- };
277
- if (r.status === "succeeded" || r.status === "failed" || r.status === "cancelled") return {
278
- kind: "already-terminal",
279
- request: n,
280
- run: r
281
- };
282
- if (r.status !== "running" && r.status !== "suspended") throw Error("Workflow control target has an invalid resident status");
283
- let i = n.dispatchAttempts + 1;
284
- if (!Number.isSafeInteger(i)) throw Error("Workflow control attempt counter exhausted");
285
- if (await e.update("_voltro_workflow_control_requests", n.id, { dispatchAttempts: i }) === null) throw Error("Workflow control request disappeared before dispatch");
286
- return {
287
- kind: "dispatch",
288
- request: {
289
- ...n,
290
- dispatchAttempts: i
291
- }
292
- };
293
- }, j = async (e, t) => {
294
- let i = t.owner, s;
295
- for (;;) {
296
- let l = await e.query({
297
- table: c,
298
- predicate: r(a("runId", i.runId), a("workflowName", i.workflowName), a("executionId", i.executionId), a("generation", i.generation), ...s === void 0 ? [] : [o("id", s)]),
299
- lock: "update",
300
- order: [{
301
- column: "id",
302
- direction: "asc"
303
- }],
304
- take: 100,
305
- skip: void 0,
306
- projection: void 0
307
- });
308
- for (let r of l) {
309
- if (typeof r.id != "string") throw Error("Workflow control request has an invalid identity");
310
- let i = await E(e, r.id);
311
- if (i === void 0) throw Error("Workflow control request disappeared during completion");
312
- if (i.result !== null) continue;
313
- let a = t.outcome;
314
- await y(e, i, n.decodeUnknownSync(f)({
315
- kind: a.status === "cancelled" && i.operation !== "resume" ? "confirmed" : "already-terminal",
316
- status: a.status,
317
- completedAt: t.now,
318
- output: a.status === "succeeded" ? a.output : null,
319
- errorTag: a.status === "failed" ? a.errorTag : null,
320
- errorMessage: a.status === "failed" ? a.errorMessage : null
321
- }), t.now);
322
- }
323
- if (l.length < 100) return;
324
- let u = l[l.length - 1];
325
- if (typeof u.id != "string") throw Error("Workflow control cursor has an invalid identity");
326
- s = u.id;
327
- }
328
- }, M = async (e, t, i, s) => {
329
- let l = n.decodeUnknownSync(d)({
330
- kind: "confirmed",
331
- status: "running",
332
- generation: i,
333
- enteredAt: s
334
- }), u;
335
- for (;;) {
336
- let n = await e.query({
337
- table: c,
338
- predicate: r(a("runId", t.runId), a("workflowName", t.workflowName), a("executionId", t.executionId), a("generation", t.generation), a("operation", "resume"), ...u === void 0 ? [] : [o("id", u)]),
339
- lock: "update",
340
- order: [{
341
- column: "id",
342
- direction: "asc"
343
- }],
344
- take: 100,
345
- skip: void 0,
346
- projection: void 0
347
- });
348
- for (let t of n) {
349
- if (typeof t.id != "string") throw Error("Workflow control request has an invalid identity");
350
- let n = await E(e, t.id);
351
- if (n === void 0) throw Error("Workflow control request disappeared during resume");
352
- n.result === null && await y(e, n, l, s);
353
- }
354
- if (n.length < 100) return;
355
- let i = n[n.length - 1];
356
- if (typeof i.id != "string") throw Error("Workflow control cursor has an invalid identity");
357
- u = i.id;
358
- }
359
- }, N = "voltro-workflow-restart", P = class extends e.Tag("voltro/CurrentWorkflowDelivery")() {}, F = (e) => ({
360
- ...e,
361
- registerEntity: (n, r, i) => e.registerEntity(n, n.type.startsWith("Workflow/") ? r.pipe(t.map((e) => {
362
- let n = e.run;
363
- if (typeof n != "function") throw Error("Workflow entity is missing its run handler");
364
- return {
365
- ...e,
366
- run: (e) => {
367
- let r = {
368
- requestId: String(e.requestId),
369
- restartToken: e.headers["voltro-workflow-restart"] ?? null
370
- };
371
- return t.suspend(() => {
372
- let r = n(e);
373
- return t.isEffect(r) ? r : t.die(/* @__PURE__ */ Error("Workflow run handler must return an Effect"));
374
- }).pipe(t.provideService(P, r));
375
- }
376
- };
377
- })) : r, i)
378
- }), I = 6e5, L = class extends e.Tag("@voltro/workflow/ClusterDiagnostics")() {}, R = (e, n, r = Date.now()) => t.flatMap(e.messagesFor(n), (n) => {
379
- if (n.length === 0) return t.succeed(void 0);
380
- let i = [...new Set(n.filter((e) => !e.processed).map((e) => e.shardId))], a = i.length === 0 ? t.succeed([]) : e.shardLockHolders(i);
381
- return t.map(a, (t) => ({
382
- runner: e.ownAddress,
383
- shardLockMode: e.shardLockMode,
384
- messages: n.map((e) => ({
385
- tag: e.tag,
386
- shardId: e.shardId,
387
- processed: e.processed,
388
- lastRead: e.lastRead === null ? null : e.lastRead.toISOString(),
389
- unreadForMs: !e.processed && e.lastRead !== null ? Math.max(0, r - e.lastRead.getTime()) : null
390
- })),
391
- shardLocks: t
392
- }));
393
- });
394
- //#endregion
395
- export { j as _, N as a, O as c, T as d, S as f, E as g, b as h, P as i, A as l, x as m, L as n, F as o, D as p, R as r, C as s, I as t, k as u, M as v };