@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.
- package/CHANGELOG.md +5987 -0
- package/THIRD-PARTY-NOTICES.md +1122 -31
- package/dist/admission.js +140 -0
- package/dist/admissionDrainer.js +705 -0
- package/dist/admissionGate.js +115 -0
- package/dist/admissionStore.js +347 -0
- package/dist/admissionSubmission.js +297 -0
- package/dist/admissionTables.js +137 -0
- package/dist/admissionTransaction.js +21 -0
- package/dist/awaitEvent.js +82 -0
- package/dist/budgetHold.js +136 -0
- package/dist/cancelOnPlan.js +75 -0
- package/dist/cancelOnSweep.js +188 -0
- package/dist/cancelPendingStart.js +50 -0
- package/dist/cluster.d.ts +111 -27
- package/dist/cluster.js +12 -2
- package/dist/clusterCron.js +19 -0
- package/dist/clusterDiagnostics.js +20 -0
- package/dist/clusterDiagnosticsSql.js +145 -0
- package/dist/clusterLayer.js +145 -0
- package/dist/clusterMigrationGate.js +61 -0
- package/dist/clusterRunnerLayer.js +31 -0
- package/dist/clusterShardGroups.js +33 -0
- package/dist/clusterTestSuite.d.ts +23 -0
- package/dist/clusterTestSuite.js +209 -179
- package/dist/controlMonitor.js +13 -0
- package/dist/controlRequest.js +367 -0
- package/dist/executionRefusal.js +162 -0
- package/dist/failureHandoff.js +183 -0
- package/dist/failureMessage.js +12 -0
- package/dist/failureRecovery.js +50 -0
- package/dist/failureReportStore.js +60 -0
- package/dist/flowControl.js +142 -0
- package/dist/forwardStartReceipts.js +41 -0
- package/dist/inMemoryLayer.js +7 -0
- package/dist/inMemoryRecorder.js +56 -0
- package/dist/index.d.ts +129 -30
- package/dist/index.js +50 -5
- package/dist/inspectWorkflow.js +101 -0
- package/dist/{journalEncryption-DTyhUzaS.js → journalEncryption.js} +30 -37
- package/dist/journalRoutingGuard.js +50 -0
- package/dist/journalRoutingLayout.js +47 -0
- package/dist/journalRoutingLock.js +39 -0
- package/dist/journalRoutingMaintenance.js +24 -0
- package/dist/journalRoutingMessageStorage.js +32 -0
- package/dist/journalRoutingNamespace.js +23 -0
- package/dist/journalRoutingRuntime.js +33 -0
- package/dist/journalRoutingSharding.js +28 -0
- package/dist/journalRoutingState.js +93 -0
- package/dist/journalRoutingTable.js +11 -0
- package/dist/journalRoutingTransaction.js +16 -0
- package/dist/messages.js +92 -0
- package/dist/nondeterminism.js +51 -0
- package/dist/parentClosure.js +141 -0
- package/dist/parentClosureRecovery.js +54 -0
- package/dist/pendingSubmission.js +85 -0
- package/dist/prepareSubmissionDispatch.js +17 -0
- package/dist/preparedExecution.js +14 -0
- package/dist/primitives.js +225 -2
- package/dist/queuedCancellationRequest.js +364 -0
- package/dist/queuedControl.js +21 -0
- package/dist/recorder.js +11 -0
- package/dist/residentExecutionEvidence.js +64 -0
- package/dist/retryPolicy.js +57 -0
- package/dist/runEventsTable.js +17 -0
- package/dist/runGeneration.js +345 -0
- package/dist/runRecording.js +615 -0
- package/dist/runStepsTable.js +28 -0
- package/dist/runnerStorageGuard.js +29 -0
- package/dist/runsTable.js +42 -0
- package/dist/scheduleDeclaration.js +44 -0
- package/dist/signalHint.js +23 -0
- package/dist/signals.js +70 -0
- package/dist/signalsSuspending.js +57 -0
- package/dist/sqliteWorkflowOwnership.js +26 -0
- package/dist/stalenessSweep.js +191 -0
- package/dist/startContextsTable.js +20 -0
- package/dist/startReceipt.js +143 -0
- package/dist/submissionRecovery.js +122 -0
- package/dist/submissionRejection.js +10 -0
- package/dist/submissionRetry.js +71 -0
- package/dist/suspensionUnavailable.js +9 -0
- package/dist/updates.js +87 -0
- package/dist/watermarkTable.js +9 -0
- package/dist/webCrypto.js +17 -0
- package/dist/workflowDelivery.js +24 -0
- package/dist/workflowExecutorRouting.js +33 -0
- package/dist/workflowJournal.js +124 -0
- package/dist/workflowJournalReset.js +111 -0
- package/dist/workflowReadSelections.js +12 -0
- package/dist/workflowRestartDispatch.js +35 -0
- package/dist/workflowRestartObservation.js +60 -0
- package/dist/workflowRestartPreparation.js +109 -0
- package/dist/workflowRestartReservation.js +427 -0
- package/dist/workflowResumeDispatch.js +30 -0
- package/dist/workflowRuntimeReadiness.js +12 -0
- package/dist/workflowShardRelocation.js +58 -0
- package/dist/workflowShardRelocationSql.js +72 -0
- package/package.json +4 -4
- package/dist/cluster-F_bhqVP7.js +0 -679
- package/dist/primitives-DX04WTWh.js +0 -507
- package/dist/src-C2NEyUM8.js +0 -3925
- package/dist/workflowReadSelections-CZAUjP7f.js +0 -2096
|
@@ -1,2096 +0,0 @@
|
|
|
1
|
-
import { C as e, S as t, _ as n, b as r, l as i, m as a } from "./journalEncryption-DTyhUzaS.js";
|
|
2
|
-
import { Context as o, Effect as s, Schema as c } from "effect";
|
|
3
|
-
import { WorkflowRestartObservationSchema as l, WorkflowRestartSelectionSchema as u, WorkflowRestartTargetSchema as d, WorkflowStartTerminalOutcomeSchema as f } from "@voltro/protocol";
|
|
4
|
-
import { and as p, derivedRowId as m, eq as h, gt as g, id as _, integer as ee, isNull as v, json as y, or as te, table as ne, text as b, timestamp as re } from "@voltro/database";
|
|
5
|
-
import { createHash as ie, randomUUID as x } from "node:crypto";
|
|
6
|
-
import { isDeepStrictEqual as ae } from "node:util";
|
|
7
|
-
import { SqlClient as S } from "effect/sql";
|
|
8
|
-
//#region src/admissionTransaction.ts
|
|
9
|
-
var oe = "_voltro_workflow_admission_locks", se = "deployment", C = async (e, t) => (await e.insertIgnoreWithOutcome(oe, {
|
|
10
|
-
id: se,
|
|
11
|
-
nonce: x()
|
|
12
|
-
}, { conflictColumns: ["id"] }), e.transactional(async (e) => {
|
|
13
|
-
if ((await e.query({
|
|
14
|
-
table: "_voltro_workflow_admission_locks",
|
|
15
|
-
predicate: h("id", se),
|
|
16
|
-
lock: "update",
|
|
17
|
-
order: [],
|
|
18
|
-
take: 1,
|
|
19
|
-
skip: void 0,
|
|
20
|
-
projection: void 0
|
|
21
|
-
})).length !== 1) throw Error("Admission coordinator row is missing; refusing an unlocked decision");
|
|
22
|
-
if (await e.update("_voltro_workflow_admission_locks", se, { nonce: x() }) === null) throw Error("Admission coordinator row disappeared; refusing an unlocked decision");
|
|
23
|
-
return t(e);
|
|
24
|
-
})), ce = class extends Error {
|
|
25
|
-
workflowName;
|
|
26
|
-
field;
|
|
27
|
-
constructor(e, t, n) {
|
|
28
|
-
super(`workflow '${e}': ${t}(payload) threw — a flow-control key function must be total over every payload the workflow accepts, because it runs before the run exists and there is nowhere to report a partial failure to. Cause: ${n instanceof Error ? n.message : String(n)}`), this.name = "FlowControlKeyError", this.workflowName = e, this.field = t, this.cause = n;
|
|
29
|
-
}
|
|
30
|
-
}, w = (e, t, n, r) => {
|
|
31
|
-
try {
|
|
32
|
-
let e = n(r);
|
|
33
|
-
if (typeof e != "string" || e.length === 0) throw Error(`returned ${e === "" ? "an empty string" : String(e)}; expected a non-empty string`);
|
|
34
|
-
return e;
|
|
35
|
-
} catch (n) {
|
|
36
|
-
throw new ce(e, t, n);
|
|
37
|
-
}
|
|
38
|
-
}, le = (e, t) => JSON.stringify([e ?? null, t]), ue = (e, t) => {
|
|
39
|
-
let n = e.workflowName, r = 0;
|
|
40
|
-
if (e.priority !== void 0) try {
|
|
41
|
-
let n = e.priority(t);
|
|
42
|
-
if (!Number.isFinite(n)) throw Error(`returned ${String(n)}; expected a finite number`);
|
|
43
|
-
r = Math.trunc(n);
|
|
44
|
-
} catch (e) {
|
|
45
|
-
throw new ce(n, "priority", e);
|
|
46
|
-
}
|
|
47
|
-
return {
|
|
48
|
-
...e.debounce === void 0 ? {} : { debounceKey: w(n, "debounce.key", e.debounce.key, t) },
|
|
49
|
-
...e.singleton === void 0 ? {} : { singletonKey: w(n, "singleton.key", e.singleton.key, t) },
|
|
50
|
-
...e.concurrency === void 0 ? {} : { concurrencyKey: le(e.concurrency.pool, e.concurrency.key === void 0 ? "" : w(n, "concurrency.key", e.concurrency.key, t)) },
|
|
51
|
-
...e.throttle?.key === void 0 ? e.throttle === void 0 ? {} : { throttleKey: "" } : { throttleKey: w(n, "throttle.key", e.throttle.key, t) },
|
|
52
|
-
...e.rateLimit?.key === void 0 ? e.rateLimit === void 0 ? {} : { rateLimitKey: "" } : { rateLimitKey: w(n, "rateLimit.key", e.rateLimit.key, t) },
|
|
53
|
-
...e.batch?.key === void 0 ? e.batch === void 0 ? {} : { batchKey: "" } : { batchKey: w(n, "batch.key", e.batch.key, t) },
|
|
54
|
-
priority: r
|
|
55
|
-
};
|
|
56
|
-
}, de = (e, t, n, r) => {
|
|
57
|
-
let i = e.filter((e) => e > r - n);
|
|
58
|
-
if (i.length < t) return;
|
|
59
|
-
let a = [...i].sort((e, t) => t - e)[t - 1];
|
|
60
|
-
if (a !== void 0) return a + n;
|
|
61
|
-
}, fe = (e) => {
|
|
62
|
-
let { control: t, keys: n, state: r, now: i, reconsidering: a } = e;
|
|
63
|
-
if (r.paused === !0) return {
|
|
64
|
-
kind: "defer",
|
|
65
|
-
mode: "paused",
|
|
66
|
-
dueAt: i,
|
|
67
|
-
collapse: a ? "hold" : "append",
|
|
68
|
-
keys: n
|
|
69
|
-
};
|
|
70
|
-
if (t.rateLimit !== void 0) {
|
|
71
|
-
let e = de(r.recentAdmissions ?? [], t.rateLimit.limit, t.rateLimit.periodMs, i);
|
|
72
|
-
if (e !== void 0) return {
|
|
73
|
-
kind: "drop",
|
|
74
|
-
reason: "rate-limit",
|
|
75
|
-
retryAfterMs: Math.max(0, e - i),
|
|
76
|
-
keys: n
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
if (t.singleton !== void 0 && r.singletonUnacknowledged === !0) return {
|
|
80
|
-
kind: "defer",
|
|
81
|
-
mode: "singleton",
|
|
82
|
-
dueAt: i,
|
|
83
|
-
collapse: a ? "hold" : "append",
|
|
84
|
-
keys: n
|
|
85
|
-
};
|
|
86
|
-
if (t.singleton !== void 0 && t.singleton.mode === "skip" && r.singletonHolder !== void 0) return {
|
|
87
|
-
kind: "skip",
|
|
88
|
-
incumbent: r.singletonHolder,
|
|
89
|
-
keys: n
|
|
90
|
-
};
|
|
91
|
-
if (t.debounce !== void 0) {
|
|
92
|
-
let e = r.debouncePending, o = e?.firstSeenAt ?? i, s = e?.deadlineAt ?? (t.debounce.timeoutMs === void 0 ? void 0 : o + t.debounce.timeoutMs);
|
|
93
|
-
return a ? s !== void 0 && i >= s ? {
|
|
94
|
-
kind: "admit",
|
|
95
|
-
reason: "debounce-deadline",
|
|
96
|
-
keys: n,
|
|
97
|
-
...T(t, r)
|
|
98
|
-
} : {
|
|
99
|
-
kind: "admit",
|
|
100
|
-
reason: "debounce-elapsed",
|
|
101
|
-
keys: n,
|
|
102
|
-
...T(t, r)
|
|
103
|
-
} : {
|
|
104
|
-
kind: "defer",
|
|
105
|
-
mode: "debounce",
|
|
106
|
-
dueAt: s === void 0 ? i + t.debounce.periodMs : Math.min(i + t.debounce.periodMs, s),
|
|
107
|
-
...s === void 0 ? {} : { deadlineAt: s },
|
|
108
|
-
collapse: "replace",
|
|
109
|
-
keys: n
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
if (t.batch !== void 0) {
|
|
113
|
-
let e = r.batchPending, o = (e?.count ?? 0) + +!a, s = (e?.firstSeenAt ?? i) + t.batch.timeoutMs;
|
|
114
|
-
return o >= t.batch.maxSize ? {
|
|
115
|
-
kind: "admit",
|
|
116
|
-
reason: "batch-full",
|
|
117
|
-
keys: n,
|
|
118
|
-
...T(t, r)
|
|
119
|
-
} : a && i >= s ? {
|
|
120
|
-
kind: "admit",
|
|
121
|
-
reason: "batch-timeout",
|
|
122
|
-
keys: n,
|
|
123
|
-
...T(t, r)
|
|
124
|
-
} : {
|
|
125
|
-
kind: "defer",
|
|
126
|
-
mode: "batch",
|
|
127
|
-
dueAt: s,
|
|
128
|
-
collapse: a ? "hold" : "append",
|
|
129
|
-
keys: n
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
if (t.throttle !== void 0) {
|
|
133
|
-
let e = de(r.recentAdmissions ?? [], t.throttle.limit, t.throttle.periodMs, i);
|
|
134
|
-
if (e !== void 0) return {
|
|
135
|
-
kind: "defer",
|
|
136
|
-
mode: "throttle",
|
|
137
|
-
dueAt: e,
|
|
138
|
-
collapse: a ? "hold" : "append",
|
|
139
|
-
keys: n
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
return t.concurrency !== void 0 && (r.inFlight ?? 0) >= t.concurrency.limit ? {
|
|
143
|
-
kind: "defer",
|
|
144
|
-
mode: "concurrency",
|
|
145
|
-
dueAt: i,
|
|
146
|
-
collapse: a ? "hold" : "append",
|
|
147
|
-
keys: n
|
|
148
|
-
} : {
|
|
149
|
-
kind: "admit",
|
|
150
|
-
reason: pe(t) ? "under-limits" : "no-controls",
|
|
151
|
-
keys: n,
|
|
152
|
-
...T(t, r)
|
|
153
|
-
};
|
|
154
|
-
}, pe = (e) => e.debounce !== void 0 || e.singleton !== void 0 || e.concurrency !== void 0 || e.throttle !== void 0 || e.rateLimit !== void 0 || e.batch !== void 0, T = (e, t) => e.singleton?.mode === "cancel" && t.singletonHolder !== void 0 ? { evict: t.singletonHolder } : {}, me = (e, t, n) => {
|
|
155
|
-
let r = e.timeouts?.startMs;
|
|
156
|
-
return r !== void 0 && n - t.firstSeenAt >= r;
|
|
157
|
-
}, he = (e, t, n) => {
|
|
158
|
-
let r = e.timeouts?.finishMs;
|
|
159
|
-
return r === void 0 || t.terminal ? !1 : n - t.startedAt >= r;
|
|
160
|
-
}, ge = (e, t) => e.priority === t.priority ? e.firstSeenAt === t.firstSeenAt ? e.id < t.id ? -1 : +(e.id > t.id) : e.firstSeenAt - t.firstSeenAt : t.priority - e.priority, E = "_voltro_workflow_failure_reports", _e = c.Struct({
|
|
161
|
-
id: c.String,
|
|
162
|
-
workflowName: c.String,
|
|
163
|
-
tenantId: c.NullOr(c.String),
|
|
164
|
-
sourceId: c.String,
|
|
165
|
-
sourceKind: c.Literals([
|
|
166
|
-
"submission",
|
|
167
|
-
"intent",
|
|
168
|
-
"run"
|
|
169
|
-
]),
|
|
170
|
-
handler: c.NullOr(c.String),
|
|
171
|
-
callerContext: c.Unknown,
|
|
172
|
-
report: c.Struct({
|
|
173
|
-
workflow: c.String,
|
|
174
|
-
payload: c.Unknown,
|
|
175
|
-
errorTag: c.NullOr(c.String),
|
|
176
|
-
errorMessage: c.NullOr(c.String),
|
|
177
|
-
runId: c.NullOr(c.String),
|
|
178
|
-
executionId: c.NullOr(c.String),
|
|
179
|
-
reason: c.String,
|
|
180
|
-
failedAt: c.Number
|
|
181
|
-
})
|
|
182
|
-
}), D = async (e, t) => {
|
|
183
|
-
let n = await e.query({
|
|
184
|
-
table: E,
|
|
185
|
-
predicate: h("id", t),
|
|
186
|
-
order: [],
|
|
187
|
-
take: 1,
|
|
188
|
-
skip: void 0,
|
|
189
|
-
projection: void 0
|
|
190
|
-
});
|
|
191
|
-
return n[0] === void 0 ? void 0 : c.decodeUnknownSync(_e)(n[0]);
|
|
192
|
-
}, ve = async (e, t) => {
|
|
193
|
-
if (t.id.length === 0 || t.sourceId.length === 0) throw Error("Workflow failure requires a stable report and source identity");
|
|
194
|
-
let n = await D(e, t.id);
|
|
195
|
-
if (n !== void 0) {
|
|
196
|
-
if (n.workflowName !== t.workflowName || n.tenantId !== t.tenantId || n.sourceId !== t.sourceId || n.sourceKind !== t.sourceKind) throw Error("Workflow failure identity belongs to a different source, workflow or tenant");
|
|
197
|
-
return n;
|
|
198
|
-
}
|
|
199
|
-
let i = c.decodeUnknownSync(_e)(t), a = {
|
|
200
|
-
...i,
|
|
201
|
-
report: {
|
|
202
|
-
...i.report,
|
|
203
|
-
errorMessage: r(i.workflowName, i.report.errorMessage)
|
|
204
|
-
}
|
|
205
|
-
};
|
|
206
|
-
if (a.report.workflow !== a.workflowName) throw Error("Workflow failure report does not describe its owning workflow");
|
|
207
|
-
return await e.insert(E, {
|
|
208
|
-
...a,
|
|
209
|
-
handoffReceiptId: null,
|
|
210
|
-
handoffAttempt: 0,
|
|
211
|
-
acceptedExecutionId: null
|
|
212
|
-
}), a;
|
|
213
|
-
}, ye = async (e, t, n) => {
|
|
214
|
-
let r, i = t === "submissionId" ? h(t, n) : p(h(t, n), v("submissionId"), v("terminal"));
|
|
215
|
-
for (;;) {
|
|
216
|
-
let t = await e.query({
|
|
217
|
-
table: N,
|
|
218
|
-
predicate: r === void 0 ? i : p(i, g("id", r)),
|
|
219
|
-
order: [{
|
|
220
|
-
column: "id",
|
|
221
|
-
direction: "asc"
|
|
222
|
-
}],
|
|
223
|
-
take: 100,
|
|
224
|
-
skip: void 0,
|
|
225
|
-
projection: void 0
|
|
226
|
-
});
|
|
227
|
-
if (t.length === 0) return !1;
|
|
228
|
-
for (let n of t) {
|
|
229
|
-
let t = P(n), i = await e.query({
|
|
230
|
-
table: E,
|
|
231
|
-
predicate: h("handoffReceiptId", t.id),
|
|
232
|
-
order: [],
|
|
233
|
-
take: 1,
|
|
234
|
-
skip: void 0,
|
|
235
|
-
projection: void 0
|
|
236
|
-
});
|
|
237
|
-
if (i.length !== 0) {
|
|
238
|
-
if (i[0]?.handler !== t.workflowName || i[0]?.tenantId !== t.tenantId) throw Error("Failure delivery receipt belongs to a different workflow or tenant");
|
|
239
|
-
return !0;
|
|
240
|
-
}
|
|
241
|
-
r = t.id;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}, be = (e, t) => ye(e, "submissionId", t), xe = (e, t) => ye(e, "pendingId", t), Se = async (e, t, n, r) => {
|
|
245
|
-
for await (let i of Pe(e, t, n)) {
|
|
246
|
-
if (i.tenantId !== r) throw Error("Failure delivery belongs to a different resident tenant");
|
|
247
|
-
if (await be(e, i.id)) return !0;
|
|
248
|
-
}
|
|
249
|
-
return !1;
|
|
250
|
-
}, Ce = c.Struct({
|
|
251
|
-
handoffReceiptId: c.NullOr(c.String),
|
|
252
|
-
handoffAttempt: c.Number.check(c.isInt(), c.isGreaterThanOrEqualTo(0)),
|
|
253
|
-
acceptedExecutionId: c.NullOr(c.NonEmptyString)
|
|
254
|
-
}), we = (e, t) => `wfrc_${ie("sha256").update(JSON.stringify([
|
|
255
|
-
"failure",
|
|
256
|
-
e,
|
|
257
|
-
t
|
|
258
|
-
])).digest("hex").slice(0, 40)}`, Te = async (e, t) => {
|
|
259
|
-
let n = await e.query({
|
|
260
|
-
table: E,
|
|
261
|
-
predicate: h("id", t),
|
|
262
|
-
order: [],
|
|
263
|
-
take: 1,
|
|
264
|
-
skip: void 0,
|
|
265
|
-
projection: void 0
|
|
266
|
-
}), r = c.decodeUnknownSync(Ce)(n[0]);
|
|
267
|
-
if (r.handoffReceiptId === null && (r.handoffAttempt !== 0 || r.acceptedExecutionId !== null)) throw Error("Failure report has contradictory unstarted handoff metadata");
|
|
268
|
-
return r;
|
|
269
|
-
}, Ee = (t) => {
|
|
270
|
-
if (t.handler === null || !i(t.handler)) return t.report;
|
|
271
|
-
let r = `failure report for '${t.handler}'`;
|
|
272
|
-
return e({
|
|
273
|
-
...t.report,
|
|
274
|
-
payload: n(t.report.payload, `${r}.payload`),
|
|
275
|
-
errorMessage: a(t.report.errorMessage)
|
|
276
|
-
}, r);
|
|
277
|
-
}, De = async (e, t, n, r, i) => {
|
|
278
|
-
if (t.handler === null || t.handler.length === 0) throw Error("Cannot queue an unconfigured failure handler");
|
|
279
|
-
if (!Number.isSafeInteger(n) || n < 0) throw Error("Failure handoff attempt exhausted");
|
|
280
|
-
if (!Number.isFinite(r)) throw Error("Failure handoff retry deadline is invalid");
|
|
281
|
-
let a = await lt({
|
|
282
|
-
store: e,
|
|
283
|
-
workflowName: t.handler,
|
|
284
|
-
payload: Ee(t),
|
|
285
|
-
callerContext: t.callerContext,
|
|
286
|
-
tenantId: t.tenantId,
|
|
287
|
-
at: r,
|
|
288
|
-
now: i
|
|
289
|
-
}), o = await Ze(e, {
|
|
290
|
-
id: we(t.id, n),
|
|
291
|
-
workflowName: t.handler,
|
|
292
|
-
tenantId: t.tenantId,
|
|
293
|
-
pendingId: a.intentId
|
|
294
|
-
});
|
|
295
|
-
if (await e.update("_voltro_workflow_failure_reports", t.id, {
|
|
296
|
-
handoffReceiptId: o.id,
|
|
297
|
-
handoffAttempt: n
|
|
298
|
-
}) === null) throw Error("Failure report disappeared during durable handoff");
|
|
299
|
-
return {
|
|
300
|
-
kind: "queued",
|
|
301
|
-
receiptId: o.id,
|
|
302
|
-
intentId: o.pendingId
|
|
303
|
-
};
|
|
304
|
-
}, O = async (e, t, n) => {
|
|
305
|
-
if (!Number.isFinite(n)) throw Error("Failure handoff requires a finite timestamp");
|
|
306
|
-
let r = await D(e, t);
|
|
307
|
-
if (r === void 0) throw Error("Cannot hand off an unknown workflow failure");
|
|
308
|
-
let { handoffReceiptId: i, handoffAttempt: a, acceptedExecutionId: o } = await Te(e, t);
|
|
309
|
-
if (r.handler === null) {
|
|
310
|
-
if (i !== null || o !== null) throw Error("Unconfigured failure report has a contradictory handoff");
|
|
311
|
-
return { kind: "unconfigured" };
|
|
312
|
-
}
|
|
313
|
-
if (r.handler.length === 0) throw Error("Failure report has an empty handler");
|
|
314
|
-
let s = we(t, a);
|
|
315
|
-
if (i !== null) {
|
|
316
|
-
if (i !== s) throw Error("Failure handoff receipt belongs to a different report");
|
|
317
|
-
let t = await F(e, i);
|
|
318
|
-
if (t === void 0 || t.workflowName !== r.handler || t.tenantId !== r.tenantId) throw Error("Failure report has no matching durable start receipt");
|
|
319
|
-
return {
|
|
320
|
-
kind: "queued",
|
|
321
|
-
receiptId: t.id,
|
|
322
|
-
intentId: t.pendingId
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
return De(e, r, 0, n, n);
|
|
326
|
-
}, k = class extends Error {
|
|
327
|
-
reason;
|
|
328
|
-
constructor(e) {
|
|
329
|
-
super(`Workflow failure delivery requires reconciliation: ${e}`), this.reason = e;
|
|
330
|
-
}
|
|
331
|
-
}, Oe = async (e, t, n) => {
|
|
332
|
-
let r = await O(e, t, n);
|
|
333
|
-
if (r.kind === "unconfigured") return r;
|
|
334
|
-
let i = await Te(e, t), a = await F(e, r.receiptId);
|
|
335
|
-
if (a === void 0) throw Error("Failure handoff receipt disappeared during reconciliation");
|
|
336
|
-
if (i.acceptedExecutionId !== null) {
|
|
337
|
-
if (a.terminal !== null || a.submissionId === null) throw Error("Accepted failure report has no submitted receipt");
|
|
338
|
-
return {
|
|
339
|
-
kind: "accepted",
|
|
340
|
-
executionId: i.acceptedExecutionId
|
|
341
|
-
};
|
|
342
|
-
}
|
|
343
|
-
if (a.terminal !== null) {
|
|
344
|
-
if (a.terminal.kind === "cancelled") return {
|
|
345
|
-
kind: "cancelled",
|
|
346
|
-
receiptId: a.id
|
|
347
|
-
};
|
|
348
|
-
let r = await D(e, t);
|
|
349
|
-
if (r === void 0) throw Error("Failure report disappeared during retry");
|
|
350
|
-
let o = i.handoffAttempt + 1, s = Math.max(W(o, () => 1), a.terminal.kind === "dropped" ? a.terminal.retryAfterMs : 0);
|
|
351
|
-
return De(e, r, o, Math.max(n, a.terminal.at + s), n);
|
|
352
|
-
}
|
|
353
|
-
if (a.submissionId === null) {
|
|
354
|
-
let t = (await e.query({
|
|
355
|
-
table: I,
|
|
356
|
-
predicate: h("id", a.pendingId),
|
|
357
|
-
order: [],
|
|
358
|
-
take: 1,
|
|
359
|
-
skip: void 0,
|
|
360
|
-
projection: void 0
|
|
361
|
-
}))[0];
|
|
362
|
-
if (t === void 0) throw new k("arrival-missing");
|
|
363
|
-
if (t.workflowName !== a.workflowName || t.tenantId !== a.tenantId) throw new k("arrival-owner-mismatch");
|
|
364
|
-
if (t.deadLetteredAt !== null) throw new k("arrival-dead-lettered");
|
|
365
|
-
return r;
|
|
366
|
-
}
|
|
367
|
-
let o = await M(e, a.submissionId);
|
|
368
|
-
if (o === void 0 || !o.receiptsBound || o.workflowName !== a.workflowName || o.tenantId !== a.tenantId || !o.intentIds.includes(a.pendingId)) throw Error("Failure handoff receipt has no matching admission submission");
|
|
369
|
-
if (o.failureId !== null) {
|
|
370
|
-
let r = await D(e, o.failureId);
|
|
371
|
-
if (o.executionId !== null || o.dispatchAttempts > 1 || r === void 0 || r.sourceKind !== "submission" || r.sourceId !== o.id || r.workflowName !== o.workflowName || r.tenantId !== o.tenantId || r.report.executionId !== null || r.report.runId !== null) throw new k("rejection-proof-invalid");
|
|
372
|
-
let a = await D(e, t);
|
|
373
|
-
if (a === void 0) throw Error("Failure report disappeared during rejected handler retry");
|
|
374
|
-
let s = i.handoffAttempt + 1;
|
|
375
|
-
return De(e, a, s, Math.max(n, r.report.failedAt + W(s, () => 1)), n);
|
|
376
|
-
}
|
|
377
|
-
if (o.executionId === null) return r;
|
|
378
|
-
if (o.failureId !== null || o.executionId.length === 0 || o.preparedExecutionId !== o.executionId) throw Error("Failure handler acknowledgement contradicts its prepared submission");
|
|
379
|
-
if (await e.update("_voltro_workflow_failure_reports", t, { acceptedExecutionId: o.executionId }) === null) throw Error("Failure report disappeared during acceptance acknowledgement");
|
|
380
|
-
return {
|
|
381
|
-
kind: "accepted",
|
|
382
|
-
executionId: o.executionId
|
|
383
|
-
};
|
|
384
|
-
}, ke = c.Struct({
|
|
385
|
-
runId: c.NonEmptyString,
|
|
386
|
-
workflowName: c.NonEmptyString,
|
|
387
|
-
executionId: c.NonEmptyString,
|
|
388
|
-
generation: c.NonEmptyString,
|
|
389
|
-
parentStatus: c.Literals([
|
|
390
|
-
"succeeded",
|
|
391
|
-
"failed",
|
|
392
|
-
"cancelled"
|
|
393
|
-
]),
|
|
394
|
-
closedAt: c.Date
|
|
395
|
-
}), Ae = async (e, t, n) => {
|
|
396
|
-
let [r] = await e.query({
|
|
397
|
-
table: "_voltro_workflow_runs",
|
|
398
|
-
predicate: h("executionId", n),
|
|
399
|
-
lock: "update",
|
|
400
|
-
order: [],
|
|
401
|
-
take: 1,
|
|
402
|
-
skip: void 0,
|
|
403
|
-
projection: void 0
|
|
404
|
-
});
|
|
405
|
-
if (r !== void 0) {
|
|
406
|
-
if (r.tag !== t) throw Error("Admission acknowledgement belongs to a different resident workflow");
|
|
407
|
-
if (typeof r.id != "string" || r.id.length === 0) throw Error("Resident execution has no run identity");
|
|
408
|
-
if (r.status === "running" || r.status === "suspended") return {
|
|
409
|
-
runId: r.id,
|
|
410
|
-
completedAt: null
|
|
411
|
-
};
|
|
412
|
-
if (r.status !== "succeeded" && r.status !== "failed" && r.status !== "cancelled") throw Error("Resident execution has an unrecognized status");
|
|
413
|
-
if (!(r.completedAt instanceof Date) || !Number.isFinite(r.completedAt.getTime())) throw Error("Terminal workflow has no valid completion timestamp for lease release");
|
|
414
|
-
return {
|
|
415
|
-
runId: r.id,
|
|
416
|
-
completedAt: r.completedAt
|
|
417
|
-
};
|
|
418
|
-
}
|
|
419
|
-
let [i] = await e.query({
|
|
420
|
-
table: "_voltro_workflow_parent_closures",
|
|
421
|
-
predicate: h("executionId", n),
|
|
422
|
-
lock: "update",
|
|
423
|
-
order: [{
|
|
424
|
-
column: "closedAt",
|
|
425
|
-
direction: "desc"
|
|
426
|
-
}, {
|
|
427
|
-
column: "id",
|
|
428
|
-
direction: "desc"
|
|
429
|
-
}],
|
|
430
|
-
take: 1,
|
|
431
|
-
skip: void 0,
|
|
432
|
-
projection: void 0
|
|
433
|
-
});
|
|
434
|
-
if (i === void 0) return;
|
|
435
|
-
let a = c.decodeUnknownSync(ke)(i);
|
|
436
|
-
if (a.workflowName !== t || a.executionId !== n) throw Error("Admission acknowledgement belongs to a different resident workflow");
|
|
437
|
-
if (!Number.isFinite(a.closedAt.getTime())) throw Error("Workflow closure has no valid completion timestamp");
|
|
438
|
-
return {
|
|
439
|
-
runId: a.runId,
|
|
440
|
-
completedAt: a.closedAt
|
|
441
|
-
};
|
|
442
|
-
}, A = "_voltro_workflow_submissions", je = "wfsub", Me = () => `${je}_${x()}`, j = c.Struct({
|
|
443
|
-
id: c.String,
|
|
444
|
-
workflowName: c.String,
|
|
445
|
-
tenantId: c.NullOr(c.String),
|
|
446
|
-
ledgerId: c.String,
|
|
447
|
-
preparedExecutionId: c.NullOr(c.String),
|
|
448
|
-
executionId: c.NullOr(c.String),
|
|
449
|
-
runId: c.NullOr(c.String),
|
|
450
|
-
receiptsBound: c.Boolean,
|
|
451
|
-
dispatchAttempts: c.Number.check(c.isInt(), c.isGreaterThanOrEqualTo(0)),
|
|
452
|
-
failureId: c.NullOr(c.String),
|
|
453
|
-
retry: c.Struct({
|
|
454
|
-
attempts: c.Int,
|
|
455
|
-
after: c.Number,
|
|
456
|
-
lastError: c.NullOr(c.String),
|
|
457
|
-
stoppedAt: c.NullOr(c.Number)
|
|
458
|
-
}),
|
|
459
|
-
payload: c.Unknown,
|
|
460
|
-
callerContext: c.Unknown,
|
|
461
|
-
intentIds: c.Array(c.String),
|
|
462
|
-
eviction: c.NullOr(c.Struct({
|
|
463
|
-
executionId: c.String,
|
|
464
|
-
runId: c.String
|
|
465
|
-
}))
|
|
466
|
-
}), Ne = c.decodeUnknownSync(j);
|
|
467
|
-
async function* Pe(e, t, n) {
|
|
468
|
-
let r;
|
|
469
|
-
for (;;) {
|
|
470
|
-
let i = p(h("preparedExecutionId", t), g("dispatchAttempts", 0)), a = await e.query({
|
|
471
|
-
table: A,
|
|
472
|
-
predicate: r === void 0 ? i : p(i, g("id", r)),
|
|
473
|
-
order: [{
|
|
474
|
-
column: "id",
|
|
475
|
-
direction: "asc"
|
|
476
|
-
}],
|
|
477
|
-
take: 100,
|
|
478
|
-
skip: void 0,
|
|
479
|
-
projection: void 0
|
|
480
|
-
});
|
|
481
|
-
if (a.length === 0) return;
|
|
482
|
-
for (let e of a) {
|
|
483
|
-
let i = Ne(e);
|
|
484
|
-
if (i.workflowName !== n || !i.receiptsBound || i.failureId !== null || i.executionId !== null && i.executionId !== t) throw Error("Workflow completion has an inconsistent resident submission owner");
|
|
485
|
-
yield i, r = i.id;
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
var Fe = async (e, t, n) => (await Ie(e, t, n)).map((e) => Ne(e)), Ie = async (e, t, n) => {
|
|
490
|
-
if (!Number.isSafeInteger(t) || t < 1) throw Error("Submission recovery requires a positive page size");
|
|
491
|
-
return e.query({
|
|
492
|
-
table: A,
|
|
493
|
-
predicate: n === void 0 ? p(h("receiptsBound", !0), v("executionId"), v("failureId")) : p(h("receiptsBound", !0), v("executionId"), v("failureId"), g("id", n)),
|
|
494
|
-
order: [{
|
|
495
|
-
column: "id",
|
|
496
|
-
direction: "asc"
|
|
497
|
-
}],
|
|
498
|
-
take: t,
|
|
499
|
-
skip: void 0,
|
|
500
|
-
projection: void 0
|
|
501
|
-
});
|
|
502
|
-
}, M = async (e, t) => {
|
|
503
|
-
let n = await e.query({
|
|
504
|
-
table: A,
|
|
505
|
-
predicate: h("id", t),
|
|
506
|
-
order: [],
|
|
507
|
-
take: 1,
|
|
508
|
-
skip: void 0,
|
|
509
|
-
projection: void 0
|
|
510
|
-
});
|
|
511
|
-
return n[0] === void 0 ? void 0 : c.decodeUnknownSync(j)(n[0]);
|
|
512
|
-
}, Le = async (e, t) => C(e, (e) => Re(e, t)), Re = async (e, t) => {
|
|
513
|
-
if (t.id.length === 0) throw Error("Admission submission requires a stable non-empty identity");
|
|
514
|
-
let n = await e.query({
|
|
515
|
-
table: A,
|
|
516
|
-
predicate: h("id", t.id),
|
|
517
|
-
order: [],
|
|
518
|
-
take: 1,
|
|
519
|
-
skip: void 0,
|
|
520
|
-
projection: void 0
|
|
521
|
-
});
|
|
522
|
-
if (n[0] !== void 0) {
|
|
523
|
-
let e = c.decodeUnknownSync(j)(n[0]);
|
|
524
|
-
if (e.workflowName !== t.control.workflowName || e.tenantId !== t.tenantId) throw Error("Admission submission identity belongs to a different workflow or tenant");
|
|
525
|
-
let r = JSON.parse(JSON.stringify(e.payload) ?? "null"), i = JSON.parse(JSON.stringify(t.encodedPayload) ?? "null");
|
|
526
|
-
if (!ae(r, i)) throw Error("Admission submission identity is already bound to a different payload");
|
|
527
|
-
return {
|
|
528
|
-
kind: "reserved",
|
|
529
|
-
submission: e,
|
|
530
|
-
reused: !0
|
|
531
|
-
};
|
|
532
|
-
}
|
|
533
|
-
let r = ue(t.control, t.keyPayload), i = await St({
|
|
534
|
-
store: e,
|
|
535
|
-
control: t.control,
|
|
536
|
-
keys: r,
|
|
537
|
-
paused: t.paused,
|
|
538
|
-
now: t.now,
|
|
539
|
-
reconsidering: !0
|
|
540
|
-
});
|
|
541
|
-
if (i.kind !== "admit") return {
|
|
542
|
-
kind: "not-admitted",
|
|
543
|
-
decision: i
|
|
544
|
-
};
|
|
545
|
-
let a = await dt({
|
|
546
|
-
store: e,
|
|
547
|
-
control: t.control,
|
|
548
|
-
keys: r,
|
|
549
|
-
outcome: "admitted",
|
|
550
|
-
mode: t.mode,
|
|
551
|
-
reason: i.reason,
|
|
552
|
-
collapsed: t.collapsed,
|
|
553
|
-
waitedMs: t.now - t.firstSeenAt,
|
|
554
|
-
executionId: null,
|
|
555
|
-
runId: null,
|
|
556
|
-
tenantId: t.tenantId,
|
|
557
|
-
now: t.now
|
|
558
|
-
});
|
|
559
|
-
if (a === void 0) throw Error("Admission reservation has no ledger identity");
|
|
560
|
-
return {
|
|
561
|
-
kind: "reserved",
|
|
562
|
-
submission: await ze(e, {
|
|
563
|
-
id: t.id,
|
|
564
|
-
workflowName: t.control.workflowName,
|
|
565
|
-
tenantId: t.tenantId,
|
|
566
|
-
ledgerId: a,
|
|
567
|
-
payload: t.encodedPayload,
|
|
568
|
-
callerContext: t.callerContext,
|
|
569
|
-
intentIds: t.intentIds,
|
|
570
|
-
eviction: i.evict ?? null
|
|
571
|
-
}),
|
|
572
|
-
reused: !1
|
|
573
|
-
};
|
|
574
|
-
}, ze = async (e, t) => {
|
|
575
|
-
if (t.id.length === 0 || t.ledgerId.length === 0) throw Error("Submission requires its reserved admission identity");
|
|
576
|
-
let n = {
|
|
577
|
-
...t,
|
|
578
|
-
callerContext: t.callerContext ?? null,
|
|
579
|
-
intentIds: [...t.intentIds],
|
|
580
|
-
preparedExecutionId: null,
|
|
581
|
-
executionId: null,
|
|
582
|
-
runId: null,
|
|
583
|
-
receiptsBound: !1,
|
|
584
|
-
dispatchAttempts: 0,
|
|
585
|
-
failureId: null,
|
|
586
|
-
retry: {
|
|
587
|
-
attempts: 0,
|
|
588
|
-
after: 0,
|
|
589
|
-
lastError: null,
|
|
590
|
-
stoppedAt: null
|
|
591
|
-
}
|
|
592
|
-
};
|
|
593
|
-
return await e.insert(A, n), n;
|
|
594
|
-
}, Be = async (e, t, n) => C(e, (e) => Ve(e, t, n)), Ve = async (e, t, n) => {
|
|
595
|
-
if (n.executionId.length === 0) throw Error("Engine acknowledgement requires an execution identity");
|
|
596
|
-
let r = await e.query({
|
|
597
|
-
table: A,
|
|
598
|
-
predicate: h("id", t),
|
|
599
|
-
order: [],
|
|
600
|
-
take: 1,
|
|
601
|
-
skip: void 0,
|
|
602
|
-
projection: void 0
|
|
603
|
-
});
|
|
604
|
-
if (r[0] === void 0) throw Error("Cannot acknowledge an unknown admission submission");
|
|
605
|
-
let i = c.decodeUnknownSync(j)(r[0]);
|
|
606
|
-
if (i.failureId !== null) throw Error("Cannot acknowledge a permanently rejected admission submission");
|
|
607
|
-
if (i.preparedExecutionId !== null && i.preparedExecutionId !== n.executionId) throw Error("Engine acknowledgement contradicts the prepared execution identity");
|
|
608
|
-
if (i.executionId !== null && i.executionId !== n.executionId || i.runId !== null && n.runId !== null && i.runId !== n.runId) throw Error("Admission submission already belongs to a different execution or run");
|
|
609
|
-
let a = await Ae(e, i.workflowName, n.executionId), o = i.runId ?? n.runId;
|
|
610
|
-
if (a !== void 0 && o !== null && a.runId !== o) throw Error("Admission acknowledgement belongs to a different resident run");
|
|
611
|
-
let s = {
|
|
612
|
-
executionId: n.executionId,
|
|
613
|
-
runId: o ?? a?.runId ?? null
|
|
614
|
-
}, l = a?.completedAt ?? void 0;
|
|
615
|
-
if (await e.update("_voltro_workflow_admissions", i.ledgerId, {
|
|
616
|
-
...s,
|
|
617
|
-
...l === void 0 ? {} : { releasedAt: l }
|
|
618
|
-
}) === null) throw Error("Admission submission has no lease to acknowledge");
|
|
619
|
-
if (await e.update("_voltro_workflow_submissions", t, s) === null) throw Error("Admission submission disappeared during acknowledgement");
|
|
620
|
-
return {
|
|
621
|
-
...i,
|
|
622
|
-
...s
|
|
623
|
-
};
|
|
624
|
-
}, He = async (e, t, n) => {
|
|
625
|
-
if (n.length === 0) throw Error("Prepared submission requires a non-empty execution identity");
|
|
626
|
-
let r = await M(e, t);
|
|
627
|
-
if (r === void 0) throw Error("Cannot prepare an unknown admission submission");
|
|
628
|
-
if (!r.receiptsBound || r.failureId !== null) throw Error("Cannot prepare an incomplete or terminal admission submission");
|
|
629
|
-
if (r.preparedExecutionId !== null) {
|
|
630
|
-
if (r.executionId !== null && r.executionId !== r.preparedExecutionId) throw Error("Submission acceptance contradicts its prepared identity");
|
|
631
|
-
return r;
|
|
632
|
-
}
|
|
633
|
-
if (r.executionId !== null) throw Error("Cannot prepare an accepted submission without its prepared identity");
|
|
634
|
-
if (r.dispatchAttempts !== 0) throw Error("Cannot choose an execution identity after an unbound dispatch");
|
|
635
|
-
if (r.retry.stoppedAt !== null) throw Error("Cannot prepare a stopped admission submission");
|
|
636
|
-
if (await e.update("_voltro_workflow_submissions", t, { preparedExecutionId: n }) === null) throw Error("Admission submission disappeared while preparing execution");
|
|
637
|
-
return {
|
|
638
|
-
...r,
|
|
639
|
-
preparedExecutionId: n
|
|
640
|
-
};
|
|
641
|
-
}, Ue = async (e, t, n, i, a = !1) => {
|
|
642
|
-
if (a !== !1 && (!Number.isSafeInteger(a) || a < 1)) throw Error("Submission retry limit must be a positive integer or false");
|
|
643
|
-
let o = await M(e, t);
|
|
644
|
-
if (o === void 0) throw Error("Cannot record failure for an unknown submission");
|
|
645
|
-
if (o.executionId !== null || o.failureId !== null || o.retry.stoppedAt !== null) return o;
|
|
646
|
-
let s = o.retry.attempts + 1, c = {
|
|
647
|
-
attempts: s,
|
|
648
|
-
lastError: r(o.workflowName, n),
|
|
649
|
-
after: i + W(s),
|
|
650
|
-
stoppedAt: a !== !1 && s >= a ? i : null
|
|
651
|
-
};
|
|
652
|
-
if (await e.update("_voltro_workflow_submissions", t, { retry: c }) === null) throw Error("Admission submission disappeared while recording failure");
|
|
653
|
-
return {
|
|
654
|
-
...o,
|
|
655
|
-
retry: c
|
|
656
|
-
};
|
|
657
|
-
}, We = async (e, t, n) => {
|
|
658
|
-
let r = await M(e, t);
|
|
659
|
-
if (r === void 0) throw Error("Cannot dispatch an unknown admission submission");
|
|
660
|
-
if (!r.receiptsBound || r.executionId !== null || r.failureId !== null || r.retry.stoppedAt !== null || r.retry.after > n) return null;
|
|
661
|
-
let i = r.dispatchAttempts + 1;
|
|
662
|
-
if (!Number.isSafeInteger(i)) throw Error("Submission dispatch counter exhausted");
|
|
663
|
-
if (await e.update("_voltro_workflow_submissions", t, { dispatchAttempts: i }) === null) throw Error("Admission submission disappeared before dispatch");
|
|
664
|
-
return {
|
|
665
|
-
...r,
|
|
666
|
-
dispatchAttempts: i
|
|
667
|
-
};
|
|
668
|
-
}, Ge = async (e, t, n, r) => {
|
|
669
|
-
if (!Number.isSafeInteger(n) || n < 0) throw Error("Invalid submission dispatch attempt");
|
|
670
|
-
let i = await M(e, t);
|
|
671
|
-
if (i === void 0) throw Error("Cannot reject an unknown admission submission");
|
|
672
|
-
if (i.failureId !== null) {
|
|
673
|
-
let n = await D(e, i.failureId);
|
|
674
|
-
if (n === void 0 || n.sourceKind !== "submission" || n.sourceId !== t || n.workflowName !== i.workflowName || n.tenantId !== i.tenantId) throw Error("Rejected submission has no matching durable failure report");
|
|
675
|
-
return await O(e, n.id, r.now), n;
|
|
676
|
-
}
|
|
677
|
-
if (!i.receiptsBound || i.executionId !== null || i.dispatchAttempts !== n || n > 1) return;
|
|
678
|
-
let a = `wffr_${ie("sha256").update(JSON.stringify(["submission", t])).digest("hex").slice(0, 40)}`, o = await ve(e, {
|
|
679
|
-
id: a,
|
|
680
|
-
sourceKind: "submission",
|
|
681
|
-
sourceId: t,
|
|
682
|
-
workflowName: i.workflowName,
|
|
683
|
-
tenantId: i.tenantId,
|
|
684
|
-
handler: await be(e, t) ? null : r.handler,
|
|
685
|
-
callerContext: i.callerContext,
|
|
686
|
-
report: {
|
|
687
|
-
workflow: i.workflowName,
|
|
688
|
-
payload: i.payload,
|
|
689
|
-
errorTag: "WorkflowPayloadError",
|
|
690
|
-
errorMessage: r.errorMessage,
|
|
691
|
-
reason: "permanent input rejection before engine acceptance",
|
|
692
|
-
failedAt: r.now,
|
|
693
|
-
runId: null,
|
|
694
|
-
executionId: null
|
|
695
|
-
}
|
|
696
|
-
});
|
|
697
|
-
if (await e.update("_voltro_workflow_admissions", i.ledgerId, { releasedAt: new Date(r.now) }) === null) throw Error("Rejected admission submission has no lease");
|
|
698
|
-
if (await e.update("_voltro_workflow_submissions", t, { failureId: a }) === null) throw Error("Admission submission disappeared during rejection");
|
|
699
|
-
return await O(e, o.id, r.now), o;
|
|
700
|
-
}, Ke = async (e, t) => {
|
|
701
|
-
if (t.failureId === null) throw Error("Workflow submission has no rejection marker");
|
|
702
|
-
let n = await D(e, t.failureId);
|
|
703
|
-
if (t.executionId !== null || t.dispatchAttempts > 1 || n === void 0 || n.sourceKind !== "submission" || n.sourceId !== t.id || n.workflowName !== t.workflowName || n.tenantId !== t.tenantId || n.report.executionId !== null || n.report.runId !== null) throw Error("Workflow start rejection has contradictory ownership or execution evidence");
|
|
704
|
-
return n.id;
|
|
705
|
-
}, N = "_voltro_workflow_start_receipts", qe = class extends Error {
|
|
706
|
-
_tag = "WorkflowStartRequestConflictError";
|
|
707
|
-
constructor() {
|
|
708
|
-
super("Workflow start request identity belongs to a different start"), this.name = "WorkflowStartRequestConflictError";
|
|
709
|
-
}
|
|
710
|
-
}, Je = c.Struct({
|
|
711
|
-
id: c.String,
|
|
712
|
-
workflowName: c.String,
|
|
713
|
-
tenantId: c.NullOr(c.String),
|
|
714
|
-
pendingId: c.String,
|
|
715
|
-
submissionId: c.NullOr(c.String),
|
|
716
|
-
terminal: c.NullOr(f),
|
|
717
|
-
requestFingerprint: c.optional(c.NullOr(c.String.pipe(c.check(c.isPattern(/^[a-f0-9]{64}$/)))))
|
|
718
|
-
}).pipe(c.check(c.makeFilter((e) => e.submissionId === null || e.terminal === null, { message: "A start receipt cannot be both submitted and terminal before admission" }))), P = c.decodeUnknownSync(Je), F = async (e, t) => {
|
|
719
|
-
let n = await e.query({
|
|
720
|
-
table: N,
|
|
721
|
-
predicate: h("id", t),
|
|
722
|
-
order: [],
|
|
723
|
-
take: 1,
|
|
724
|
-
skip: void 0,
|
|
725
|
-
projection: void 0
|
|
726
|
-
});
|
|
727
|
-
return n[0] === void 0 ? void 0 : P(n[0]);
|
|
728
|
-
}, Ye = async (e, t) => {
|
|
729
|
-
if (t.id.trim().length === 0 || !/^[a-f0-9]{64}$/.test(t.requestFingerprint)) throw Error("Workflow start request requires an identity and a SHA-256 fingerprint");
|
|
730
|
-
let n = await F(e, t.id);
|
|
731
|
-
if (n !== void 0) {
|
|
732
|
-
if (n.workflowName !== t.workflowName || n.tenantId !== t.tenantId || n.requestFingerprint !== t.requestFingerprint) throw new qe();
|
|
733
|
-
return n;
|
|
734
|
-
}
|
|
735
|
-
}, Xe = async (e, t) => {
|
|
736
|
-
let n = await F(e, t.receiptId);
|
|
737
|
-
if (n === void 0 || n.workflowName !== t.workflowName || n.tenantId !== t.tenantId) throw Error("Workflow start receipt is missing or belongs to another workflow or tenant");
|
|
738
|
-
if (n.terminal !== null) {
|
|
739
|
-
if (n.terminal.kind === "abandoned") {
|
|
740
|
-
let t = await D(e, n.terminal.failureId);
|
|
741
|
-
if (t === void 0 || t.workflowName !== n.workflowName || t.tenantId !== n.tenantId || t.sourceKind !== "intent" || t.report.executionId !== null || t.report.runId !== null) throw Error("Abandoned workflow receipt has no matching failure report");
|
|
742
|
-
}
|
|
743
|
-
return {
|
|
744
|
-
kind: "terminal",
|
|
745
|
-
outcome: n.terminal
|
|
746
|
-
};
|
|
747
|
-
}
|
|
748
|
-
if (n.submissionId === null) {
|
|
749
|
-
let t = await e.query({
|
|
750
|
-
table: I,
|
|
751
|
-
predicate: h("id", n.pendingId),
|
|
752
|
-
order: [],
|
|
753
|
-
take: 1,
|
|
754
|
-
skip: void 0,
|
|
755
|
-
projection: void 0
|
|
756
|
-
});
|
|
757
|
-
if (t[0] === void 0) throw Error("Workflow receipt has no pending input or submission");
|
|
758
|
-
let r = H(t[0]);
|
|
759
|
-
if (r.workflowName !== n.workflowName || r.tenantId !== n.tenantId) throw Error("Workflow receipt pending input belongs to another workflow or tenant");
|
|
760
|
-
if (r.deadLetteredAt !== void 0) throw Error("Workflow receipt input is dead-lettered; reconciliation required");
|
|
761
|
-
return { kind: "pending" };
|
|
762
|
-
}
|
|
763
|
-
let r = await M(e, n.submissionId);
|
|
764
|
-
if (r === void 0 || !r.receiptsBound || r.workflowName !== n.workflowName || r.tenantId !== n.tenantId || !r.intentIds.includes(n.pendingId)) throw Error("Workflow receipt has no matching admission submission");
|
|
765
|
-
if (r.failureId !== null) return {
|
|
766
|
-
kind: "rejected",
|
|
767
|
-
failureId: await Ke(e, r)
|
|
768
|
-
};
|
|
769
|
-
if (r.executionId === null) {
|
|
770
|
-
if (r.retry.stoppedAt !== null) throw Error("Workflow start acceptance is unresolved; reconciliation required");
|
|
771
|
-
return { kind: "pending" };
|
|
772
|
-
}
|
|
773
|
-
if (r.executionId.length === 0 || r.executionId !== r.preparedExecutionId) throw Error("Workflow start acknowledgement contradicts its prepared identity");
|
|
774
|
-
return {
|
|
775
|
-
kind: "accepted",
|
|
776
|
-
executionId: r.executionId
|
|
777
|
-
};
|
|
778
|
-
}, Ze = async (e, t) => {
|
|
779
|
-
if (t.id.length === 0 || t.id === t.pendingId) throw Error("Workflow start receipt requires an identity distinct from its queue slot");
|
|
780
|
-
if (t.requestFingerprint != null && !/^[a-f0-9]{64}$/.test(t.requestFingerprint)) throw Error("Workflow start request requires a SHA-256 fingerprint");
|
|
781
|
-
let n = P((await e.insertIgnoreWithOutcome(N, {
|
|
782
|
-
...t,
|
|
783
|
-
requestFingerprint: t.requestFingerprint ?? null,
|
|
784
|
-
submissionId: null,
|
|
785
|
-
terminal: null
|
|
786
|
-
}, { conflictColumns: ["id"] })).row);
|
|
787
|
-
if (n.workflowName !== t.workflowName || n.tenantId !== t.tenantId || n.pendingId !== t.pendingId || (n.requestFingerprint ?? null) !== (t.requestFingerprint ?? null)) throw Error("Workflow start receipt identity belongs to a different start");
|
|
788
|
-
return n;
|
|
789
|
-
}, Qe = async (e, t) => {
|
|
790
|
-
let n = await M(e, t);
|
|
791
|
-
if (n === void 0) throw Error("Cannot bind receipts to an unknown admission submission");
|
|
792
|
-
if (n.receiptsBound) return 0;
|
|
793
|
-
let r = 0;
|
|
794
|
-
for (let t of new Set(n.intentIds)) for (;;) {
|
|
795
|
-
let i = await e.query({
|
|
796
|
-
table: N,
|
|
797
|
-
predicate: p(h("pendingId", t), v("submissionId"), v("terminal")),
|
|
798
|
-
order: [{
|
|
799
|
-
column: "id",
|
|
800
|
-
direction: "asc"
|
|
801
|
-
}],
|
|
802
|
-
take: 100,
|
|
803
|
-
skip: void 0,
|
|
804
|
-
projection: void 0
|
|
805
|
-
});
|
|
806
|
-
if (i.length === 0) break;
|
|
807
|
-
for (let t of i) {
|
|
808
|
-
let i = P(t);
|
|
809
|
-
if (i.workflowName !== n.workflowName || i.tenantId !== n.tenantId) throw Error("Pending receipt belongs to a different workflow or tenant");
|
|
810
|
-
if (await e.update("_voltro_workflow_start_receipts", i.id, { submissionId: n.id }) === null) throw Error("Workflow start receipt disappeared during queue transfer");
|
|
811
|
-
r++;
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
if (await e.update("_voltro_workflow_submissions", t, { receiptsBound: !0 }) === null) throw Error("Admission submission disappeared during receipt binding");
|
|
815
|
-
return r;
|
|
816
|
-
}, $e = async (e, t) => {
|
|
817
|
-
let n = c.decodeUnknownSync(f)(t.terminal);
|
|
818
|
-
for (;;) {
|
|
819
|
-
let r = await e.query({
|
|
820
|
-
table: N,
|
|
821
|
-
predicate: p(h("pendingId", t.pendingId), v("submissionId"), v("terminal")),
|
|
822
|
-
order: [{
|
|
823
|
-
column: "id",
|
|
824
|
-
direction: "asc"
|
|
825
|
-
}],
|
|
826
|
-
take: 100,
|
|
827
|
-
skip: void 0,
|
|
828
|
-
projection: void 0
|
|
829
|
-
});
|
|
830
|
-
if (r.length === 0) return;
|
|
831
|
-
for (let i of r) {
|
|
832
|
-
let r = P(i);
|
|
833
|
-
if (r.workflowName !== t.workflowName || r.tenantId !== t.tenantId) throw Error("Terminal receipt belongs to a different workflow or tenant");
|
|
834
|
-
if (await e.update("_voltro_workflow_start_receipts", r.id, { terminal: n }) === null) throw Error("Start receipt disappeared while recording its terminal outcome");
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
}, I = "_voltro_workflow_pending", L = "_voltro_workflow_admissions", R = "_voltro_workflow_pauses", z = (e, t, n) => e.encodeWorkflowPayload === void 0 ? n : e.encodeWorkflowPayload(t, n), et = (e, t, n) => e.decodeWorkflowPayload === void 0 ? n : e.decodeWorkflowPayload(t, n), tt = 864e5, nt = (e, t, n) => `wfp_${ie("sha256").update(`${e}\u0000${t}\u0000${n}`).digest("hex").slice(0, 40)}`, B = (e) => {
|
|
838
|
-
if (e instanceof Date) return e.getTime();
|
|
839
|
-
if (typeof e == "number") return e;
|
|
840
|
-
let t = Date.parse(String(e));
|
|
841
|
-
return Number.isNaN(t) ? 0 : t;
|
|
842
|
-
}, V = (e, t) => {
|
|
843
|
-
let n = typeof e == "number" ? e : Number(e);
|
|
844
|
-
return Number.isFinite(n) ? Math.trunc(n) : t;
|
|
845
|
-
}, H = (e) => ({
|
|
846
|
-
id: String(e.id),
|
|
847
|
-
tenantId: e.tenantId === null || e.tenantId === void 0 ? null : String(e.tenantId),
|
|
848
|
-
workflowName: String(e.workflowName),
|
|
849
|
-
controlKey: String(e.controlKey ?? ""),
|
|
850
|
-
mode: String(e.mode),
|
|
851
|
-
payload: e.payload,
|
|
852
|
-
callerContext: e.callerContext ?? null,
|
|
853
|
-
queuedAppVersion: e.queuedAppVersion === null || e.queuedAppVersion === void 0 ? null : String(e.queuedAppVersion),
|
|
854
|
-
queuedSchemaFingerprint: e.queuedSchemaFingerprint === null || e.queuedSchemaFingerprint === void 0 ? null : String(e.queuedSchemaFingerprint),
|
|
855
|
-
priority: V(e.priority, 0),
|
|
856
|
-
dueAt: B(e.dueAt),
|
|
857
|
-
deadlineAt: e.deadlineAt === null || e.deadlineAt === void 0 ? void 0 : B(e.deadlineAt),
|
|
858
|
-
collapsed: V(e.collapsed, 1),
|
|
859
|
-
firstSeenAt: B(e.firstSeenAt),
|
|
860
|
-
attempts: V(e.attempts, 0),
|
|
861
|
-
lastError: e.lastError === null || e.lastError === void 0 ? null : a(String(e.lastError)),
|
|
862
|
-
deadLetteredAt: e.deadLetteredAt === null || e.deadLetteredAt === void 0 ? void 0 : B(e.deadLetteredAt)
|
|
863
|
-
}), U = (e, t, n, r) => ({
|
|
864
|
-
table: e,
|
|
865
|
-
predicate: t,
|
|
866
|
-
order: n,
|
|
867
|
-
take: r,
|
|
868
|
-
skip: void 0,
|
|
869
|
-
projection: void 0
|
|
870
|
-
}), rt = async (e) => {
|
|
871
|
-
let t = await e.query(U(R, void 0, [], 1e3));
|
|
872
|
-
return new Set(t.map((e) => String(e.id)));
|
|
873
|
-
}, it = async (e, t, n, r) => {
|
|
874
|
-
await e.upsert(R, {
|
|
875
|
-
id: t,
|
|
876
|
-
pausedAt: /* @__PURE__ */ new Date(),
|
|
877
|
-
pausedBy: n,
|
|
878
|
-
reason: r
|
|
879
|
-
}, {
|
|
880
|
-
conflictColumns: ["id"],
|
|
881
|
-
update: [
|
|
882
|
-
"pausedAt",
|
|
883
|
-
"pausedBy",
|
|
884
|
-
"reason"
|
|
885
|
-
]
|
|
886
|
-
});
|
|
887
|
-
}, at = async (e, t) => e.delete(R, t), ot = async (e) => {
|
|
888
|
-
let { store: t, control: n, keys: r, now: i } = e, a = { paused: e.paused }, o = [];
|
|
889
|
-
n.debounce !== void 0 && r.debounceKey !== void 0 && o.push((async () => {
|
|
890
|
-
let e = (await t.query(U(I, p(h("workflowName", n.workflowName), h("controlKey", r.debounceKey), h("mode", "debounce")), [], 1)))[0];
|
|
891
|
-
if (e === void 0) return;
|
|
892
|
-
let i = e.deadlineAt === null || e.deadlineAt === void 0 ? void 0 : B(e.deadlineAt);
|
|
893
|
-
a.debouncePending = {
|
|
894
|
-
firstSeenAt: B(e.firstSeenAt),
|
|
895
|
-
collapsed: V(e.collapsed, 1),
|
|
896
|
-
...i === void 0 ? {} : { deadlineAt: i }
|
|
897
|
-
};
|
|
898
|
-
})()), n.batch !== void 0 && r.batchKey !== void 0 && o.push((async () => {
|
|
899
|
-
let e = await t.query(U(I, p(h("workflowName", n.workflowName), h("controlKey", r.batchKey), h("mode", "batch")), [{
|
|
900
|
-
column: "firstSeenAt",
|
|
901
|
-
direction: "asc"
|
|
902
|
-
}], n.batch.maxSize + 1));
|
|
903
|
-
e.length !== 0 && (a.batchPending = {
|
|
904
|
-
count: e.length,
|
|
905
|
-
firstSeenAt: B(e[0].firstSeenAt)
|
|
906
|
-
});
|
|
907
|
-
})()), n.singleton !== void 0 && r.singletonKey !== void 0 && o.push((async () => {
|
|
908
|
-
let e = await st(t, n.workflowName, r.singletonKey, i);
|
|
909
|
-
e === "unacknowledged" ? a.singletonUnacknowledged = !0 : e !== void 0 && (a.singletonHolder = e);
|
|
910
|
-
})()), n.concurrency !== void 0 && r.concurrencyKey !== void 0 && o.push((async () => {
|
|
911
|
-
let e = n.concurrency.pool === void 0 ? [h("workflowName", n.workflowName)] : [], o = await t.query(U(L, p(...e, h("concurrencyKey", r.concurrencyKey), v("releasedAt"), te(v("executionId"), g("expiresAt", new Date(i)))), [], n.concurrency.limit));
|
|
912
|
-
a.inFlight = o.length;
|
|
913
|
-
})());
|
|
914
|
-
let s = n.rateLimit ?? n.throttle, c = r.rateLimitKey ?? r.throttleKey;
|
|
915
|
-
return s !== void 0 && c !== void 0 && o.push((async () => {
|
|
916
|
-
let e = await t.query(U(L, p(h("workflowName", n.workflowName), h("rateKey", c), h("outcome", "admitted"), g("admittedAt", new Date(i - s.periodMs))), [{
|
|
917
|
-
column: "admittedAt",
|
|
918
|
-
direction: "desc"
|
|
919
|
-
}], s.limit));
|
|
920
|
-
a.recentAdmissions = e.map((e) => B(e.admittedAt));
|
|
921
|
-
})()), await Promise.all(o), a;
|
|
922
|
-
}, st = async (e, t, n, r) => {
|
|
923
|
-
if ((await e.query(U("_voltro_workflow_admissions", p(h("workflowName", t), h("singletonKey", n), v("releasedAt"), v("executionId")), [], 1))).length > 0) return "unacknowledged";
|
|
924
|
-
let i = (await e.query(U(L, p(h("workflowName", t), h("singletonKey", n), v("releasedAt"), g("expiresAt", new Date(r))), [{
|
|
925
|
-
column: "admittedAt",
|
|
926
|
-
direction: "desc"
|
|
927
|
-
}], 1)))[0];
|
|
928
|
-
if (i === void 0) return;
|
|
929
|
-
let a = i.executionId;
|
|
930
|
-
if (a != null) return {
|
|
931
|
-
executionId: String(a),
|
|
932
|
-
runId: i.runId === null || i.runId === void 0 ? "" : String(i.runId),
|
|
933
|
-
admittedAt: B(i.admittedAt)
|
|
934
|
-
};
|
|
935
|
-
}, ct = async (e) => {
|
|
936
|
-
let { store: t, control: n, decision: r, now: i } = e, a = ut(r.mode, r.keys);
|
|
937
|
-
if (r.collapse === "hold") {
|
|
938
|
-
let o = e.existingId ?? nt(n.workflowName, r.mode, a);
|
|
939
|
-
return await t.update(I, o, {
|
|
940
|
-
dueAt: new Date(r.dueAt),
|
|
941
|
-
updatedAt: new Date(i)
|
|
942
|
-
}), o;
|
|
943
|
-
}
|
|
944
|
-
if (r.collapse === "replace") {
|
|
945
|
-
let o = nt(n.workflowName, r.mode, a);
|
|
946
|
-
return await $e(t, {
|
|
947
|
-
pendingId: o,
|
|
948
|
-
workflowName: n.workflowName,
|
|
949
|
-
tenantId: e.tenantId,
|
|
950
|
-
terminal: {
|
|
951
|
-
kind: "superseded",
|
|
952
|
-
at: i
|
|
953
|
-
}
|
|
954
|
-
}), await t.upsert(I, {
|
|
955
|
-
id: o,
|
|
956
|
-
tenantId: e.tenantId,
|
|
957
|
-
workflowName: n.workflowName,
|
|
958
|
-
controlKey: a,
|
|
959
|
-
mode: r.mode,
|
|
960
|
-
payload: z(t, n.workflowName, e.payload),
|
|
961
|
-
callerContext: e.callerContext ?? null,
|
|
962
|
-
queuedAppVersion: e.queuedAppVersion ?? null,
|
|
963
|
-
queuedSchemaFingerprint: e.queuedSchemaFingerprint ?? null,
|
|
964
|
-
priority: r.keys.priority,
|
|
965
|
-
dueAt: new Date(r.dueAt),
|
|
966
|
-
deadlineAt: r.deadlineAt === void 0 ? null : new Date(r.deadlineAt),
|
|
967
|
-
collapsed: 1,
|
|
968
|
-
firstSeenAt: new Date(i),
|
|
969
|
-
updatedAt: new Date(i),
|
|
970
|
-
attempts: 0,
|
|
971
|
-
lastError: null,
|
|
972
|
-
deadLetteredAt: null
|
|
973
|
-
}, {
|
|
974
|
-
conflictColumns: ["id"],
|
|
975
|
-
update: (a) => ({
|
|
976
|
-
payload: z(t, n.workflowName, e.payload),
|
|
977
|
-
callerContext: e.callerContext ?? null,
|
|
978
|
-
queuedAppVersion: e.queuedAppVersion ?? null,
|
|
979
|
-
queuedSchemaFingerprint: e.queuedSchemaFingerprint ?? null,
|
|
980
|
-
priority: r.keys.priority,
|
|
981
|
-
dueAt: new Date(r.dueAt),
|
|
982
|
-
deadlineAt: r.deadlineAt === void 0 ? a.deadlineAt ?? null : new Date(r.deadlineAt),
|
|
983
|
-
collapsed: V(a.collapsed, 1) + 1,
|
|
984
|
-
updatedAt: new Date(i),
|
|
985
|
-
attempts: 0,
|
|
986
|
-
lastError: null,
|
|
987
|
-
deadLetteredAt: null
|
|
988
|
-
})
|
|
989
|
-
}), o;
|
|
990
|
-
}
|
|
991
|
-
let o = await t.insert(I, {
|
|
992
|
-
id: `wfpi_${x()}`,
|
|
993
|
-
tenantId: e.tenantId,
|
|
994
|
-
workflowName: n.workflowName,
|
|
995
|
-
controlKey: a,
|
|
996
|
-
mode: r.mode,
|
|
997
|
-
payload: z(t, n.workflowName, e.payload),
|
|
998
|
-
callerContext: e.callerContext ?? null,
|
|
999
|
-
queuedAppVersion: e.queuedAppVersion ?? null,
|
|
1000
|
-
queuedSchemaFingerprint: e.queuedSchemaFingerprint ?? null,
|
|
1001
|
-
priority: r.keys.priority,
|
|
1002
|
-
dueAt: new Date(r.dueAt),
|
|
1003
|
-
deadlineAt: r.deadlineAt === void 0 ? null : new Date(r.deadlineAt),
|
|
1004
|
-
collapsed: 1,
|
|
1005
|
-
firstSeenAt: new Date(i),
|
|
1006
|
-
updatedAt: new Date(i),
|
|
1007
|
-
attempts: 0,
|
|
1008
|
-
lastError: null,
|
|
1009
|
-
deadLetteredAt: null
|
|
1010
|
-
});
|
|
1011
|
-
return String(o.id);
|
|
1012
|
-
}, lt = async (e) => {
|
|
1013
|
-
let t = await e.store.insert(I, {
|
|
1014
|
-
id: `wfpi_${x()}`,
|
|
1015
|
-
tenantId: e.tenantId,
|
|
1016
|
-
workflowName: e.workflowName,
|
|
1017
|
-
controlKey: "",
|
|
1018
|
-
mode: "delayed",
|
|
1019
|
-
payload: z(e.store, e.workflowName, e.payload),
|
|
1020
|
-
callerContext: e.callerContext ?? null,
|
|
1021
|
-
queuedAppVersion: e.queuedAppVersion ?? null,
|
|
1022
|
-
queuedSchemaFingerprint: e.queuedSchemaFingerprint ?? null,
|
|
1023
|
-
priority: 0,
|
|
1024
|
-
dueAt: new Date(e.at),
|
|
1025
|
-
deadlineAt: null,
|
|
1026
|
-
collapsed: 1,
|
|
1027
|
-
firstSeenAt: new Date(e.now),
|
|
1028
|
-
updatedAt: new Date(e.now),
|
|
1029
|
-
attempts: 0,
|
|
1030
|
-
lastError: null,
|
|
1031
|
-
deadLetteredAt: null
|
|
1032
|
-
});
|
|
1033
|
-
return {
|
|
1034
|
-
intentId: String(t.id),
|
|
1035
|
-
dueAt: e.at
|
|
1036
|
-
};
|
|
1037
|
-
}, ut = (e, t) => {
|
|
1038
|
-
switch (e) {
|
|
1039
|
-
case "debounce": return t.debounceKey ?? "";
|
|
1040
|
-
case "batch": return t.batchKey ?? "";
|
|
1041
|
-
case "throttle": return t.throttleKey ?? "";
|
|
1042
|
-
case "concurrency": return t.concurrencyKey ?? "";
|
|
1043
|
-
case "singleton": return t.singletonKey ?? "";
|
|
1044
|
-
default: return "";
|
|
1045
|
-
}
|
|
1046
|
-
}, dt = async (e) => {
|
|
1047
|
-
let { control: t, keys: n, now: r } = e, i = t.timeouts?.finishMs ?? 864e5, a = await e.store.insert(L, {
|
|
1048
|
-
id: `wfad_${x()}`,
|
|
1049
|
-
tenantId: e.tenantId,
|
|
1050
|
-
workflowName: t.workflowName,
|
|
1051
|
-
outcome: e.outcome,
|
|
1052
|
-
mode: e.mode,
|
|
1053
|
-
reason: e.reason,
|
|
1054
|
-
collapsed: e.collapsed,
|
|
1055
|
-
waitedMs: e.waitedMs,
|
|
1056
|
-
executionId: e.executionId,
|
|
1057
|
-
runId: e.runId,
|
|
1058
|
-
singletonKey: n.singletonKey ?? null,
|
|
1059
|
-
concurrencyKey: n.concurrencyKey ?? null,
|
|
1060
|
-
concurrencyReservation: t.concurrency === void 0 ? null : {
|
|
1061
|
-
pool: t.concurrency.pool ?? null,
|
|
1062
|
-
key: n.concurrencyKey ?? null,
|
|
1063
|
-
limit: t.concurrency.limit
|
|
1064
|
-
},
|
|
1065
|
-
rateKey: n.rateLimitKey ?? n.throttleKey ?? null,
|
|
1066
|
-
admittedAt: new Date(r),
|
|
1067
|
-
expiresAt: e.outcome === "admitted" ? new Date(r + i) : null,
|
|
1068
|
-
releasedAt: e.outcome === "admitted" ? null : new Date(r)
|
|
1069
|
-
});
|
|
1070
|
-
return String(a.id);
|
|
1071
|
-
}, ft = async (e, t, n) => {
|
|
1072
|
-
let r = !1;
|
|
1073
|
-
for (;;) {
|
|
1074
|
-
let i = await e.query(U(L, p(h("executionId", t), h("outcome", "admitted"), v("releasedAt")), [], 10));
|
|
1075
|
-
if (i.length === 0) return r;
|
|
1076
|
-
for (let t of i) if (await e.update("_voltro_workflow_admissions", String(t.id), { releasedAt: new Date(n) }) === null) throw Error("Admission lease disappeared during release");
|
|
1077
|
-
r = !0;
|
|
1078
|
-
}
|
|
1079
|
-
}, pt = async (e, t, n) => (await mt(e, t, n)).due, mt = async (e, t, n) => {
|
|
1080
|
-
let r = (await e.query(U(I, v("deadLetteredAt"), [{
|
|
1081
|
-
column: "priority",
|
|
1082
|
-
direction: "desc"
|
|
1083
|
-
}, {
|
|
1084
|
-
column: "firstSeenAt",
|
|
1085
|
-
direction: "asc"
|
|
1086
|
-
}], n))).map(H), i;
|
|
1087
|
-
for (let e of r) e.dueAt <= t || (i === void 0 || e.dueAt < i) && (i = e.dueAt);
|
|
1088
|
-
return {
|
|
1089
|
-
due: r.filter((e) => e.dueAt <= t).sort(ge),
|
|
1090
|
-
nextDueAt: i
|
|
1091
|
-
};
|
|
1092
|
-
}, ht = async (e, t) => (await e.query(U(I, void 0, [{
|
|
1093
|
-
column: "firstSeenAt",
|
|
1094
|
-
direction: "asc"
|
|
1095
|
-
}], t))).map(H), gt = async (e, t) => e.delete(I, t), _t = async (e, t, n, r) => C(e, (e) => vt(e, t, n, r)), vt = async (e, t, n, r) => {
|
|
1096
|
-
let i = (await e.query(U(I, h("id", t), [], 1)))[0];
|
|
1097
|
-
if (i === void 0) return !1;
|
|
1098
|
-
let a = H(i);
|
|
1099
|
-
if (await e.insert(L, {
|
|
1100
|
-
id: `wfa_${x()}`,
|
|
1101
|
-
tenantId: a.tenantId,
|
|
1102
|
-
workflowName: a.workflowName,
|
|
1103
|
-
outcome: "discarded",
|
|
1104
|
-
mode: a.mode,
|
|
1105
|
-
reason: n,
|
|
1106
|
-
collapsed: a.collapsed,
|
|
1107
|
-
waitedMs: Math.max(0, r - a.firstSeenAt),
|
|
1108
|
-
executionId: null,
|
|
1109
|
-
runId: null,
|
|
1110
|
-
singletonKey: null,
|
|
1111
|
-
concurrencyKey: a.controlKey === "" ? null : a.controlKey,
|
|
1112
|
-
rateKey: null,
|
|
1113
|
-
admittedAt: new Date(r),
|
|
1114
|
-
expiresAt: null,
|
|
1115
|
-
releasedAt: new Date(r)
|
|
1116
|
-
}), await $e(e, {
|
|
1117
|
-
pendingId: t,
|
|
1118
|
-
workflowName: a.workflowName,
|
|
1119
|
-
tenantId: a.tenantId,
|
|
1120
|
-
terminal: {
|
|
1121
|
-
kind: "cancelled",
|
|
1122
|
-
at: r
|
|
1123
|
-
}
|
|
1124
|
-
}), !await e.delete("_voltro_workflow_pending", t)) throw Error("Pending intent disappeared during discard");
|
|
1125
|
-
return !0;
|
|
1126
|
-
}, W = (e, t = Math.random) => {
|
|
1127
|
-
let n = Math.min(1e3 * 2 ** Math.max(0, e - 1), 3e5);
|
|
1128
|
-
return Math.round(n / 2 + t() * (n / 2));
|
|
1129
|
-
}, yt = async (e, t, n, i) => {
|
|
1130
|
-
let a = t.attempts + 1;
|
|
1131
|
-
await e.update(I, t.id, {
|
|
1132
|
-
attempts: a,
|
|
1133
|
-
lastError: r(t.workflowName, n.slice(0, 500)),
|
|
1134
|
-
dueAt: new Date(i + W(a)),
|
|
1135
|
-
updatedAt: new Date(i)
|
|
1136
|
-
});
|
|
1137
|
-
}, bt = async (e, t, n, i) => await e.update(I, t.id, {
|
|
1138
|
-
attempts: t.attempts + 1,
|
|
1139
|
-
lastError: r(t.workflowName, n.slice(0, 500)),
|
|
1140
|
-
deadLetteredAt: new Date(i),
|
|
1141
|
-
updatedAt: new Date(i)
|
|
1142
|
-
}) !== null, xt = async (e, t, n) => {
|
|
1143
|
-
let r = (await e.query(U(I, h("id", t), [], 1)))[0];
|
|
1144
|
-
return r === void 0 || r.deadLetteredAt === null || r.deadLetteredAt === void 0 ? !1 : await e.update(I, t, {
|
|
1145
|
-
attempts: 0,
|
|
1146
|
-
lastError: null,
|
|
1147
|
-
deadLetteredAt: null,
|
|
1148
|
-
dueAt: new Date(n),
|
|
1149
|
-
updatedAt: new Date(n)
|
|
1150
|
-
}) !== null;
|
|
1151
|
-
}, St = async (e) => {
|
|
1152
|
-
let t = await ot({
|
|
1153
|
-
store: e.store,
|
|
1154
|
-
control: e.control,
|
|
1155
|
-
keys: e.keys,
|
|
1156
|
-
now: e.now,
|
|
1157
|
-
paused: e.paused
|
|
1158
|
-
});
|
|
1159
|
-
return fe({
|
|
1160
|
-
control: e.control,
|
|
1161
|
-
keys: e.keys,
|
|
1162
|
-
state: t,
|
|
1163
|
-
now: e.now,
|
|
1164
|
-
reconsidering: e.reconsidering
|
|
1165
|
-
});
|
|
1166
|
-
}, Ct = async (e, t, n = 1e3) => {
|
|
1167
|
-
let r = await e.query(U(L, void 0, [{
|
|
1168
|
-
column: "admittedAt",
|
|
1169
|
-
direction: "asc"
|
|
1170
|
-
}], n)), i = t.getTime(), a = r.filter((e) => e.releasedAt != null && B(e.admittedAt) < i);
|
|
1171
|
-
return await Promise.all(a.map((t) => e.delete(L, String(t.id)))), a.length;
|
|
1172
|
-
}, G = "_voltro_workflow_control_requests", K = c.String.pipe(c.check(c.isMinLength(1))), wt = c.Struct({
|
|
1173
|
-
kind: c.Literals(["confirmed", "already-terminal"]),
|
|
1174
|
-
status: c.Literals([
|
|
1175
|
-
"succeeded",
|
|
1176
|
-
"failed",
|
|
1177
|
-
"cancelled"
|
|
1178
|
-
]),
|
|
1179
|
-
completedAt: c.Number.pipe(c.check(c.isFinite())),
|
|
1180
|
-
output: c.Unknown,
|
|
1181
|
-
errorTag: c.NullOr(c.String),
|
|
1182
|
-
errorMessage: c.NullOr(c.String)
|
|
1183
|
-
}), Tt = c.Struct({
|
|
1184
|
-
kind: c.Literal("confirmed"),
|
|
1185
|
-
status: c.Literal("running"),
|
|
1186
|
-
enteredAt: c.Number.pipe(c.check(c.isFinite())),
|
|
1187
|
-
generation: K
|
|
1188
|
-
}), Et = c.Union([wt, Tt]), Dt = c.Struct({
|
|
1189
|
-
reason: c.NonEmptyString,
|
|
1190
|
-
detail: c.optional(c.Record(c.String, c.Unknown))
|
|
1191
|
-
}), Ot = c.Struct({ tenantId: c.NullOr(c.String) }), q = c.Struct({
|
|
1192
|
-
requestId: c.String.pipe(c.check(c.isPattern(/^[1-9]\d*$/))),
|
|
1193
|
-
replyId: c.String.pipe(c.check(c.isPattern(/^[1-9]\d*$/))),
|
|
1194
|
-
restartToken: c.NullOr(c.NonEmptyString)
|
|
1195
|
-
}), kt = c.Struct({
|
|
1196
|
-
id: K,
|
|
1197
|
-
runId: K,
|
|
1198
|
-
workflowName: K,
|
|
1199
|
-
executionId: K,
|
|
1200
|
-
generation: K,
|
|
1201
|
-
operation: c.Literals([
|
|
1202
|
-
"cancel",
|
|
1203
|
-
"terminate",
|
|
1204
|
-
"resume"
|
|
1205
|
-
]),
|
|
1206
|
-
requestedAt: c.Number.pipe(c.check(c.isFinite())),
|
|
1207
|
-
owner: c.NullOr(Ot),
|
|
1208
|
-
cause: c.optional(c.NullOr(Dt)),
|
|
1209
|
-
dispatchAttempts: c.Number.pipe(c.check(c.isInt()), c.check(c.isGreaterThanOrEqualTo(0))),
|
|
1210
|
-
resumeJournal: c.NullOr(q),
|
|
1211
|
-
result: c.NullOr(Et)
|
|
1212
|
-
}), At = c.Struct({
|
|
1213
|
-
...kt.fields,
|
|
1214
|
-
requestedAt: c.Date
|
|
1215
|
-
}), J = (e) => {
|
|
1216
|
-
let t = c.decodeUnknownSync(At)(e);
|
|
1217
|
-
return c.decodeUnknownSync(kt)({
|
|
1218
|
-
...t,
|
|
1219
|
-
requestedAt: t.requestedAt.getTime()
|
|
1220
|
-
});
|
|
1221
|
-
}, jt = async (e, t, n, r) => {
|
|
1222
|
-
if (await e.update("_voltro_workflow_control_requests", t.id, { result: n }) === null) throw Error("Workflow control request disappeared during settlement");
|
|
1223
|
-
await e.insert("_voltro_workflow_run_events", {
|
|
1224
|
-
id: m("wfev", JSON.stringify(["control-settled", t.id])),
|
|
1225
|
-
runId: t.runId,
|
|
1226
|
-
eventType: "control-settled",
|
|
1227
|
-
occurredAt: new Date(r),
|
|
1228
|
-
stepName: null,
|
|
1229
|
-
attempt: null,
|
|
1230
|
-
payload: {
|
|
1231
|
-
requestId: t.id,
|
|
1232
|
-
operation: t.operation,
|
|
1233
|
-
workflowName: t.workflowName,
|
|
1234
|
-
executionId: t.executionId,
|
|
1235
|
-
generation: t.generation,
|
|
1236
|
-
cause: t.cause ?? null,
|
|
1237
|
-
kind: n.kind,
|
|
1238
|
-
status: n.status,
|
|
1239
|
-
..."generation" in n ? { enteredGeneration: n.generation } : {}
|
|
1240
|
-
}
|
|
1241
|
-
});
|
|
1242
|
-
}, Mt = async (e, t) => {
|
|
1243
|
-
let n = [], r;
|
|
1244
|
-
for (;;) {
|
|
1245
|
-
let i = await e({
|
|
1246
|
-
table: G,
|
|
1247
|
-
predicate: p(h("runId", t.runId), h("workflowName", t.workflowName), h("executionId", t.executionId), h("generation", t.generation), te(h("operation", "cancel"), h("operation", "terminate")), ...r === void 0 ? [] : [g("id", r)]),
|
|
1248
|
-
order: [{
|
|
1249
|
-
column: "id",
|
|
1250
|
-
direction: "asc"
|
|
1251
|
-
}],
|
|
1252
|
-
take: 100,
|
|
1253
|
-
skip: void 0,
|
|
1254
|
-
projection: void 0
|
|
1255
|
-
});
|
|
1256
|
-
for (let e of i) {
|
|
1257
|
-
let t = J(e);
|
|
1258
|
-
t.result === null && n.push(t);
|
|
1259
|
-
}
|
|
1260
|
-
if (i.length < 100) return n;
|
|
1261
|
-
r = J(i[i.length - 1]).id;
|
|
1262
|
-
}
|
|
1263
|
-
}, Nt = async (e, t) => (await Mt(e, t)).length > 0, Pt = (e, t) => Nt((t) => e.query({
|
|
1264
|
-
...t,
|
|
1265
|
-
lock: "update"
|
|
1266
|
-
}), t), Ft = {
|
|
1267
|
-
source: "flow-control",
|
|
1268
|
-
timeout: "finish"
|
|
1269
|
-
}, It = c.Struct({
|
|
1270
|
-
reason: c.NonEmptyString,
|
|
1271
|
-
detail: c.Struct({
|
|
1272
|
-
source: c.Literal("flow-control"),
|
|
1273
|
-
timeout: c.Literal("finish"),
|
|
1274
|
-
onFailure: c.NullOr(c.NonEmptyString)
|
|
1275
|
-
})
|
|
1276
|
-
}), Lt = (e) => {
|
|
1277
|
-
let t = c.decodeUnknownOption(It)(e.cause);
|
|
1278
|
-
return t._tag === "Some" ? t.value : void 0;
|
|
1279
|
-
}, Y = async (e, t) => {
|
|
1280
|
-
let [n] = await e.query({
|
|
1281
|
-
table: G,
|
|
1282
|
-
predicate: h("id", t),
|
|
1283
|
-
lock: "update",
|
|
1284
|
-
order: [],
|
|
1285
|
-
take: 1,
|
|
1286
|
-
skip: void 0,
|
|
1287
|
-
projection: void 0
|
|
1288
|
-
});
|
|
1289
|
-
if (n !== void 0) return J(n);
|
|
1290
|
-
}, Rt = async (e, t) => {
|
|
1291
|
-
let n;
|
|
1292
|
-
for (;;) {
|
|
1293
|
-
let r = await e.query({
|
|
1294
|
-
table: G,
|
|
1295
|
-
predicate: p(h("parentClosureId", t), ...n === void 0 ? [] : [g("id", n)]),
|
|
1296
|
-
lock: "update",
|
|
1297
|
-
order: [{
|
|
1298
|
-
column: "id",
|
|
1299
|
-
direction: "asc"
|
|
1300
|
-
}],
|
|
1301
|
-
take: 100,
|
|
1302
|
-
skip: void 0,
|
|
1303
|
-
projection: void 0
|
|
1304
|
-
});
|
|
1305
|
-
for (let e of r) {
|
|
1306
|
-
let r = J(e);
|
|
1307
|
-
if (r.cause?.reason !== "parent-close" || r.cause.detail?.closureId !== t || r.operation === "resume") throw Error("Parent closure control has contradictory ownership");
|
|
1308
|
-
if (r.result === null) return !0;
|
|
1309
|
-
n = r.id;
|
|
1310
|
-
}
|
|
1311
|
-
if (r.length < 100) return !1;
|
|
1312
|
-
}
|
|
1313
|
-
}, zt = async (e, t) => {
|
|
1314
|
-
let n = c.decodeUnknownSync(kt)({
|
|
1315
|
-
...t,
|
|
1316
|
-
owner: null,
|
|
1317
|
-
cause: t.cause ?? null,
|
|
1318
|
-
dispatchAttempts: 0,
|
|
1319
|
-
resumeJournal: null,
|
|
1320
|
-
result: null
|
|
1321
|
-
}), r = await Y(e, n.id);
|
|
1322
|
-
if (r !== void 0) {
|
|
1323
|
-
if (r.runId !== n.runId || r.workflowName !== n.workflowName || r.executionId !== n.executionId || r.generation !== n.generation || r.operation !== n.operation) throw Error("Workflow control identity belongs to a different target or operation");
|
|
1324
|
-
return r;
|
|
1325
|
-
}
|
|
1326
|
-
let i = new Date(n.requestedAt);
|
|
1327
|
-
if (!Number.isFinite(i.getTime())) throw Error("Workflow control timestamp is outside the supported date range");
|
|
1328
|
-
let [a] = await e.query({
|
|
1329
|
-
table: "_voltro_workflow_runs",
|
|
1330
|
-
predicate: h("id", n.runId),
|
|
1331
|
-
lock: "update",
|
|
1332
|
-
order: [],
|
|
1333
|
-
take: 1,
|
|
1334
|
-
skip: void 0,
|
|
1335
|
-
projection: void 0
|
|
1336
|
-
});
|
|
1337
|
-
if (a !== void 0 && (a.tag !== n.workflowName || a.executionId !== n.executionId)) throw Error("Workflow control target does not match its resident run");
|
|
1338
|
-
let o = c.decodeUnknownOption(Ot)(a?.runnerGeneration === n.generation ? a.subject : void 0), s = {
|
|
1339
|
-
...n,
|
|
1340
|
-
owner: o._tag === "Some" ? o.value : null
|
|
1341
|
-
}, l = a !== void 0 && a.runnerGeneration === n.generation && (a.status === "succeeded" || a.status === "failed" || a.status === "cancelled") ? {
|
|
1342
|
-
...s,
|
|
1343
|
-
result: c.decodeUnknownSync(Et)({
|
|
1344
|
-
kind: "already-terminal",
|
|
1345
|
-
status: a.status,
|
|
1346
|
-
completedAt: c.decodeUnknownSync(c.Date)(a.completedAt).getTime(),
|
|
1347
|
-
output: a.output,
|
|
1348
|
-
errorTag: a.errorTag,
|
|
1349
|
-
errorMessage: a.errorMessage
|
|
1350
|
-
})
|
|
1351
|
-
} : s, u = l.cause?.reason === "parent-close" ? c.decodeUnknownSync(c.NonEmptyString)(l.cause.detail?.closureId) : null;
|
|
1352
|
-
return await e.insert(G, {
|
|
1353
|
-
...l,
|
|
1354
|
-
requestedAt: i,
|
|
1355
|
-
parentClosureId: u
|
|
1356
|
-
}), l.result !== null && await jt(e, l, l.result, n.requestedAt), l;
|
|
1357
|
-
}, Bt = async (e, t, n) => {
|
|
1358
|
-
let r = await Y(e, t);
|
|
1359
|
-
if (r === void 0) throw Error("Workflow control request is missing");
|
|
1360
|
-
if (r.operation !== "resume") throw Error("Only resume controls can bind a suspension journal");
|
|
1361
|
-
if (r.result !== null) return {
|
|
1362
|
-
kind: "settled",
|
|
1363
|
-
request: r
|
|
1364
|
-
};
|
|
1365
|
-
let [i] = await e.query({
|
|
1366
|
-
table: "_voltro_workflow_runs",
|
|
1367
|
-
predicate: h("id", r.runId),
|
|
1368
|
-
lock: "update",
|
|
1369
|
-
order: [],
|
|
1370
|
-
take: 1,
|
|
1371
|
-
skip: void 0,
|
|
1372
|
-
projection: void 0
|
|
1373
|
-
});
|
|
1374
|
-
if (i === void 0) return {
|
|
1375
|
-
kind: "unknown",
|
|
1376
|
-
request: r
|
|
1377
|
-
};
|
|
1378
|
-
if (i.tag !== r.workflowName || i.executionId !== r.executionId) throw Error("Workflow control target does not match its resident run");
|
|
1379
|
-
if (i.runnerGeneration !== r.generation) return {
|
|
1380
|
-
kind: "superseded",
|
|
1381
|
-
request: r
|
|
1382
|
-
};
|
|
1383
|
-
if (i.status !== "suspended" || i.runnerEnteredAt !== null) return {
|
|
1384
|
-
kind: "not-suspended",
|
|
1385
|
-
request: r
|
|
1386
|
-
};
|
|
1387
|
-
let a = c.decodeUnknownSync(c.NullOr(c.Struct({
|
|
1388
|
-
requestId: q.fields.requestId,
|
|
1389
|
-
restartToken: q.fields.restartToken
|
|
1390
|
-
})))(i.engineDelivery);
|
|
1391
|
-
if (a === null) return {
|
|
1392
|
-
kind: "unknown",
|
|
1393
|
-
request: r
|
|
1394
|
-
};
|
|
1395
|
-
if (r.resumeJournal !== null) {
|
|
1396
|
-
if (r.resumeJournal.requestId !== a.requestId || r.resumeJournal.restartToken !== a.restartToken) throw Error("Resume journal binding does not match its resident delivery");
|
|
1397
|
-
return {
|
|
1398
|
-
kind: "bound",
|
|
1399
|
-
request: r
|
|
1400
|
-
};
|
|
1401
|
-
}
|
|
1402
|
-
if (r.dispatchAttempts !== 0) return {
|
|
1403
|
-
kind: "unknown",
|
|
1404
|
-
request: r
|
|
1405
|
-
};
|
|
1406
|
-
let o = await n({
|
|
1407
|
-
workflowName: r.workflowName,
|
|
1408
|
-
executionId: r.executionId,
|
|
1409
|
-
...a
|
|
1410
|
-
});
|
|
1411
|
-
if (o === void 0) return {
|
|
1412
|
-
kind: "waiting-journal",
|
|
1413
|
-
request: r
|
|
1414
|
-
};
|
|
1415
|
-
let s = c.decodeUnknownSync(q)(o);
|
|
1416
|
-
if (s.requestId !== a.requestId || s.restartToken !== a.restartToken) throw Error("Observed suspension belongs to another engine delivery");
|
|
1417
|
-
if (await e.update("_voltro_workflow_control_requests", r.id, { resumeJournal: s }) === null) throw Error("Workflow control request disappeared during suspension binding");
|
|
1418
|
-
return {
|
|
1419
|
-
kind: "bound",
|
|
1420
|
-
request: {
|
|
1421
|
-
...r,
|
|
1422
|
-
resumeJournal: s
|
|
1423
|
-
}
|
|
1424
|
-
};
|
|
1425
|
-
}, Vt = async (e, t) => {
|
|
1426
|
-
let n = await Y(e, t);
|
|
1427
|
-
if (n === void 0) throw Error("Workflow control request is missing");
|
|
1428
|
-
if (n.result !== null) return {
|
|
1429
|
-
kind: "settled",
|
|
1430
|
-
request: n
|
|
1431
|
-
};
|
|
1432
|
-
let [r] = await e.query({
|
|
1433
|
-
table: "_voltro_workflow_runs",
|
|
1434
|
-
predicate: h("id", n.runId),
|
|
1435
|
-
lock: "update",
|
|
1436
|
-
order: [],
|
|
1437
|
-
take: 1,
|
|
1438
|
-
skip: void 0,
|
|
1439
|
-
projection: void 0
|
|
1440
|
-
});
|
|
1441
|
-
if (r === void 0) return {
|
|
1442
|
-
kind: "unknown",
|
|
1443
|
-
request: n
|
|
1444
|
-
};
|
|
1445
|
-
if (r.tag !== n.workflowName || r.executionId !== n.executionId) throw Error("Workflow control target does not match its resident run");
|
|
1446
|
-
if (r.runnerGeneration !== n.generation) return {
|
|
1447
|
-
kind: "superseded",
|
|
1448
|
-
request: n
|
|
1449
|
-
};
|
|
1450
|
-
if (r.status === "succeeded" || r.status === "failed" || r.status === "cancelled") return {
|
|
1451
|
-
kind: "already-terminal",
|
|
1452
|
-
request: n,
|
|
1453
|
-
run: r
|
|
1454
|
-
};
|
|
1455
|
-
if (r.status !== "running" && r.status !== "suspended") throw Error("Workflow control target has an invalid resident status");
|
|
1456
|
-
let i = n.dispatchAttempts + 1;
|
|
1457
|
-
if (!Number.isSafeInteger(i)) throw Error("Workflow control attempt counter exhausted");
|
|
1458
|
-
if (await e.update("_voltro_workflow_control_requests", n.id, { dispatchAttempts: i }) === null) throw Error("Workflow control request disappeared before dispatch");
|
|
1459
|
-
return {
|
|
1460
|
-
kind: "dispatch",
|
|
1461
|
-
request: {
|
|
1462
|
-
...n,
|
|
1463
|
-
dispatchAttempts: i
|
|
1464
|
-
}
|
|
1465
|
-
};
|
|
1466
|
-
}, Ht = async (e, n) => {
|
|
1467
|
-
let a = n.owner, o;
|
|
1468
|
-
for (;;) {
|
|
1469
|
-
let s = await e.query({
|
|
1470
|
-
table: G,
|
|
1471
|
-
predicate: p(h("runId", a.runId), h("workflowName", a.workflowName), h("executionId", a.executionId), h("generation", a.generation), ...o === void 0 ? [] : [g("id", o)]),
|
|
1472
|
-
lock: "update",
|
|
1473
|
-
order: [{
|
|
1474
|
-
column: "id",
|
|
1475
|
-
direction: "asc"
|
|
1476
|
-
}],
|
|
1477
|
-
take: 100,
|
|
1478
|
-
skip: void 0,
|
|
1479
|
-
projection: void 0
|
|
1480
|
-
});
|
|
1481
|
-
for (let o of s) {
|
|
1482
|
-
if (typeof o.id != "string") throw Error("Workflow control request has an invalid identity");
|
|
1483
|
-
let s = await Y(e, o.id);
|
|
1484
|
-
if (s === void 0) throw Error("Workflow control request disappeared during completion");
|
|
1485
|
-
if (s.result !== null) continue;
|
|
1486
|
-
let l = n.outcome;
|
|
1487
|
-
await jt(e, s, c.decodeUnknownSync(Et)({
|
|
1488
|
-
kind: l.status === "cancelled" && s.operation !== "resume" ? "confirmed" : "already-terminal",
|
|
1489
|
-
status: l.status,
|
|
1490
|
-
completedAt: n.now,
|
|
1491
|
-
output: l.status === "succeeded" ? i(a.workflowName) ? t(l.output, `workflow '${a.workflowName}' result`) : l.output : null,
|
|
1492
|
-
errorTag: l.status === "failed" ? l.errorTag : null,
|
|
1493
|
-
errorMessage: l.status === "failed" ? r(a.workflowName, l.errorMessage) : null
|
|
1494
|
-
}), n.now);
|
|
1495
|
-
}
|
|
1496
|
-
if (s.length < 100) return;
|
|
1497
|
-
let l = s[s.length - 1];
|
|
1498
|
-
if (typeof l.id != "string") throw Error("Workflow control cursor has an invalid identity");
|
|
1499
|
-
o = l.id;
|
|
1500
|
-
}
|
|
1501
|
-
}, Ut = async (e, t, n, r) => {
|
|
1502
|
-
let i = c.decodeUnknownSync(Tt)({
|
|
1503
|
-
kind: "confirmed",
|
|
1504
|
-
status: "running",
|
|
1505
|
-
generation: n,
|
|
1506
|
-
enteredAt: r
|
|
1507
|
-
}), a;
|
|
1508
|
-
for (;;) {
|
|
1509
|
-
let n = await e.query({
|
|
1510
|
-
table: G,
|
|
1511
|
-
predicate: p(h("runId", t.runId), h("workflowName", t.workflowName), h("executionId", t.executionId), h("generation", t.generation), h("operation", "resume"), ...a === void 0 ? [] : [g("id", a)]),
|
|
1512
|
-
lock: "update",
|
|
1513
|
-
order: [{
|
|
1514
|
-
column: "id",
|
|
1515
|
-
direction: "asc"
|
|
1516
|
-
}],
|
|
1517
|
-
take: 100,
|
|
1518
|
-
skip: void 0,
|
|
1519
|
-
projection: void 0
|
|
1520
|
-
});
|
|
1521
|
-
for (let t of n) {
|
|
1522
|
-
if (typeof t.id != "string") throw Error("Workflow control request has an invalid identity");
|
|
1523
|
-
let n = await Y(e, t.id);
|
|
1524
|
-
if (n === void 0) throw Error("Workflow control request disappeared during resume");
|
|
1525
|
-
n.result === null && await jt(e, n, i, r);
|
|
1526
|
-
}
|
|
1527
|
-
if (n.length < 100) return;
|
|
1528
|
-
let o = n[n.length - 1];
|
|
1529
|
-
if (typeof o.id != "string") throw Error("Workflow control cursor has an invalid identity");
|
|
1530
|
-
a = o.id;
|
|
1531
|
-
}
|
|
1532
|
-
}, Wt = "voltro-workflow-restart", Gt = class extends o.Service()("voltro/CurrentWorkflowDelivery") {}, Kt = (e) => ({
|
|
1533
|
-
...e,
|
|
1534
|
-
registerEntity: (t, n, r) => e.registerEntity(t, t.type.startsWith("Workflow/") ? n.pipe(s.map((e) => {
|
|
1535
|
-
let t = e.run;
|
|
1536
|
-
if (typeof t != "function") throw Error("Workflow entity is missing its run handler");
|
|
1537
|
-
return {
|
|
1538
|
-
...e,
|
|
1539
|
-
run: (e) => {
|
|
1540
|
-
let n = {
|
|
1541
|
-
requestId: String(e.requestId),
|
|
1542
|
-
restartToken: e.headers["voltro-workflow-restart"] ?? null
|
|
1543
|
-
};
|
|
1544
|
-
return s.suspend(() => {
|
|
1545
|
-
let n = t(e);
|
|
1546
|
-
return s.isEffect(n) ? n : s.die(/* @__PURE__ */ Error("Workflow run handler must return an Effect"));
|
|
1547
|
-
}).pipe(s.provideService(Gt, n));
|
|
1548
|
-
}
|
|
1549
|
-
};
|
|
1550
|
-
})) : n, r)
|
|
1551
|
-
}), qt = c.fromJsonString(c.Struct({
|
|
1552
|
-
_tag: c.Literal("Success"),
|
|
1553
|
-
value: c.Struct({ _tag: c.Literal("Suspended") })
|
|
1554
|
-
})), Jt = c.fromJsonString(c.Record(c.String, c.String)), Yt = (e) => s.gen(function* () {
|
|
1555
|
-
if (!/^[1-9]\d*$/.test(e.requestId) || e.workflowName.length === 0 || e.executionId.length === 0) return yield* s.die(/* @__PURE__ */ Error("Suspension observation requires an exact engine delivery owner"));
|
|
1556
|
-
let [t] = yield* (yield* S.SqlClient).withoutTransforms()`
|
|
1557
|
-
SELECT m.entity_type, m.entity_id, m.tag, m.headers, r.id AS reply_id, r.payload
|
|
1558
|
-
FROM cluster_messages m LEFT JOIN cluster_replies r
|
|
1559
|
-
ON r.id = m.last_reply_id AND r.request_id = m.id AND r.kind = 0
|
|
1560
|
-
WHERE m.id = ${e.requestId} AND m.kind = 0`;
|
|
1561
|
-
if (t === void 0) return;
|
|
1562
|
-
if (t.entity_type !== `Workflow/${e.workflowName}` || t.entity_id !== e.executionId || t.tag !== "run") return yield* s.die(/* @__PURE__ */ Error("Suspension observation belongs to another execution or procedure"));
|
|
1563
|
-
if (((yield* s.sync(() => c.decodeUnknownSync(Jt)(t.headers)))["voltro-workflow-restart"] ?? null) !== e.restartToken || t.reply_id === null || c.decodeUnknownOption(qt)(t.payload)._tag === "None") return;
|
|
1564
|
-
let n = String(t.reply_id);
|
|
1565
|
-
return /^[1-9]\d*$/.test(n) ? {
|
|
1566
|
-
...e,
|
|
1567
|
-
replyId: n
|
|
1568
|
-
} : yield* s.die(/* @__PURE__ */ Error("Suspension reply has an invalid identity"));
|
|
1569
|
-
}).pipe(s.provideService(S.SafeIntegers, !0)), Xt = (e, t) => s.gen(function* () {
|
|
1570
|
-
let { restart: n, suspension: r } = t, i = /* @__PURE__ */ new Map();
|
|
1571
|
-
for (let t of e) {
|
|
1572
|
-
if (!/^[1-9]\d*$/.test(t.requestId) || !/^[1-9]\d*$/.test(t.replyId)) return yield* s.die(/* @__PURE__ */ Error("Journal reset requires positive decimal request and reply identities"));
|
|
1573
|
-
let e = i.get(t.requestId);
|
|
1574
|
-
if (e !== void 0 && e !== t.replyId) return yield* s.die(/* @__PURE__ */ Error("Journal reset contains conflicting observations for one request"));
|
|
1575
|
-
i.set(t.requestId, t.replyId);
|
|
1576
|
-
}
|
|
1577
|
-
if (n !== void 0 && (!i.has(n.requestId) || n.token.length === 0 || n.token === n.previousToken || n.workflowName.length === 0 || n.executionId.length === 0)) return yield* s.die(/* @__PURE__ */ Error("Journal restart requires a selected request, new token and execution owner"));
|
|
1578
|
-
if (i.size === 0) return {
|
|
1579
|
-
kind: "reset",
|
|
1580
|
-
count: 0
|
|
1581
|
-
};
|
|
1582
|
-
let a = [...i].sort(([e], [t]) => e < t ? -1 : +(e > t)), o = (yield* S.SqlClient).withoutTransforms(), l = o("cluster_messages"), u = o("cluster_replies"), d = o.onDialectOrElse({
|
|
1583
|
-
pg: () => o.literal("FALSE"),
|
|
1584
|
-
orElse: () => o.literal("0")
|
|
1585
|
-
});
|
|
1586
|
-
return yield* s.gen(function* () {
|
|
1587
|
-
let e = /* @__PURE__ */ new Map();
|
|
1588
|
-
for (let [t] of a) {
|
|
1589
|
-
let r = yield* o.onDialectOrElse({
|
|
1590
|
-
mssql: () => o`
|
|
1591
|
-
SELECT last_reply_id FROM ${l} WITH (UPDLOCK, HOLDLOCK)
|
|
1592
|
-
WHERE id = ${t} AND kind = 0`,
|
|
1593
|
-
sqlite: () => o`
|
|
1594
|
-
SELECT last_reply_id FROM ${l} WHERE id = ${t} AND kind = 0`,
|
|
1595
|
-
orElse: () => o`
|
|
1596
|
-
SELECT last_reply_id FROM ${l} WHERE id = ${t} AND kind = 0 FOR UPDATE`
|
|
1597
|
-
});
|
|
1598
|
-
if (r.length !== 1) return {
|
|
1599
|
-
kind: "changed",
|
|
1600
|
-
requestId: t
|
|
1601
|
-
};
|
|
1602
|
-
if (e.set(t, String(r[0]?.last_reply_id)), n !== void 0) {
|
|
1603
|
-
let [e] = yield* o`
|
|
1604
|
-
SELECT entity_type, entity_id, tag FROM ${l} WHERE id = ${t}`;
|
|
1605
|
-
if (e?.entity_type !== `Workflow/${n.workflowName}` || e.entity_id !== n.executionId || e.tag !== (t === n.requestId ? "run" : "activity")) return yield* s.die(/* @__PURE__ */ Error("Journal restart selection belongs to another execution or procedure"));
|
|
1606
|
-
}
|
|
1607
|
-
}
|
|
1608
|
-
let t;
|
|
1609
|
-
if (r !== void 0) {
|
|
1610
|
-
let [e] = yield* o`
|
|
1611
|
-
SELECT entity_type, entity_id, tag, headers FROM ${l} WHERE id = ${r.requestId}`;
|
|
1612
|
-
if (e?.entity_type !== `Workflow/${r.workflowName}` || e.entity_id !== r.executionId || e.tag !== "run" || r.workflowName.length === 0 || r.executionId.length === 0) return yield* s.die(/* @__PURE__ */ Error("Journal resume selection belongs to another execution or procedure"));
|
|
1613
|
-
if (((yield* s.sync(() => c.decodeUnknownSync(c.fromJsonString(c.Record(c.String, c.String)))(e.headers)))["voltro-workflow-restart"] ?? null) !== r.restartToken) return {
|
|
1614
|
-
kind: "changed",
|
|
1615
|
-
requestId: r.requestId
|
|
1616
|
-
};
|
|
1617
|
-
}
|
|
1618
|
-
if (n !== void 0) {
|
|
1619
|
-
let [e] = yield* o`
|
|
1620
|
-
SELECT tag, entity_type, headers FROM ${l} WHERE id = ${n.requestId}`;
|
|
1621
|
-
if (e?.tag !== "run" || !e.entity_type.startsWith("Workflow/")) return yield* s.die(/* @__PURE__ */ Error("Journal restart marker can only target a workflow run"));
|
|
1622
|
-
if (t = yield* s.sync(() => c.decodeUnknownSync(c.fromJsonString(c.Record(c.String, c.String)))(e.headers)), t["voltro-workflow-restart"] === n.token) return {
|
|
1623
|
-
kind: "already-reset",
|
|
1624
|
-
count: a.length
|
|
1625
|
-
};
|
|
1626
|
-
if ((t["voltro-workflow-restart"] ?? null) !== n.previousToken) return {
|
|
1627
|
-
kind: "changed",
|
|
1628
|
-
requestId: n.requestId
|
|
1629
|
-
};
|
|
1630
|
-
}
|
|
1631
|
-
for (let [t, n] of a) {
|
|
1632
|
-
if (e.get(t) !== n) return {
|
|
1633
|
-
kind: "changed",
|
|
1634
|
-
requestId: t
|
|
1635
|
-
};
|
|
1636
|
-
let i = yield* o`SELECT payload FROM ${u}
|
|
1637
|
-
WHERE id = ${n} AND request_id = ${t} AND kind = 0`;
|
|
1638
|
-
if (i.length !== 1 || r !== void 0 && c.decodeUnknownOption(qt)(i[0]?.payload)._tag === "None") return {
|
|
1639
|
-
kind: "changed",
|
|
1640
|
-
requestId: t
|
|
1641
|
-
};
|
|
1642
|
-
}
|
|
1643
|
-
n !== void 0 && (yield* o`UPDATE ${l} SET headers = ${JSON.stringify({
|
|
1644
|
-
...t,
|
|
1645
|
-
[Wt]: n.token
|
|
1646
|
-
})}
|
|
1647
|
-
WHERE id = ${n.requestId}`);
|
|
1648
|
-
for (let [e] of a) yield* o`DELETE FROM ${u} WHERE request_id = ${e} AND kind = 0`, yield* o`DELETE FROM ${l} WHERE request_id = ${e} AND kind = 2`, yield* o`UPDATE ${l} SET processed = ${d}, last_reply_id = NULL,
|
|
1649
|
-
last_read = NULL WHERE request_id = ${e}`;
|
|
1650
|
-
return {
|
|
1651
|
-
kind: "reset",
|
|
1652
|
-
count: a.length
|
|
1653
|
-
};
|
|
1654
|
-
}).pipe(o.withTransaction, s.provideService(S.SafeIntegers, !0));
|
|
1655
|
-
}), Zt = (e, t) => Xt(e, t === void 0 ? {} : { restart: t }), Qt = (e) => Xt([e], { suspension: e }), X = ne("_voltro_workflow_restart_requests", {
|
|
1656
|
-
id: _({ prefix: "wfrs" }),
|
|
1657
|
-
runId: b(),
|
|
1658
|
-
workflowName: b(),
|
|
1659
|
-
executionId: b(),
|
|
1660
|
-
generation: b(),
|
|
1661
|
-
token: b(),
|
|
1662
|
-
ledgerId: b(),
|
|
1663
|
-
tenantId: b().nullable(),
|
|
1664
|
-
delivery: y(),
|
|
1665
|
-
replies: y(),
|
|
1666
|
-
selection: y().nullable(),
|
|
1667
|
-
eviction: y().nullable(),
|
|
1668
|
-
requestedAt: re(),
|
|
1669
|
-
dispatchAttempts: ee().default(0),
|
|
1670
|
-
enteredGeneration: b().nullable()
|
|
1671
|
-
}).unique(["runId", "generation"]).unique(["runId", "token"]).nonReactive(), Z = c.NonEmptyString, Q = c.Struct({
|
|
1672
|
-
requestId: Z,
|
|
1673
|
-
restartToken: c.NullOr(Z)
|
|
1674
|
-
}), $t = c.Struct({
|
|
1675
|
-
requestId: Z,
|
|
1676
|
-
replyId: Z
|
|
1677
|
-
}), $ = u, en = ne("_voltro_workflow_restart_withdrawals", {
|
|
1678
|
-
id: _({ prefix: "wfrw" }),
|
|
1679
|
-
runId: b(),
|
|
1680
|
-
workflowName: b(),
|
|
1681
|
-
tenantId: b().nullable(),
|
|
1682
|
-
selection: y(),
|
|
1683
|
-
withdrawnAt: re()
|
|
1684
|
-
}).nonReactive(), tn = c.Struct({
|
|
1685
|
-
id: c.NonEmptyString,
|
|
1686
|
-
runId: c.NonEmptyString,
|
|
1687
|
-
workflowName: c.NonEmptyString,
|
|
1688
|
-
tenantId: c.NullOr(c.NonEmptyString),
|
|
1689
|
-
selection: $,
|
|
1690
|
-
withdrawnAt: c.Date
|
|
1691
|
-
}), nn = async (e, t) => {
|
|
1692
|
-
let n = c.decodeUnknownSync(d)(t), [r] = await e.query({
|
|
1693
|
-
table: en.tableName,
|
|
1694
|
-
predicate: h("id", n.requestId),
|
|
1695
|
-
lock: "update",
|
|
1696
|
-
order: [],
|
|
1697
|
-
take: 1,
|
|
1698
|
-
skip: void 0,
|
|
1699
|
-
projection: void 0
|
|
1700
|
-
});
|
|
1701
|
-
if (r === void 0) return;
|
|
1702
|
-
let i = c.decodeUnknownSync(tn)(r);
|
|
1703
|
-
if (i.runId !== n.runId) throw Error("Restart identity belongs to a different command");
|
|
1704
|
-
if (!Number.isFinite(i.withdrawnAt.getTime())) throw Error("Invalid restart withdrawal timestamp");
|
|
1705
|
-
return i;
|
|
1706
|
-
}, rn = async (e, t) => {
|
|
1707
|
-
if (await nn(e, t) !== void 0) throw Error("Restart request was permanently withdrawn");
|
|
1708
|
-
}, an = c.Struct({
|
|
1709
|
-
id: Z,
|
|
1710
|
-
runId: Z,
|
|
1711
|
-
workflowName: Z,
|
|
1712
|
-
executionId: Z,
|
|
1713
|
-
generation: Z,
|
|
1714
|
-
token: Z,
|
|
1715
|
-
ledgerId: Z,
|
|
1716
|
-
tenantId: c.NullOr(Z),
|
|
1717
|
-
delivery: Q,
|
|
1718
|
-
replies: c.Array($t),
|
|
1719
|
-
selection: $,
|
|
1720
|
-
eviction: c.NullOr(c.Struct({
|
|
1721
|
-
executionId: Z,
|
|
1722
|
-
runId: c.String
|
|
1723
|
-
})),
|
|
1724
|
-
requestedAt: c.Date,
|
|
1725
|
-
dispatchAttempts: c.Number.check(c.isInt(), c.isGreaterThanOrEqualTo(0)),
|
|
1726
|
-
enteredGeneration: c.NullOr(Z)
|
|
1727
|
-
}), on = (e, t) => e.kind === t.kind && (e.kind === "failed-steps" || t.kind === "from-step" && e.stepName === t.stepName), sn = async (e, t) => {
|
|
1728
|
-
let n = c.decodeUnknownSync(d)(t), [r] = await e.query({
|
|
1729
|
-
table: X.tableName,
|
|
1730
|
-
predicate: h("id", n.requestId),
|
|
1731
|
-
lock: "update",
|
|
1732
|
-
order: [],
|
|
1733
|
-
take: 1,
|
|
1734
|
-
skip: void 0,
|
|
1735
|
-
projection: void 0
|
|
1736
|
-
});
|
|
1737
|
-
if (r === void 0) return;
|
|
1738
|
-
let i = c.decodeUnknownSync(an)(r);
|
|
1739
|
-
if (i.runId !== n.runId) throw Error("Restart identity belongs to a different command");
|
|
1740
|
-
return i;
|
|
1741
|
-
}, cn = async (e, t) => {
|
|
1742
|
-
let n = await nn(e, t);
|
|
1743
|
-
if (n !== void 0) return c.decodeUnknownSync(l)({
|
|
1744
|
-
...t,
|
|
1745
|
-
kind: "withdrawn",
|
|
1746
|
-
workflowName: n.workflowName,
|
|
1747
|
-
selection: n.selection,
|
|
1748
|
-
withdrawnAt: n.withdrawnAt.getTime()
|
|
1749
|
-
});
|
|
1750
|
-
let r = await sn(e, t);
|
|
1751
|
-
if (r === void 0) return c.decodeUnknownSync(l)({
|
|
1752
|
-
...t,
|
|
1753
|
-
kind: "not-found"
|
|
1754
|
-
});
|
|
1755
|
-
let i = {
|
|
1756
|
-
requestId: r.id,
|
|
1757
|
-
runId: r.runId,
|
|
1758
|
-
workflowName: r.workflowName,
|
|
1759
|
-
executionId: r.executionId,
|
|
1760
|
-
originalGeneration: r.generation,
|
|
1761
|
-
selection: r.selection,
|
|
1762
|
-
requestedAt: r.requestedAt.getTime(),
|
|
1763
|
-
dispatchAttempts: r.dispatchAttempts
|
|
1764
|
-
};
|
|
1765
|
-
return c.decodeUnknownSync(l)(r.enteredGeneration === null ? {
|
|
1766
|
-
...i,
|
|
1767
|
-
kind: "pending"
|
|
1768
|
-
} : {
|
|
1769
|
-
...i,
|
|
1770
|
-
kind: "entered",
|
|
1771
|
-
enteredGeneration: r.enteredGeneration
|
|
1772
|
-
});
|
|
1773
|
-
}, ln = async (e, t) => {
|
|
1774
|
-
for (let e of [
|
|
1775
|
-
t.id,
|
|
1776
|
-
t.runId,
|
|
1777
|
-
t.workflowName
|
|
1778
|
-
]) c.decodeUnknownSync(Z)(e);
|
|
1779
|
-
if (t.id.length > 64) throw Error("Invalid restart request identity");
|
|
1780
|
-
c.decodeUnknownSync(c.NullOr(Z))(t.tenantId);
|
|
1781
|
-
let n = c.decodeUnknownSync($)(t.selection);
|
|
1782
|
-
await rn(e, {
|
|
1783
|
-
requestId: t.id,
|
|
1784
|
-
runId: t.runId
|
|
1785
|
-
});
|
|
1786
|
-
let r = await sn(e, {
|
|
1787
|
-
requestId: t.id,
|
|
1788
|
-
runId: t.runId
|
|
1789
|
-
});
|
|
1790
|
-
if (r !== void 0) {
|
|
1791
|
-
if (r.runId !== t.runId || r.workflowName !== t.workflowName || r.tenantId !== t.tenantId || !on(r.selection, n)) throw Error("Restart identity belongs to a different command");
|
|
1792
|
-
return r;
|
|
1793
|
-
}
|
|
1794
|
-
}, un = async (e, t) => {
|
|
1795
|
-
let n = c.decodeUnknownSync(tn)({
|
|
1796
|
-
...t,
|
|
1797
|
-
withdrawnAt: new Date(t.now)
|
|
1798
|
-
});
|
|
1799
|
-
if (c.decodeUnknownSync(d)({
|
|
1800
|
-
requestId: n.id,
|
|
1801
|
-
runId: n.runId
|
|
1802
|
-
}), !Number.isFinite(n.withdrawnAt.getTime())) throw Error("Invalid restart withdrawal timestamp");
|
|
1803
|
-
let r = await nn(e, {
|
|
1804
|
-
requestId: n.id,
|
|
1805
|
-
runId: n.runId
|
|
1806
|
-
});
|
|
1807
|
-
if (r !== void 0) {
|
|
1808
|
-
if (r.workflowName !== n.workflowName || r.tenantId !== n.tenantId || !on(r.selection, n.selection)) throw Error("Restart identity belongs to a different command");
|
|
1809
|
-
return {
|
|
1810
|
-
kind: "withdrawn",
|
|
1811
|
-
withdrawal: r,
|
|
1812
|
-
reused: !0
|
|
1813
|
-
};
|
|
1814
|
-
}
|
|
1815
|
-
let i = await ln(e, n);
|
|
1816
|
-
if (i !== void 0) return {
|
|
1817
|
-
kind: "reserved",
|
|
1818
|
-
request: i
|
|
1819
|
-
};
|
|
1820
|
-
let [a] = await e.query({
|
|
1821
|
-
table: "_voltro_workflow_runs",
|
|
1822
|
-
predicate: h("id", n.runId),
|
|
1823
|
-
lock: "update",
|
|
1824
|
-
order: [],
|
|
1825
|
-
take: 1,
|
|
1826
|
-
skip: void 0,
|
|
1827
|
-
projection: void 0
|
|
1828
|
-
});
|
|
1829
|
-
if (a === void 0 || a.tag !== n.workflowName) throw Error("Restart withdrawal requires its resident workflow");
|
|
1830
|
-
if ((c.decodeUnknownSync(c.NullOr(c.Struct({ tenantId: c.NullOr(Z) })))(a.subject ?? null)?.tenantId ?? null) !== n.tenantId) throw Error("Restart withdrawal belongs to another resident tenant");
|
|
1831
|
-
return await e.insert(en.tableName, n), {
|
|
1832
|
-
kind: "withdrawn",
|
|
1833
|
-
withdrawal: n,
|
|
1834
|
-
reused: !1
|
|
1835
|
-
};
|
|
1836
|
-
}, dn = async (e, t) => {
|
|
1837
|
-
c.decodeUnknownSync(Z)(t.generation);
|
|
1838
|
-
let n = await ln(e, t);
|
|
1839
|
-
if (n !== void 0 && n.generation !== t.generation) throw Error("Restart identity belongs to a different command");
|
|
1840
|
-
return n;
|
|
1841
|
-
}, fn = async (e, t) => {
|
|
1842
|
-
for (let e of [
|
|
1843
|
-
t.id,
|
|
1844
|
-
t.runId,
|
|
1845
|
-
t.generation,
|
|
1846
|
-
t.token
|
|
1847
|
-
]) c.decodeUnknownSync(Z)(e);
|
|
1848
|
-
if (t.id.length > 64 || !Number.isFinite(new Date(t.now).getTime())) throw Error("Invalid restart request identity or timestamp");
|
|
1849
|
-
await rn(e, {
|
|
1850
|
-
requestId: t.id,
|
|
1851
|
-
runId: t.runId
|
|
1852
|
-
});
|
|
1853
|
-
let n = c.decodeUnknownSync(Q)(t.delivery), r = c.decodeUnknownSync($)(t.selection);
|
|
1854
|
-
if (n.restartToken === t.token) throw Error("Restart requires a new delivery token");
|
|
1855
|
-
let i = c.decodeUnknownSync(c.Array($t))(t.replies), a = /* @__PURE__ */ new Map();
|
|
1856
|
-
for (let e of i) {
|
|
1857
|
-
if (!/^[1-9]\d*$/.test(e.requestId) || !/^[1-9]\d*$/.test(e.replyId) || a.has(e.requestId)) throw Error("Restart requires distinct, exact journal reply identities");
|
|
1858
|
-
a.set(e.requestId, e.replyId);
|
|
1859
|
-
}
|
|
1860
|
-
if (!a.has(n.requestId)) throw Error("Restart selection must include its run reply");
|
|
1861
|
-
let [o] = await e.query({
|
|
1862
|
-
table: X.tableName,
|
|
1863
|
-
predicate: h("id", t.id),
|
|
1864
|
-
lock: "update",
|
|
1865
|
-
order: [],
|
|
1866
|
-
take: 1,
|
|
1867
|
-
skip: void 0,
|
|
1868
|
-
projection: void 0
|
|
1869
|
-
});
|
|
1870
|
-
if (o !== void 0) {
|
|
1871
|
-
let e = c.decodeUnknownSync(an)(o);
|
|
1872
|
-
if (e.runId !== t.runId || e.generation !== t.generation || e.token !== t.token || e.workflowName !== t.control.workflowName || e.tenantId !== t.tenantId || e.delivery.requestId !== n.requestId || e.delivery.restartToken !== n.restartToken || !on(e.selection, r) || e.replies.length !== a.size || e.replies.some((e) => a.get(e.requestId) !== e.replyId)) throw Error("Restart identity belongs to a different request");
|
|
1873
|
-
return {
|
|
1874
|
-
kind: "reserved",
|
|
1875
|
-
request: e,
|
|
1876
|
-
reused: !0
|
|
1877
|
-
};
|
|
1878
|
-
}
|
|
1879
|
-
let [s] = await e.query({
|
|
1880
|
-
table: "_voltro_workflow_runs",
|
|
1881
|
-
predicate: h("id", t.runId),
|
|
1882
|
-
lock: "update",
|
|
1883
|
-
order: [],
|
|
1884
|
-
take: 1,
|
|
1885
|
-
skip: void 0,
|
|
1886
|
-
projection: void 0
|
|
1887
|
-
});
|
|
1888
|
-
if (s === void 0 || s.tag !== t.control.workflowName || s.runnerGeneration !== t.generation || s.status !== "failed" || s.discardedAt != null || typeof s.executionId != "string" || s.executionId.length === 0) throw Error("Restart requires its undiscarded failed resident generation");
|
|
1889
|
-
if ((c.decodeUnknownSync(c.NullOr(c.Struct({ tenantId: c.NullOr(Z) })))(s.subject ?? null)?.tenantId ?? null) !== t.tenantId) throw Error("Restart belongs to another resident tenant");
|
|
1890
|
-
let l = c.decodeUnknownSync(Q)(s.engineDelivery);
|
|
1891
|
-
if (l.requestId !== n.requestId || l.restartToken !== n.restartToken) throw Error("Restart journal delivery does not belong to its resident generation");
|
|
1892
|
-
let [u] = await e.query({
|
|
1893
|
-
table: X.tableName,
|
|
1894
|
-
predicate: p(h("runId", t.runId), te(h("generation", t.generation), h("token", t.token))),
|
|
1895
|
-
lock: "update",
|
|
1896
|
-
order: [],
|
|
1897
|
-
take: 1,
|
|
1898
|
-
skip: void 0,
|
|
1899
|
-
projection: ["id", "generation"]
|
|
1900
|
-
});
|
|
1901
|
-
if (u !== void 0) {
|
|
1902
|
-
if (u.generation !== t.generation) throw Error("Restart delivery token was already used by this run");
|
|
1903
|
-
return { kind: "already-requested" };
|
|
1904
|
-
}
|
|
1905
|
-
let d = et(e, t.control.workflowName, s.payload), f = ue(t.control, d), m = await St({
|
|
1906
|
-
store: e,
|
|
1907
|
-
control: t.control,
|
|
1908
|
-
keys: f,
|
|
1909
|
-
paused: t.paused,
|
|
1910
|
-
now: t.now,
|
|
1911
|
-
reconsidering: !0
|
|
1912
|
-
});
|
|
1913
|
-
if (m.kind !== "admit") return {
|
|
1914
|
-
kind: "not-admitted",
|
|
1915
|
-
decision: m
|
|
1916
|
-
};
|
|
1917
|
-
let g = await dt({
|
|
1918
|
-
store: e,
|
|
1919
|
-
control: t.control,
|
|
1920
|
-
keys: f,
|
|
1921
|
-
outcome: "admitted",
|
|
1922
|
-
mode: "restart",
|
|
1923
|
-
reason: m.reason,
|
|
1924
|
-
collapsed: 1,
|
|
1925
|
-
waitedMs: 0,
|
|
1926
|
-
executionId: null,
|
|
1927
|
-
runId: null,
|
|
1928
|
-
tenantId: t.tenantId,
|
|
1929
|
-
now: t.now
|
|
1930
|
-
});
|
|
1931
|
-
if (g === void 0) throw Error("Restart has no admission reservation");
|
|
1932
|
-
let _ = c.decodeUnknownSync(an)({
|
|
1933
|
-
id: t.id,
|
|
1934
|
-
runId: t.runId,
|
|
1935
|
-
workflowName: t.control.workflowName,
|
|
1936
|
-
executionId: s.executionId,
|
|
1937
|
-
generation: t.generation,
|
|
1938
|
-
token: t.token,
|
|
1939
|
-
ledgerId: g,
|
|
1940
|
-
tenantId: t.tenantId,
|
|
1941
|
-
delivery: n,
|
|
1942
|
-
replies: i,
|
|
1943
|
-
selection: r,
|
|
1944
|
-
eviction: m.evict ?? null,
|
|
1945
|
-
requestedAt: new Date(t.now),
|
|
1946
|
-
dispatchAttempts: 0,
|
|
1947
|
-
enteredGeneration: null
|
|
1948
|
-
});
|
|
1949
|
-
return await e.insert(X.tableName, _), {
|
|
1950
|
-
kind: "reserved",
|
|
1951
|
-
request: _,
|
|
1952
|
-
reused: !1
|
|
1953
|
-
};
|
|
1954
|
-
}, pn = async (e, t) => {
|
|
1955
|
-
let [n] = await e.query({
|
|
1956
|
-
table: X.tableName,
|
|
1957
|
-
predicate: h("id", t),
|
|
1958
|
-
lock: "update",
|
|
1959
|
-
order: [],
|
|
1960
|
-
take: 1,
|
|
1961
|
-
skip: void 0,
|
|
1962
|
-
projection: void 0
|
|
1963
|
-
});
|
|
1964
|
-
if (n === void 0) throw Error("Restart dispatch has no resident request");
|
|
1965
|
-
let r = c.decodeUnknownSync(an)(n);
|
|
1966
|
-
if (r.enteredGeneration !== null) throw Error("Restart request has already entered its resident generation");
|
|
1967
|
-
let [i] = await e.query({
|
|
1968
|
-
table: "_voltro_workflow_admissions",
|
|
1969
|
-
predicate: h("id", r.ledgerId),
|
|
1970
|
-
lock: "update",
|
|
1971
|
-
order: [],
|
|
1972
|
-
take: 1,
|
|
1973
|
-
skip: void 0,
|
|
1974
|
-
projection: void 0
|
|
1975
|
-
});
|
|
1976
|
-
if (i === void 0 || i.outcome !== "admitted" || i.releasedAt !== null || i.workflowName !== r.workflowName || i.tenantId !== r.tenantId || i.executionId !== null || i.runId !== null) throw Error("Restart dispatch has no matching held resident reservation");
|
|
1977
|
-
let [a] = await e.query({
|
|
1978
|
-
table: "_voltro_workflow_runs",
|
|
1979
|
-
predicate: h("id", r.runId),
|
|
1980
|
-
lock: "update",
|
|
1981
|
-
order: [],
|
|
1982
|
-
take: 1,
|
|
1983
|
-
skip: void 0,
|
|
1984
|
-
projection: void 0
|
|
1985
|
-
});
|
|
1986
|
-
if (a === void 0 || a.tag !== r.workflowName || a.executionId !== r.executionId || a.runnerGeneration !== r.generation || a.status !== "failed" || a.discardedAt != null) throw Error("Restart dispatch no longer owns its failed resident generation");
|
|
1987
|
-
let o = c.decodeUnknownSync(Q)(a.engineDelivery);
|
|
1988
|
-
if (o.requestId !== r.delivery.requestId || o.restartToken !== r.delivery.restartToken) throw Error("Restart dispatch no longer owns its journal delivery");
|
|
1989
|
-
return {
|
|
1990
|
-
request: r,
|
|
1991
|
-
run: a
|
|
1992
|
-
};
|
|
1993
|
-
}, mn = async (e, t) => {
|
|
1994
|
-
let { request: n } = await pn(e, t), r = n.dispatchAttempts + 1;
|
|
1995
|
-
if (!Number.isSafeInteger(r)) throw Error("Restart dispatch attempt counter exhausted");
|
|
1996
|
-
if (await e.update(X.tableName, t, { dispatchAttempts: r }) === null) throw Error("Restart request disappeared before dispatch");
|
|
1997
|
-
return {
|
|
1998
|
-
...n,
|
|
1999
|
-
dispatchAttempts: r
|
|
2000
|
-
};
|
|
2001
|
-
}, hn = (e) => s.gen(function* () {
|
|
2002
|
-
let { request: t } = yield* s.promise(() => e.transaction((t) => pn(t, e.requestId)));
|
|
2003
|
-
if (!(yield* s.promise(() => e.acquireCapacity(t)))) return { kind: "waiting-capacity" };
|
|
2004
|
-
let n = yield* s.promise(() => e.transaction((e) => mn(e, t.id)));
|
|
2005
|
-
return yield* Zt(n.replies, {
|
|
2006
|
-
requestId: n.delivery.requestId,
|
|
2007
|
-
previousToken: n.delivery.restartToken,
|
|
2008
|
-
token: n.token,
|
|
2009
|
-
workflowName: n.workflowName,
|
|
2010
|
-
executionId: n.executionId
|
|
2011
|
-
});
|
|
2012
|
-
}), gn = async (e, t) => {
|
|
2013
|
-
for (let e of [
|
|
2014
|
-
t.runId,
|
|
2015
|
-
t.workflowName,
|
|
2016
|
-
t.executionId,
|
|
2017
|
-
t.generation
|
|
2018
|
-
]) c.decodeUnknownSync(Z)(e);
|
|
2019
|
-
if (!Number.isFinite(new Date(t.now).getTime())) throw Error("Restart entry requires a valid timestamp");
|
|
2020
|
-
let n = c.decodeUnknownSync(Q)(t.delivery);
|
|
2021
|
-
if (n.restartToken === null) throw Error("Restart entry has no delivery token");
|
|
2022
|
-
let [r] = await e.query({
|
|
2023
|
-
table: X.tableName,
|
|
2024
|
-
predicate: p(h("runId", t.runId), h("token", n.restartToken)),
|
|
2025
|
-
lock: "update",
|
|
2026
|
-
order: [],
|
|
2027
|
-
take: 1,
|
|
2028
|
-
skip: void 0,
|
|
2029
|
-
projection: ["id"]
|
|
2030
|
-
});
|
|
2031
|
-
if (r === void 0) throw Error("Restart delivery has no matching resident request");
|
|
2032
|
-
let { request: i, run: a } = await pn(e, c.decodeUnknownSync(Z)(r.id));
|
|
2033
|
-
if (i.runId !== t.runId || i.workflowName !== t.workflowName || i.executionId !== t.executionId || i.generation === t.generation || i.delivery.requestId !== n.requestId || i.token !== n.restartToken) throw Error("Restart entry does not match its reserved delivery");
|
|
2034
|
-
if (i.dispatchAttempts === 0) throw Error("Restart entry has no committed dispatch attempt");
|
|
2035
|
-
if (await e.update("_voltro_workflow_admissions", i.ledgerId, {
|
|
2036
|
-
executionId: i.executionId,
|
|
2037
|
-
runId: i.runId
|
|
2038
|
-
}) === null) throw Error("Restart reservation disappeared during entry");
|
|
2039
|
-
if (await e.update(X.tableName, i.id, { enteredGeneration: t.generation }) === null) throw Error("Restart request disappeared during entry");
|
|
2040
|
-
let o = await e.update("_voltro_workflow_runs", i.runId, {
|
|
2041
|
-
runnerGeneration: t.generation,
|
|
2042
|
-
engineDelivery: n,
|
|
2043
|
-
runnerEnteredAt: new Date(t.now),
|
|
2044
|
-
reclaimCount: 0,
|
|
2045
|
-
status: "running",
|
|
2046
|
-
errorTag: null,
|
|
2047
|
-
errorMessage: null,
|
|
2048
|
-
output: null,
|
|
2049
|
-
completedAt: null,
|
|
2050
|
-
durationMs: null
|
|
2051
|
-
});
|
|
2052
|
-
if (o === null) throw Error("Restart run disappeared during entry");
|
|
2053
|
-
return {
|
|
2054
|
-
row: o,
|
|
2055
|
-
previous: a,
|
|
2056
|
-
event: await e.insert("_voltro_workflow_run_events", {
|
|
2057
|
-
id: m("wfev", JSON.stringify(["restart", i.id])),
|
|
2058
|
-
runId: i.runId,
|
|
2059
|
-
eventType: "run-redriven",
|
|
2060
|
-
occurredAt: new Date(t.now),
|
|
2061
|
-
stepName: null,
|
|
2062
|
-
attempt: null,
|
|
2063
|
-
payload: {
|
|
2064
|
-
requestId: i.id,
|
|
2065
|
-
executionId: i.executionId,
|
|
2066
|
-
previousGeneration: i.generation,
|
|
2067
|
-
generation: t.generation
|
|
2068
|
-
}
|
|
2069
|
-
})
|
|
2070
|
-
};
|
|
2071
|
-
}, _n = 6e5, vn = class extends o.Service()("@voltro/workflow/ClusterDiagnostics") {}, yn = (e, t, n = Date.now()) => s.flatMap(e.messagesFor(t), (t) => {
|
|
2072
|
-
if (t.length === 0) return s.succeed(void 0);
|
|
2073
|
-
let r = [...new Set(t.filter((e) => !e.processed).map((e) => e.shardId))], i = r.length === 0 ? s.succeed([]) : e.shardLockHolders(r);
|
|
2074
|
-
return s.map(i, (r) => ({
|
|
2075
|
-
runner: e.ownAddress,
|
|
2076
|
-
shardLockMode: e.shardLockMode,
|
|
2077
|
-
messages: t.map((e) => ({
|
|
2078
|
-
tag: e.tag,
|
|
2079
|
-
shardId: e.shardId,
|
|
2080
|
-
processed: e.processed,
|
|
2081
|
-
lastRead: e.lastRead === null ? null : e.lastRead.toISOString(),
|
|
2082
|
-
unreadForMs: !e.processed && e.lastRead !== null ? Math.max(0, n - e.lastRead.getTime()) : null
|
|
2083
|
-
})),
|
|
2084
|
-
shardLocks: r
|
|
2085
|
-
}));
|
|
2086
|
-
}), bn = (e) => e.findLast((e, t, n) => t in n && e._tag === "WithExit"), xn = (e) => {
|
|
2087
|
-
let t = /* @__PURE__ */ new Set();
|
|
2088
|
-
for (let n of e) {
|
|
2089
|
-
if (n.eventType !== "update-completed" && n.eventType !== "update-failed") continue;
|
|
2090
|
-
let e = n.payload?.updateId;
|
|
2091
|
-
typeof e == "string" && e.length > 0 && t.add(e);
|
|
2092
|
-
}
|
|
2093
|
-
return t;
|
|
2094
|
-
};
|
|
2095
|
-
//#endregion
|
|
2096
|
-
export { rt as $, Ht as A, Le as At, _t as B, ve as Bt, Bt as C, Ue as Ct, Nt as D, M as Dt, Rt as E, He as Et, I as F, Se as Ft, yt as G, me as Gt, pt as H, ge as Ht, ht as I, xe as It, nt as J, ue as Jt, lt as K, de as Kt, bt as L, Oe as Lt, L as M, Ae as Mt, tt as N, k as Nt, Mt as O, Ie as Ot, R as P, O as Pt, ot as Q, et as R, E as Rt, Vt as S, Me as St, Pt as T, ze as Tt, z as U, fe as Ut, vt as V, ce as Vt, St as W, he as Wt, ct as X, mt as Y, C as Yt, Ct as Z, Gt as _, Be as _t, yn as a, H as at, Ft as b, Ne as bt, cn as c, Qe as ct, hn as d, Ye as dt, dt as et, un as f, Ze as ft, Qt as g, je as gt, Yt as h, Ke as ht, vn as i, xt as it, Ut as j, Re as jt, Y as k, Ge as kt, dn as l, P as lt, en as m, $e as mt, xn as n, at as nt, gn as o, N as ot, X as p, Xe as pt, it as q, le as qt, _n as r, W as rt, ln as s, qe as st, bn as t, ft as tt, fn as u, F as ut, Wt as v, Ve as vt, Lt as w, Fe as wt, zt as x, Pe as xt, Kt as y, We as yt, gt as z, D as zt };
|