@voltro/workflow 0.84.0 → 0.86.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1215 -0
- package/THIRD-PARTY-NOTICES.md +5 -151
- 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 +304 -280
- package/dist/cluster.js +8 -2
- package/dist/clusterCron.js +11 -0
- package/dist/clusterDiagnostics.js +20 -0
- package/dist/clusterDiagnosticsSql.js +145 -0
- package/dist/clusterLayer.js +110 -0
- package/dist/clusterMigrationGate.js +61 -0
- package/dist/clusterRunnerLayer.js +21 -0
- package/dist/clusterTestSuite.d.ts +11 -11
- package/dist/clusterTestSuite.js +257 -257
- 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 +456 -360
- package/dist/index.js +49 -5
- package/dist/inspectWorkflow.js +101 -0
- package/dist/journalEncryption.js +147 -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.d.ts +56 -31
- 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/workflowJournal.js +124 -0
- package/dist/workflowJournalReset.js +111 -0
- package/dist/workflowReadSelections.js +12 -0
- package/dist/workflowRestartDispatch.js +29 -0
- package/dist/workflowRestartObservation.js +60 -0
- package/dist/workflowRestartPreparation.js +109 -0
- package/dist/workflowRestartReservation.js +426 -0
- package/dist/workflowResumeDispatch.js +29 -0
- package/package.json +6 -9
- package/dist/cluster-i3frC3Da.js +0 -646
- package/dist/clusterDiagnostics-CGUtnJkX.js +0 -2084
- package/dist/journalEncryption--n5VDdYO.js +0 -148
- package/dist/primitives-Btjhjm8P.js +0 -483
- package/dist/src-DP-lKqaG.js +0 -3867
package/dist/index.js
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
1
|
+
import { failureMessage as e } from "./failureMessage.js";
|
|
2
|
+
import { attachPreparedWorkflowExecution as t, executePreparedWorkflow as n, hasPreparedWorkflowExecution as r } from "./preparedExecution.js";
|
|
3
|
+
import { STEP_JOURNAL_BINDING as i, WORKFLOW_JOURNAL_BINDING as a, getWorkflowJournalCipher as o, isSealedJournalValue as s, isWorkflowEncrypted as c, openErrorText as l, openEventPayload as u, openJournalValue as d, openPayloadFields as f, openWorkflowRow as p, sealJournalValue as m, setWorkflowJournalCipher as h, tryOpenJournalValue as g } from "./journalEncryption.js";
|
|
4
|
+
import { DEFERRING_CONTROLS as _, assertConsistentPools as v, deferringControlsOf as y, hasCancelOn as b, hasFlowControl as x, validateFlowControl as S } from "./flowControl.js";
|
|
5
|
+
import { CurrentWorkflowExecutionId as C, CurrentWorkflowPatches as w, CurrentWorkflowRunId as T, CurrentWorkflowStep as E, WorkflowRunRecorder as D, WorkflowStepInterceptorTag as O, currentWorkflowStep as k, getCurrentWorkflowExecutionId as A, getCurrentWorkflowRunId as j } from "./recorder.js";
|
|
6
|
+
import { DEFAULT_WORKFLOW_SCHEDULE_MAX_RUNTIME_MS as M, WorkflowScheduleProperty as N, getWorkflowSchedule as P, validateWorkflowSchedule as F } from "./scheduleDeclaration.js";
|
|
7
|
+
import { CurrentWorkflowReplayShape as I, makeReplayShapeTracker as L, nondeterminismEventPayload as R, reportNondeterminism as z } from "./nondeterminism.js";
|
|
8
|
+
import { WorkflowFlowControlProperty as B, WorkflowMessagesProperty as V, WorkflowVersionTypeId as H, WorkflowWorkerLayerTypeId as U, durableClock as W, durableQueue as G, durableQueueModule as K, getWorkflowFlowControl as q, getWorkflowVersionMetadata as J, isCarrier as Y, isWorkflowWorkerLayer as X, patch as Z, processQueue as Q, queueWorker as $, rateLimit as ee, sleep as te, sleepUntil as ne, step as re, stepIdempotencyKey as ie, stepModule as ae, withCompensation as oe, workflow as se, workflowModule as ce } from "./primitives.js";
|
|
9
|
+
import { inMemoryWorkflowEngineLayer as le } from "./inMemoryLayer.js";
|
|
10
|
+
import { _voltroWorkflowRunsTable as ue } from "./runsTable.js";
|
|
11
|
+
import { _voltroWorkflowRunStepsTable as de } from "./runStepsTable.js";
|
|
12
|
+
import { _voltroWorkflowRunEventsTable as fe } from "./runEventsTable.js";
|
|
13
|
+
import { _voltroWorkflowStartContextsTable as pe } from "./startContextsTable.js";
|
|
14
|
+
import { _voltroWorkflowAdmissionLocksTable as me, _voltroWorkflowAdmissionsTable as he, _voltroWorkflowControlRequestsTable as ge, _voltroWorkflowFailureReportsTable as _e, _voltroWorkflowParentClosuresTable as ve, _voltroWorkflowPausesTable as ye, _voltroWorkflowPendingTable as be, _voltroWorkflowStartReceiptsTable as xe, _voltroWorkflowSubmissionsTable as Se } from "./admissionTables.js";
|
|
15
|
+
import { withAdmissionTransaction as Ce } from "./admissionTransaction.js";
|
|
16
|
+
import { FlowControlKeyError as we, comparePendingOrder as Te, decideAdmission as Ee, isFinishExpired as De, isStartExpired as Oe, nextSlotAt as ke, pooledConcurrencyKey as Ae, resolveAdmissionKeys as je } from "./admission.js";
|
|
17
|
+
import { readWorkflowFailureRecord as Me, recordWorkflowFailureInTransaction as Ne } from "./failureReportStore.js";
|
|
18
|
+
import { handoffWorkflowFailureInTransaction as Pe, reconcileWorkflowFailureInTransaction as Fe } from "./failureHandoff.js";
|
|
19
|
+
import { ADMISSION_SUBMISSION_ID_PREFIX as Ie, SUBMISSIONS_TABLE as Le, acknowledgeAdmissionSubmission as Re, beginAdmissionSubmissionDispatchInTransaction as ze, newAdmissionSubmissionId as Be, noteAdmissionSubmissionFailure as Ve, pendingAdmissionSubmissions as He, prepareAdmissionSubmissionExecutionInTransaction as Ue, readAdmissionSubmission as We, rejectAdmissionSubmissionInTransaction as Ge, reserveAdmissionSubmission as Ke, reserveAdmissionSubmissionInTransaction as qe } from "./admissionSubmission.js";
|
|
20
|
+
import { WorkflowStartRequestConflictError as Je, bindWorkflowStartReceipts as Ye, readWorkflowStartReceipt as Xe, readWorkflowStartRequest as Ze, recordWorkflowStartReceipt as Qe, resolveWorkflowStartReceipt as $e } from "./startReceipt.js";
|
|
21
|
+
import { ADMISSIONS_TABLE as et, DEFAULT_LEASE_MS as tt, PAUSES_TABLE as nt, PENDING_TABLE as rt, admissionLeaseHeldPredicate as it, allIntents as at, deadLetterIntent as ot, deleteIntent as st, discardIntent as ct, discardIntentInTransaction as lt, dueIntents as ut, evaluateAdmission as dt, noteIntentAttempt as ft, parkDelayedStart as pt, pauseWorkflow as mt, pendingSlotId as ht, pendingWindow as gt, persistDefer as _t, pruneAdmissions as vt, readAdmissionState as yt, readPausedWorkflows as bt, recordAdmission as xt, releaseLease as St, resumeWorkflow as Ct, retryDeadLetterIntent as wt } from "./admissionStore.js";
|
|
22
|
+
import { acceptWorkflowControlInTransaction as Tt, beginWorkflowControlDispatchInTransaction as Et, bindWorkflowResumeJournalInTransaction as Dt, readWorkflowControlInTransaction as Ot } from "./controlRequest.js";
|
|
23
|
+
import { stageWorkflowParentClosureInTransaction as kt } from "./parentClosure.js";
|
|
24
|
+
import { readWorkflowRestartObservationInTransaction as At, reserveWorkflowRestartInTransaction as jt, withdrawWorkflowRestartInTransaction as Mt, workflowRestartRequestsTable as Nt, workflowRestartWithdrawalsTable as Pt } from "./workflowRestartReservation.js";
|
|
25
|
+
import { cancelSuspendedWorkflowRunInTransaction as Ft, completeWorkflowRunGenerationInTransaction as It, enterWorkflowRunGenerationInTransaction as Lt } from "./runGeneration.js";
|
|
26
|
+
import { queuedCancellationRequestsTable as Rt } from "./queuedCancellationRequest.js";
|
|
27
|
+
import { cancelQueuedWorkflowStartInTransaction as zt, readQueuedWorkflowCancellationInTransaction as Bt } from "./queuedControl.js";
|
|
28
|
+
import { inspectAdmissionSubmissionRetry as Vt, retryAdmissionSubmissionInTransaction as Ht } from "./submissionRetry.js";
|
|
29
|
+
import { takeAdmittedSubmissionInTransaction as Ut, takePendingAdmissionSubmission as Wt } from "./pendingSubmission.js";
|
|
30
|
+
import { admitStart as Gt, linkExecution as Kt } from "./admissionGate.js";
|
|
31
|
+
import { _voltroWorkflowWatermarksTable as qt } from "./watermarkTable.js";
|
|
32
|
+
import { newestEventAt as Jt, planCancellations as Yt } from "./cancelOnPlan.js";
|
|
33
|
+
import { CANCEL_ON_WATERMARK as Xt, DEFAULT_COLD_LOOKBACK_MS as Zt, DEFAULT_EVENT_BATCH as Qt, EVENTS_TABLE as $t, WATERMARKS_TABLE as en, readWatermark as tn, sweepCancelOn as nn, writeWatermark as rn } from "./cancelOnSweep.js";
|
|
34
|
+
import { DEFAULT_STALL_AFTER_MS as an, DEFAULT_STALL_EVENT_LOOKBACK as on, DEFAULT_STALL_RUN_PAGE as sn, sweepStalledRuns as cn } from "./stalenessSweep.js";
|
|
35
|
+
import { CLUSTER_REREAD_WINDOW_MS as ln, ClusterDiagnostics as un, describeStalledRun as dn } from "./clusterDiagnostics.js";
|
|
36
|
+
import { DEFAULT_DRAIN_BATCH as fn, acceptAdmissionSubmission as pn, drainTick as mn, isUnacknowledgedSubmission as hn } from "./admissionDrainer.js";
|
|
37
|
+
import { DEFAULT_SUSPEND_HINT_MS as gn, maybeHintSuspendingSignal as _n, resetSuspendHintsForTest as vn, resolveSuspendHintMs as yn, setSuspendSignalHintMs as bn } from "./signalHint.js";
|
|
38
|
+
import { awaitSignal as xn } from "./signals.js";
|
|
39
|
+
import { awaitEvent as Sn } from "./awaitEvent.js";
|
|
40
|
+
import { SuspensionUnavailable as Cn, WorkflowCannotPark as wn } from "./suspensionUnavailable.js";
|
|
41
|
+
import { makeWorkflowUpdateId as Tn, resolveWorkflowMessageRun as En, sendWorkflowSignal as Dn, sendWorkflowUpdate as On } from "./messages.js";
|
|
42
|
+
import { awaitSignalSuspending as kn, completeSuspendingSignal as An, suspendingSignalDeferredName as jn } from "./signalsSuspending.js";
|
|
43
|
+
import { BUDGET_HOLDS_TABLE as Mn, BudgetHoldExpired as Nn, DEFAULT_BUDGET_HOLD_TIMEOUT_MS as Pn, _voltroBudgetHoldsTable as Fn, budgetHoldGeneration as In, budgetHoldKey as Ln, budgetHoldSignalName as Rn, heldBudgets as zn, pendingBudgetHolds as Bn, releaseBudgetHolds as Vn, suspendForBudget as Hn } from "./budgetHold.js";
|
|
44
|
+
import { awaitUpdate as Un } from "./updates.js";
|
|
45
|
+
import { inspectWorkflow as Wn } from "./inspectWorkflow.js";
|
|
46
|
+
import { makeInMemoryRecorder as Gn } from "./inMemoryRecorder.js";
|
|
47
|
+
import { DEFAULT_MAX_RUN_RECLAIMS as Kn, DEFAULT_REPLAY_SHAPE_LIMIT as qn, makeWorkflowRunRecorder as Jn, normaliseWorkflowPatches as Yn, resolveRunGuardTuning as Xn, serialiseWorkflowRowForWire as Zn, truncateWorkflowValue as Qn, wrapWorkflowExecuteWithRunRecording as $n } from "./runRecording.js";
|
|
48
|
+
import { recordWorkflowExecutionRefusal as er } from "./executionRefusal.js";
|
|
49
|
+
export { et as ADMISSIONS_TABLE, Ie as ADMISSION_SUBMISSION_ID_PREFIX, Mn as BUDGET_HOLDS_TABLE, Nn as BudgetHoldExpired, Xt as CANCEL_ON_WATERMARK, ln as CLUSTER_REREAD_WINDOW_MS, un as ClusterDiagnostics, C as CurrentWorkflowExecutionId, w as CurrentWorkflowPatches, I as CurrentWorkflowReplayShape, T as CurrentWorkflowRunId, E as CurrentWorkflowStep, Pn as DEFAULT_BUDGET_HOLD_TIMEOUT_MS, Zt as DEFAULT_COLD_LOOKBACK_MS, fn as DEFAULT_DRAIN_BATCH, Qt as DEFAULT_EVENT_BATCH, tt as DEFAULT_LEASE_MS, Kn as DEFAULT_MAX_RUN_RECLAIMS, qn as DEFAULT_REPLAY_SHAPE_LIMIT, an as DEFAULT_STALL_AFTER_MS, on as DEFAULT_STALL_EVENT_LOOKBACK, sn as DEFAULT_STALL_RUN_PAGE, gn as DEFAULT_SUSPEND_HINT_MS, M as DEFAULT_WORKFLOW_SCHEDULE_MAX_RUNTIME_MS, _ as DEFERRING_CONTROLS, $t as EVENTS_TABLE, we as FlowControlKeyError, nt as PAUSES_TABLE, rt as PENDING_TABLE, i as STEP_JOURNAL_BINDING, Le as SUBMISSIONS_TABLE, Cn as SuspensionUnavailable, en as WATERMARKS_TABLE, a as WORKFLOW_JOURNAL_BINDING, wn as WorkflowCannotPark, B as WorkflowFlowControlProperty, V as WorkflowMessagesProperty, D as WorkflowRunRecorder, N as WorkflowScheduleProperty, Je as WorkflowStartRequestConflictError, O as WorkflowStepInterceptorTag, H as WorkflowVersionTypeId, U as WorkflowWorkerLayerTypeId, Fn as _voltroBudgetHoldsTable, me as _voltroWorkflowAdmissionLocksTable, he as _voltroWorkflowAdmissionsTable, ge as _voltroWorkflowControlRequestsTable, _e as _voltroWorkflowFailureReportsTable, ve as _voltroWorkflowParentClosuresTable, ye as _voltroWorkflowPausesTable, be as _voltroWorkflowPendingTable, fe as _voltroWorkflowRunEventsTable, de as _voltroWorkflowRunStepsTable, ue as _voltroWorkflowRunsTable, pe as _voltroWorkflowStartContextsTable, xe as _voltroWorkflowStartReceiptsTable, Se as _voltroWorkflowSubmissionsTable, qt as _voltroWorkflowWatermarksTable, pn as acceptAdmissionSubmission, Tt as acceptWorkflowControlInTransaction, Re as acknowledgeAdmissionSubmission, it as admissionLeaseHeldPredicate, Gt as admitStart, at as allIntents, v as assertConsistentPools, t as attachPreparedWorkflowExecution, Sn as awaitEvent, xn as awaitSignal, kn as awaitSignalSuspending, Un as awaitUpdate, ze as beginAdmissionSubmissionDispatchInTransaction, Et as beginWorkflowControlDispatchInTransaction, Dt as bindWorkflowResumeJournalInTransaction, Ye as bindWorkflowStartReceipts, In as budgetHoldGeneration, Ln as budgetHoldKey, Rn as budgetHoldSignalName, zt as cancelQueuedWorkflowStartInTransaction, Ft as cancelSuspendedWorkflowRunInTransaction, Te as comparePendingOrder, An as completeSuspendingSignal, It as completeWorkflowRunGenerationInTransaction, k as currentWorkflowStep, ot as deadLetterIntent, Ee as decideAdmission, y as deferringControlsOf, st as deleteIntent, dn as describeStalledRun, ct as discardIntent, lt as discardIntentInTransaction, mn as drainTick, ut as dueIntents, W as durableClock, G as durableQueue, K as durableQueueModule, Lt as enterWorkflowRunGenerationInTransaction, dt as evaluateAdmission, n as executePreparedWorkflow, e as failureMessage, A as getCurrentWorkflowExecutionId, j as getCurrentWorkflowRunId, q as getWorkflowFlowControl, o as getWorkflowJournalCipher, P as getWorkflowSchedule, J as getWorkflowVersionMetadata, Pe as handoffWorkflowFailureInTransaction, b as hasCancelOn, x as hasFlowControl, r as hasPreparedWorkflowExecution, zn as heldBudgets, le as inMemoryWorkflowEngineLayer, Vt as inspectAdmissionSubmissionRetry, Wn as inspectWorkflow, Y as isCarrier, De as isFinishExpired, s as isSealedJournalValue, Oe as isStartExpired, hn as isUnacknowledgedSubmission, c as isWorkflowEncrypted, X as isWorkflowWorkerLayer, Kt as linkExecution, Gn as makeInMemoryRecorder, L as makeReplayShapeTracker, Jn as makeWorkflowRunRecorder, Tn as makeWorkflowUpdateId, _n as maybeHintSuspendingSignal, Be as newAdmissionSubmissionId, Jt as newestEventAt, ke as nextSlotAt, R as nondeterminismEventPayload, Yn as normaliseWorkflowPatches, Ve as noteAdmissionSubmissionFailure, ft as noteIntentAttempt, l as openErrorText, u as openEventPayload, d as openJournalValue, f as openPayloadFields, p as openWorkflowRow, pt as parkDelayedStart, Z as patch, mt as pauseWorkflow, He as pendingAdmissionSubmissions, Bn as pendingBudgetHolds, ht as pendingSlotId, gt as pendingWindow, _t as persistDefer, Yt as planCancellations, Ae as pooledConcurrencyKey, Ue as prepareAdmissionSubmissionExecutionInTransaction, Q as processQueue, vt as pruneAdmissions, $ as queueWorker, Rt as queuedCancellationRequestsTable, ee as rateLimit, yt as readAdmissionState, We as readAdmissionSubmission, bt as readPausedWorkflows, Bt as readQueuedWorkflowCancellationInTransaction, tn as readWatermark, Ot as readWorkflowControlInTransaction, Me as readWorkflowFailureRecord, At as readWorkflowRestartObservationInTransaction, Xe as readWorkflowStartReceipt, Ze as readWorkflowStartRequest, Fe as reconcileWorkflowFailureInTransaction, xt as recordAdmission, er as recordWorkflowExecutionRefusal, Ne as recordWorkflowFailureInTransaction, Qe as recordWorkflowStartReceipt, Ge as rejectAdmissionSubmissionInTransaction, Vn as releaseBudgetHolds, St as releaseLease, z as reportNondeterminism, Ke as reserveAdmissionSubmission, qe as reserveAdmissionSubmissionInTransaction, jt as reserveWorkflowRestartInTransaction, vn as resetSuspendHintsForTest, je as resolveAdmissionKeys, Xn as resolveRunGuardTuning, yn as resolveSuspendHintMs, En as resolveWorkflowMessageRun, $e as resolveWorkflowStartReceipt, Ct as resumeWorkflow, Ht as retryAdmissionSubmissionInTransaction, wt as retryDeadLetterIntent, m as sealJournalValue, Dn as sendWorkflowSignal, On as sendWorkflowUpdate, Zn as serialiseWorkflowRowForWire, bn as setSuspendSignalHintMs, h as setWorkflowJournalCipher, te as sleep, ne as sleepUntil, kt as stageWorkflowParentClosureInTransaction, re as step, ie as stepIdempotencyKey, ae as stepModule, Hn as suspendForBudget, jn as suspendingSignalDeferredName, nn as sweepCancelOn, cn as sweepStalledRuns, Ut as takeAdmittedSubmissionInTransaction, Wt as takePendingAdmissionSubmission, Qn as truncateWorkflowValue, g as tryOpenJournalValue, S as validateFlowControl, F as validateWorkflowSchedule, Ce as withAdmissionTransaction, oe as withCompensation, Mt as withdrawWorkflowRestartInTransaction, se as workflow, ce as workflowModule, Nt as workflowRestartRequestsTable, Pt as workflowRestartWithdrawalsTable, $n as wrapWorkflowExecuteWithRunRecording, rn as writeWatermark };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { openJournalValue as e, openPayloadFields as t } from "./journalEncryption.js";
|
|
2
|
+
import { _voltroWorkflowRunsTable as n } from "./runsTable.js";
|
|
3
|
+
import { _voltroWorkflowRunStepsTable as r } from "./runStepsTable.js";
|
|
4
|
+
import { eq as i, or as a, queryFor as o } from "@voltro/database";
|
|
5
|
+
import { types as s } from "node:util";
|
|
6
|
+
//#region src/inspectWorkflow.ts
|
|
7
|
+
var c = (e) => {
|
|
8
|
+
if (e == null) return null;
|
|
9
|
+
if (e instanceof Date) return e;
|
|
10
|
+
if (typeof e == "string" || typeof e == "number") {
|
|
11
|
+
let t = new Date(e);
|
|
12
|
+
return Number.isNaN(t.getTime()) ? null : t;
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}, l = (e) => typeof e == "number" ? e : e == null ? null : Number(e), u = (e) => e == null ? null : String(e), d = (e) => {
|
|
16
|
+
if (s.isProxy(e)) return !1;
|
|
17
|
+
let t = Object.getPrototypeOf(e);
|
|
18
|
+
if (t !== null && t !== Object.prototype) return !1;
|
|
19
|
+
for (let t of Reflect.ownKeys(e)) {
|
|
20
|
+
let n = Object.getOwnPropertyDescriptor(e, t);
|
|
21
|
+
if (n === void 0 || !("value" in n)) return !1;
|
|
22
|
+
}
|
|
23
|
+
let n = Object.getOwnPropertyDescriptor(e, "stepName");
|
|
24
|
+
if (n === void 0 || !("value" in n) || typeof n.value != "string") return !1;
|
|
25
|
+
for (let t of [
|
|
26
|
+
"attempt",
|
|
27
|
+
"durationMs",
|
|
28
|
+
"errorTag",
|
|
29
|
+
"errorMessage",
|
|
30
|
+
"startedAt"
|
|
31
|
+
]) {
|
|
32
|
+
let n = Object.getOwnPropertyDescriptor(e, t);
|
|
33
|
+
if (n === void 0) {
|
|
34
|
+
if (t in e) return !1;
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
let r = n.value;
|
|
38
|
+
if (typeof r == "object" && r && s.isProxy(r) || !(t === "startedAt" && r instanceof Date && Object.getPrototypeOf(r) === Date.prototype && Reflect.ownKeys(r).length === 0) && r != null && typeof r != "number" && typeof r != "string" && typeof r != "boolean") return !1;
|
|
39
|
+
}
|
|
40
|
+
return !0;
|
|
41
|
+
}, f = (e) => {
|
|
42
|
+
let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map(), r = !s.isProxy(e) && Object.getPrototypeOf(e) === Array.prototype && !Object.hasOwn(e, Symbol.iterator) && e.find === Array.prototype.find, i = 0;
|
|
43
|
+
for (let a of e) {
|
|
44
|
+
let o = r ? Object.getOwnPropertyDescriptor(e, String(i)) : void 0;
|
|
45
|
+
(o === void 0 || !("value" in o) || !d(a)) && (r = !1), i++;
|
|
46
|
+
let s = String(a.stepName), c = t.get(s);
|
|
47
|
+
c === void 0 ? (t.set(s, [a]), n.set(s, a)) : c.push(a);
|
|
48
|
+
}
|
|
49
|
+
let a = [];
|
|
50
|
+
for (let [e, n] of t) {
|
|
51
|
+
n.sort((e, t) => (l(e.attempt) ?? 0) - (l(t.attempt) ?? 0));
|
|
52
|
+
let t = n[n.length - 1], r = u(t.errorTag), i = u(t.errorMessage), o = r !== null || i !== null ? {
|
|
53
|
+
tag: r,
|
|
54
|
+
message: i ?? ""
|
|
55
|
+
} : null;
|
|
56
|
+
a.push({
|
|
57
|
+
name: e,
|
|
58
|
+
attempt: l(t.attempt) ?? n.length,
|
|
59
|
+
attempts: n.length,
|
|
60
|
+
status: t.status ?? "running",
|
|
61
|
+
input: t.input ?? null,
|
|
62
|
+
output: t.output ?? null,
|
|
63
|
+
error: o,
|
|
64
|
+
durationMs: l(t.durationMs)
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return a.sort((t, i) => {
|
|
68
|
+
let a = r ? n.get(t.name) : e.find((e) => String(e.stepName) === t.name), o = r ? n.get(i.name) : e.find((e) => String(e.stepName) === i.name);
|
|
69
|
+
return (c(a?.startedAt)?.getTime() ?? 0) - (c(o?.startedAt)?.getTime() ?? 0);
|
|
70
|
+
}), a;
|
|
71
|
+
}, p = (e) => {
|
|
72
|
+
if (e == null) return null;
|
|
73
|
+
if (typeof e == "string") try {
|
|
74
|
+
return JSON.parse(e);
|
|
75
|
+
} catch {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
return typeof e == "object" ? e : null;
|
|
79
|
+
}, m = async (s, l) => {
|
|
80
|
+
let d = o(n), m = (await l.query(d.where(a(i("id", s), i("executionId", s))).limit(1).descriptor))[0];
|
|
81
|
+
if (m === void 0) return null;
|
|
82
|
+
let h = String(m.id), g = o(r), _ = await l.query(g.where(i("runId", h)).descriptor);
|
|
83
|
+
return {
|
|
84
|
+
id: h,
|
|
85
|
+
executionId: u(m.executionId) ?? "",
|
|
86
|
+
name: u(m.tag) ?? "",
|
|
87
|
+
status: m.status ?? "running",
|
|
88
|
+
input: t(m.payload ?? null, "workflow run payload"),
|
|
89
|
+
output: e(m.output ?? null, "workflow run result"),
|
|
90
|
+
subject: p(m.subject),
|
|
91
|
+
source: u(m.source),
|
|
92
|
+
steps: f(_),
|
|
93
|
+
startedAt: c(m.startedAt) ?? /* @__PURE__ */ new Date(0),
|
|
94
|
+
finishedAt: c(m.completedAt),
|
|
95
|
+
traceId: u(m.traceId),
|
|
96
|
+
parentExecutionId: u(m.parentExecutionId),
|
|
97
|
+
parentClosePolicy: u(m.parentClosePolicy)
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
//#endregion
|
|
101
|
+
export { m as inspectWorkflow };
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { failureMessage as e } from "./failureMessage.js";
|
|
2
|
+
import { Activity as t } from "effect/workflow";
|
|
3
|
+
import { Cause as n, Context as r, Effect as i, Effectable as a, Schema as o, SchemaAST as s, SchemaGetter as c, SchemaIssue as l } from "effect";
|
|
4
|
+
//#region src/journalEncryption.ts
|
|
5
|
+
var u = () => void 0, d = (e) => {
|
|
6
|
+
u = typeof e == "function" ? e : () => e;
|
|
7
|
+
}, f = () => u(), p = r.Reference("@voltro/workflow/CurrentWorkflowEncrypted", { defaultValue: () => !1 }), m = { column: "workflow-journal" }, h = /* @__PURE__ */ new Set(), g = (e) => {
|
|
8
|
+
h.add(e);
|
|
9
|
+
}, _ = /* @__PURE__ */ new Set(), v = (e) => {
|
|
10
|
+
_.add(e);
|
|
11
|
+
}, y = (e) => _.has(e), b = (e) => h.has(e), x = (e) => typeof e == "string" && (e.startsWith("enc:v1:") || e.startsWith("enc:v2:")), S = (e) => /* @__PURE__ */ Error(`${e}: the workflow is declared encrypted, but no field-encryption key is registered — set VOLTRO_FIELD_ENCRYPTION_KEY (\`voltro secret generate field-encryption\`). Nothing was written in plaintext instead.`), C = (e, t, n = m) => {
|
|
12
|
+
if (e == null) return e;
|
|
13
|
+
let r = u();
|
|
14
|
+
if (r === void 0) throw S(t);
|
|
15
|
+
return r.encrypt(JSON.stringify(e), n);
|
|
16
|
+
}, w = (e, t, n = m) => {
|
|
17
|
+
if (!x(e)) return e;
|
|
18
|
+
let r = u();
|
|
19
|
+
if (r === void 0) throw S(t);
|
|
20
|
+
return JSON.parse(r.decrypt(e, n));
|
|
21
|
+
}, T = (e) => s.isVoid(e) || s.isNever(e) || s.isUndefined(e), E = (e, t) => {
|
|
22
|
+
if (T(e.ast)) return e;
|
|
23
|
+
let n = (e, t) => {
|
|
24
|
+
try {
|
|
25
|
+
return i.succeed(t());
|
|
26
|
+
} catch (t) {
|
|
27
|
+
return i.fail(new l.InvalidValue({ message: t.message }, e));
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
return (e.ast.context?.isOptional === !0 ? o.optionalKey(o.Unknown) : o.Unknown).pipe(o.decodeTo(e, {
|
|
31
|
+
decode: c.transformEffect((e) => n(e, () => Array.isArray(e) ? e.map((e) => w(e, t)) : w(e, t))),
|
|
32
|
+
encode: c.transformEffect((e) => n(e, () => e === void 0 ? void 0 : C(e, t)))
|
|
33
|
+
}));
|
|
34
|
+
}, D = (e, t) => {
|
|
35
|
+
let n = o.isSchema(t) ? t.fields : t, r = `workflow '${e}' payload`, i = {};
|
|
36
|
+
for (let [e, t] of Object.entries(n)) i[e] = E(t, `${r}.${e}`);
|
|
37
|
+
return i;
|
|
38
|
+
}, O = (e) => typeof e == "object" && !!e && !Array.isArray(e), k = (e, t) => {
|
|
39
|
+
if (!O(e)) return w(e, t);
|
|
40
|
+
let n = {};
|
|
41
|
+
for (let [r, i] of Object.entries(e)) n[r] = w(i, `${t}.${r}`);
|
|
42
|
+
return n;
|
|
43
|
+
}, A = (e, t) => {
|
|
44
|
+
let n = {};
|
|
45
|
+
for (let [r, i] of Object.entries(e)) n[r] = C(i, `${t}.${r}`);
|
|
46
|
+
return n;
|
|
47
|
+
}, j = "VoltroSealedDefect", M = (e, t) => {
|
|
48
|
+
if (e instanceof Error && e.name === "VoltroSealedDefect") return e;
|
|
49
|
+
let n = e instanceof Error ? {
|
|
50
|
+
name: e.name,
|
|
51
|
+
message: e.message,
|
|
52
|
+
...e.stack === void 0 ? {} : { stack: e.stack }
|
|
53
|
+
} : {
|
|
54
|
+
name: "Defect",
|
|
55
|
+
message: typeof e == "string" ? e : P(e)
|
|
56
|
+
}, r = Error(String(C(n, t)));
|
|
57
|
+
return r.name = j, r.stack = `${j}: ${r.message}`, r;
|
|
58
|
+
}, N = (e, t) => {
|
|
59
|
+
let n = e?.name, r = e?.message;
|
|
60
|
+
if (n !== "VoltroSealedDefect" || typeof r != "string" || !x(r)) return e;
|
|
61
|
+
try {
|
|
62
|
+
let e = w(r, t), n = Error(e.message ?? "");
|
|
63
|
+
return n.name = e.name ?? "Error", e.stack !== void 0 && (n.stack = e.stack), n;
|
|
64
|
+
} catch {
|
|
65
|
+
return e;
|
|
66
|
+
}
|
|
67
|
+
}, P = (e) => {
|
|
68
|
+
try {
|
|
69
|
+
return JSON.stringify(e) ?? String(e);
|
|
70
|
+
} catch {
|
|
71
|
+
return String(e);
|
|
72
|
+
}
|
|
73
|
+
}, F = () => h.size > 0, I = (e, t) => t == null ? null : b(e) ? String(C(t, `workflow '${e}' error message`)) : t, L = (e, t) => {
|
|
74
|
+
try {
|
|
75
|
+
return w(e, t);
|
|
76
|
+
} catch {
|
|
77
|
+
return e;
|
|
78
|
+
}
|
|
79
|
+
}, R = (e) => {
|
|
80
|
+
if (e == null) return null;
|
|
81
|
+
let t = L(e, "workflow error message");
|
|
82
|
+
return typeof t == "string" ? t : e;
|
|
83
|
+
}, z = [
|
|
84
|
+
"value",
|
|
85
|
+
"result",
|
|
86
|
+
"errorMessage"
|
|
87
|
+
], B = (e, t) => {
|
|
88
|
+
if (t == null) return null;
|
|
89
|
+
if (!b(e)) return t;
|
|
90
|
+
let n = { ...t };
|
|
91
|
+
for (let t of z) t in n && n[t] !== void 0 && n[t] !== null && !x(n[t]) && (n[t] = C(n[t], `workflow '${e}' event ${t}`));
|
|
92
|
+
return n;
|
|
93
|
+
}, V = (e) => {
|
|
94
|
+
if (!O(e)) return e;
|
|
95
|
+
let t = { ...e };
|
|
96
|
+
for (let e of z) x(t[e]) && (t[e] = L(t[e], `workflow event ${e}`));
|
|
97
|
+
return t;
|
|
98
|
+
}, H = (e) => {
|
|
99
|
+
let n = t.make({
|
|
100
|
+
...e,
|
|
101
|
+
error: o.Defect()
|
|
102
|
+
}), r, s = `wait '${e.name}'`, c = () => r ??= t.make({
|
|
103
|
+
...e,
|
|
104
|
+
success: E(e.success, `${s} value`),
|
|
105
|
+
error: o.Defect(),
|
|
106
|
+
execute: e.execute.pipe(i.catchDefect((e) => i.die(M(e, `${s} defect`))))
|
|
107
|
+
}), l = n;
|
|
108
|
+
return {
|
|
109
|
+
...n,
|
|
110
|
+
...a.Prototype({
|
|
111
|
+
label: "Activity",
|
|
112
|
+
evaluate: () => i.flatMap(p, (e) => e ? c().pipe(i.catchDefect((e) => i.die(N(e, `${s} defect`)))) : l)
|
|
113
|
+
})
|
|
114
|
+
};
|
|
115
|
+
}, U = { column: "_voltro_workflow_run_steps:payload" }, W = (e) => {
|
|
116
|
+
if (!x(e)) return e;
|
|
117
|
+
try {
|
|
118
|
+
return w(e, "workflow step value", U);
|
|
119
|
+
} catch {
|
|
120
|
+
return e;
|
|
121
|
+
}
|
|
122
|
+
}, G = (e) => {
|
|
123
|
+
if (!O(e)) return e;
|
|
124
|
+
let t = { ...e };
|
|
125
|
+
if ("eventType" in t) return "payload" in t && (t.payload = V(t.payload)), t;
|
|
126
|
+
if ("stepName" in t && ("input" in t || "errorCause" in t)) {
|
|
127
|
+
for (let e of [
|
|
128
|
+
"input",
|
|
129
|
+
"output",
|
|
130
|
+
"errorCause",
|
|
131
|
+
"errorMessage"
|
|
132
|
+
]) e in t && (t[e] = W(t[e]));
|
|
133
|
+
return t;
|
|
134
|
+
}
|
|
135
|
+
if ("payload" in t) try {
|
|
136
|
+
t.payload = k(t.payload, "workflow run payload");
|
|
137
|
+
} catch {}
|
|
138
|
+
return "output" in t && (t.output = L(t.output, "workflow run result")), typeof t.errorMessage == "string" && (t.errorMessage = R(t.errorMessage)), t;
|
|
139
|
+
}, K = (t, r) => {
|
|
140
|
+
if (t === void 0 || !b(t)) {
|
|
141
|
+
let t = n.isCause(r) ? n.squash(r) : r;
|
|
142
|
+
return t instanceof Error && t.message.length > 0 ? `${t.name}: ${t.message}` : e(t);
|
|
143
|
+
}
|
|
144
|
+
return `${r instanceof Error ? r.name : typeof r}: [withheld — workflow '${t}' is declared encrypted; the full cause is recorded sealed on its row]`;
|
|
145
|
+
};
|
|
146
|
+
//#endregion
|
|
147
|
+
export { p as CurrentWorkflowEncrypted, j as SEALED_DEFECT_NAME, U as STEP_JOURNAL_BINDING, m as WORKFLOW_JOURNAL_BINDING, F as anyWorkflowEncrypted, H as encryptionAwareActivity, f as getWorkflowJournalCipher, y as isQueueEncrypted, x as isSealedJournalValue, b as isWorkflowEncrypted, K as loggableCause, v as markQueueEncrypted, g as markWorkflowEncrypted, N as openDefect, R as openErrorText, V as openEventPayload, w as openJournalValue, k as openPayloadFields, G as openWorkflowRow, M as sealDefect, I as sealErrorText, B as sealEventPayload, C as sealJournalValue, A as sealPayloadFields, D as sealedPayloadFields, E as sealedSchema, d as setWorkflowJournalCipher, L as tryOpenJournalValue };
|
package/dist/messages.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { openEventPayload as e } from "./journalEncryption.js";
|
|
2
|
+
import { eq as t } from "@voltro/database";
|
|
3
|
+
//#region src/messages.ts
|
|
4
|
+
var n = (e) => new Promise((t) => setTimeout(t, e)), r = () => {
|
|
5
|
+
let e = globalThis.crypto;
|
|
6
|
+
return typeof e?.randomUUID == "function" ? e.randomUUID() : `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`;
|
|
7
|
+
}, i = () => `wfu_${r()}`, a = async (e, n) => {
|
|
8
|
+
let r = n.id ?? n.executionId;
|
|
9
|
+
if (!r) throw Error("workflow message target requires target.id or target.executionId");
|
|
10
|
+
let i = await e.query({
|
|
11
|
+
table: "_voltro_workflow_runs",
|
|
12
|
+
order: [],
|
|
13
|
+
predicate: t("id", r),
|
|
14
|
+
projection: void 0,
|
|
15
|
+
skip: void 0,
|
|
16
|
+
take: 1
|
|
17
|
+
});
|
|
18
|
+
if (i[0]) return i[0];
|
|
19
|
+
let a = (await e.query({
|
|
20
|
+
table: "_voltro_workflow_runs",
|
|
21
|
+
order: [],
|
|
22
|
+
predicate: t("executionId", r),
|
|
23
|
+
projection: void 0,
|
|
24
|
+
skip: void 0,
|
|
25
|
+
take: 1
|
|
26
|
+
}))[0];
|
|
27
|
+
if (!a) throw Error(`workflow message target not found: ${r}`);
|
|
28
|
+
return a;
|
|
29
|
+
}, o = class extends Error {
|
|
30
|
+
runId;
|
|
31
|
+
eventType;
|
|
32
|
+
eventId;
|
|
33
|
+
_tag = "WorkflowMessageNotRecorded";
|
|
34
|
+
constructor(e, t, n) {
|
|
35
|
+
super(`workflow ${t} for run ${e} was NOT recorded (event ${n}): the run will not see it — the store refused the row, see the recorder's warning`), this.runId = e, this.eventType = t, this.eventId = n, this.name = "WorkflowMessageNotRecorded";
|
|
36
|
+
}
|
|
37
|
+
}, s = async (e) => {
|
|
38
|
+
let t = await a(e.store, e.target), n = await e.recorder.recordEvent({
|
|
39
|
+
runId: t.id,
|
|
40
|
+
eventType: "signal-sent",
|
|
41
|
+
payload: {
|
|
42
|
+
signalName: e.signalName,
|
|
43
|
+
value: e.payload
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
if (n.recorded === !1) throw new o(t.id, "signal-sent", n.id);
|
|
47
|
+
return { eventId: n.id };
|
|
48
|
+
}, c = async (r) => {
|
|
49
|
+
let s = await a(r.store, r.target), c = i(), l = await r.recorder.recordEvent({
|
|
50
|
+
runId: s.id,
|
|
51
|
+
eventType: "update-requested",
|
|
52
|
+
payload: {
|
|
53
|
+
updateId: c,
|
|
54
|
+
updateName: r.updateName,
|
|
55
|
+
value: r.payload
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
if (l.recorded === !1) throw new o(s.id, "update-requested", l.id);
|
|
59
|
+
let u = Date.now(), d = r.options?.timeoutMs ?? 3e4, f = r.options?.pollIntervalMs ?? 100;
|
|
60
|
+
for (;;) {
|
|
61
|
+
let i = {
|
|
62
|
+
table: "_voltro_workflow_run_events",
|
|
63
|
+
order: [{
|
|
64
|
+
column: "occurredAt",
|
|
65
|
+
direction: "asc"
|
|
66
|
+
}],
|
|
67
|
+
predicate: t("runId", s.id),
|
|
68
|
+
projection: void 0,
|
|
69
|
+
skip: void 0,
|
|
70
|
+
take: 1e3
|
|
71
|
+
}, a = await r.store.query(i), o = a.find((e) => e.eventType === "update-completed" && e.payload?.updateId === c);
|
|
72
|
+
if (o) return {
|
|
73
|
+
eventId: l.id,
|
|
74
|
+
updateId: c,
|
|
75
|
+
completedEventId: o.id,
|
|
76
|
+
result: e(o.payload)?.result
|
|
77
|
+
};
|
|
78
|
+
let p = a.find((e) => e.eventType === "update-failed" && e.payload?.updateId === c);
|
|
79
|
+
if (p) {
|
|
80
|
+
let t = Error(e(p.payload)?.errorMessage ?? `workflow update '${r.updateName}' failed`);
|
|
81
|
+
throw Object.assign(t, {
|
|
82
|
+
updateId: c,
|
|
83
|
+
eventId: l.id,
|
|
84
|
+
errorTag: p.payload?.errorTag ?? null
|
|
85
|
+
}), t;
|
|
86
|
+
}
|
|
87
|
+
if (Date.now() - u >= d) throw Error(`Timed out waiting for workflow update '${r.updateName}' (${c})`);
|
|
88
|
+
await n(f);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
//#endregion
|
|
92
|
+
export { o as WorkflowMessageNotRecorded, i as makeWorkflowUpdateId, a as resolveWorkflowMessageRun, s as sendWorkflowSignal, c as sendWorkflowUpdate };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { CurrentWorkflowRunId as e, WorkflowRunRecorder as t } from "./recorder.js";
|
|
2
|
+
import { Context as n, Effect as r } from "effect";
|
|
3
|
+
//#region src/nondeterminism.ts
|
|
4
|
+
var i = (e) => {
|
|
5
|
+
let t = /* @__PURE__ */ new Map();
|
|
6
|
+
for (let n of e) t.set(n.stepName, (t.get(n.stepName) ?? 0) + 1);
|
|
7
|
+
let n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Set(), i = (e) => !r.has(e) && (r.add(e), !0);
|
|
8
|
+
return {
|
|
9
|
+
reach: (e) => {
|
|
10
|
+
let r = (n.get(e) ?? 0) + 1;
|
|
11
|
+
n.set(e, r);
|
|
12
|
+
let a = t.get(e) ?? 0;
|
|
13
|
+
if (a !== 0 && !(r <= a) && i(`extra:${e}`)) return {
|
|
14
|
+
kind: "extra-step-occurrence",
|
|
15
|
+
stepName: e,
|
|
16
|
+
recorded: a,
|
|
17
|
+
reached: r,
|
|
18
|
+
detail: `step '${e}' was reached ${r} time(s) on this attempt but this run only ever recorded ${a} — the body may have changed how often it runs this step (a loop bound), so the journal replays a result for an iteration the code no longer means.`
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
settle: () => {
|
|
22
|
+
let e = [];
|
|
23
|
+
for (let [r, a] of t) (n.get(r) ?? 0) > 0 || i(`unreached:${r}`) && e.push({
|
|
24
|
+
kind: "unreached-step",
|
|
25
|
+
stepName: r,
|
|
26
|
+
recorded: a,
|
|
27
|
+
reached: 0,
|
|
28
|
+
detail: `step '${r}' ran on an earlier attempt of this run but the current code never reaches it — the step was renamed, removed, or moved behind a branch, so its journaled result is orphaned and any step that replaced it executed fresh.`
|
|
29
|
+
});
|
|
30
|
+
return e;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}, a = n.Reference("@voltro/workflow/CurrentWorkflowReplayShape", { defaultValue: () => void 0 }), o = (e) => ({
|
|
34
|
+
kind: e.kind,
|
|
35
|
+
stepName: e.stepName,
|
|
36
|
+
recorded: e.recorded,
|
|
37
|
+
reached: e.reached,
|
|
38
|
+
detail: e.detail
|
|
39
|
+
}), s = (n) => r.gen(function* () {
|
|
40
|
+
if (n.length === 0) return;
|
|
41
|
+
let i = yield* e, a = yield* r.serviceOption(t);
|
|
42
|
+
if (i === void 0 || a._tag !== "Some") return;
|
|
43
|
+
let s = a.value;
|
|
44
|
+
for (let e of n) yield* r.promise(() => s.recordEvent({
|
|
45
|
+
runId: i,
|
|
46
|
+
eventType: "nondeterminism-suspected",
|
|
47
|
+
payload: o(e)
|
|
48
|
+
}).then(() => void 0).catch(() => void 0));
|
|
49
|
+
});
|
|
50
|
+
//#endregion
|
|
51
|
+
export { a as CurrentWorkflowReplayShape, i as makeReplayShapeTracker, o as nondeterminismEventPayload, s as reportNondeterminism };
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { acceptWorkflowControlInTransaction as e, hasUnsettledParentClosureControls as t, readWorkflowControlInTransaction as n } from "./controlRequest.js";
|
|
2
|
+
import { cancelSuspendedWorkflowRunInTransaction as r } from "./runGeneration.js";
|
|
3
|
+
import { Schema as i } from "effect";
|
|
4
|
+
import { and as a, derivedRowId as o, eq as s, gt as c } from "@voltro/database";
|
|
5
|
+
//#region src/parentClosure.ts
|
|
6
|
+
var l = "_voltro_workflow_parent_closures", u = i.NonEmptyString, d = i.Struct({
|
|
7
|
+
id: u,
|
|
8
|
+
runId: u,
|
|
9
|
+
workflowName: u,
|
|
10
|
+
executionId: u,
|
|
11
|
+
generation: u,
|
|
12
|
+
parentStatus: i.Literals([
|
|
13
|
+
"succeeded",
|
|
14
|
+
"failed",
|
|
15
|
+
"cancelled"
|
|
16
|
+
]),
|
|
17
|
+
closedAt: i.Date,
|
|
18
|
+
afterChildId: i.NullOr(u),
|
|
19
|
+
scanHasOpenChildren: i.Boolean,
|
|
20
|
+
completedAt: i.NullOr(i.Date)
|
|
21
|
+
}), f = i.Struct({
|
|
22
|
+
id: u,
|
|
23
|
+
tag: u,
|
|
24
|
+
executionId: u,
|
|
25
|
+
status: i.Literals([
|
|
26
|
+
"running",
|
|
27
|
+
"suspended",
|
|
28
|
+
"succeeded",
|
|
29
|
+
"failed",
|
|
30
|
+
"cancelled"
|
|
31
|
+
]),
|
|
32
|
+
runnerGeneration: i.optional(i.NullOr(u)),
|
|
33
|
+
parentGeneration: i.optional(i.NullOr(u)),
|
|
34
|
+
parentClosePolicy: i.NullOr(i.Literals([
|
|
35
|
+
"cancel",
|
|
36
|
+
"terminate",
|
|
37
|
+
"abandon"
|
|
38
|
+
]))
|
|
39
|
+
}), p = async (t, r, c) => {
|
|
40
|
+
if (r.parentClosePolicy !== "cancel" && r.parentClosePolicy !== "terminate") return !1;
|
|
41
|
+
if (typeof r.parentExecutionId != "string" || r.parentExecutionId.length === 0 || typeof r.parentGeneration != "string" || r.parentGeneration.length === 0) throw Error("Child entry requires its original parent execution and generation");
|
|
42
|
+
let u = c ?? (await t.query({
|
|
43
|
+
table: l,
|
|
44
|
+
predicate: a(s("executionId", r.parentExecutionId), s("generation", r.parentGeneration)),
|
|
45
|
+
lock: "update",
|
|
46
|
+
order: [],
|
|
47
|
+
take: 1,
|
|
48
|
+
skip: void 0,
|
|
49
|
+
projection: void 0
|
|
50
|
+
}))[0];
|
|
51
|
+
if (u === void 0) return !1;
|
|
52
|
+
let p = i.decodeUnknownSync(d)(u);
|
|
53
|
+
if (p.executionId !== r.parentExecutionId || p.generation !== r.parentGeneration) return !1;
|
|
54
|
+
let m = i.decodeUnknownSync(f)(r), h = o("wfctl", JSON.stringify([
|
|
55
|
+
"parent-close",
|
|
56
|
+
p.id,
|
|
57
|
+
m.id
|
|
58
|
+
])), g = await n(t, h);
|
|
59
|
+
if (g !== void 0) {
|
|
60
|
+
if (g.runId !== m.id || g.workflowName !== m.tag || g.executionId !== m.executionId || g.operation === "resume" || g.cause?.reason !== "parent-close" || g.cause.detail?.closureId !== p.id) throw Error("Parent closure receipt belongs to another child");
|
|
61
|
+
} else {
|
|
62
|
+
if (m.status !== "running" && m.status !== "suspended") return !1;
|
|
63
|
+
if (m.runnerGeneration === void 0 || m.runnerGeneration === null) throw Error("Child entry requires its own generation");
|
|
64
|
+
await e(t, {
|
|
65
|
+
id: h,
|
|
66
|
+
runId: m.id,
|
|
67
|
+
workflowName: m.tag,
|
|
68
|
+
executionId: m.executionId,
|
|
69
|
+
generation: m.runnerGeneration,
|
|
70
|
+
operation: r.parentClosePolicy,
|
|
71
|
+
requestedAt: p.closedAt.getTime(),
|
|
72
|
+
cause: {
|
|
73
|
+
reason: "parent-close",
|
|
74
|
+
detail: {
|
|
75
|
+
closureId: p.id,
|
|
76
|
+
parentRunId: p.runId,
|
|
77
|
+
parentExecutionId: p.executionId,
|
|
78
|
+
parentGeneration: p.generation,
|
|
79
|
+
parentStatus: p.parentStatus,
|
|
80
|
+
parentClosePolicy: r.parentClosePolicy
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return !0;
|
|
86
|
+
}, m = async (e, n, o = Date.now()) => {
|
|
87
|
+
let [u] = await e.query({
|
|
88
|
+
table: l,
|
|
89
|
+
predicate: s("id", n),
|
|
90
|
+
lock: "update",
|
|
91
|
+
order: [],
|
|
92
|
+
take: 1,
|
|
93
|
+
skip: void 0,
|
|
94
|
+
projection: void 0
|
|
95
|
+
});
|
|
96
|
+
if (u === void 0) throw Error("Parent closure is missing");
|
|
97
|
+
let m = i.decodeUnknownSync(d)(u);
|
|
98
|
+
if (m.completedAt !== null) return {
|
|
99
|
+
scanned: 0,
|
|
100
|
+
controls: 0,
|
|
101
|
+
wrapped: !1
|
|
102
|
+
};
|
|
103
|
+
if (!Number.isFinite(o)) throw Error("Parent closure requires a finite completion timestamp");
|
|
104
|
+
let h = await e.query({
|
|
105
|
+
table: "_voltro_workflow_runs",
|
|
106
|
+
predicate: a(s("parentExecutionId", m.executionId), ...m.afterChildId === null ? [] : [c("id", m.afterChildId)]),
|
|
107
|
+
lock: "update",
|
|
108
|
+
order: [{
|
|
109
|
+
column: "id",
|
|
110
|
+
direction: "asc"
|
|
111
|
+
}],
|
|
112
|
+
take: 100,
|
|
113
|
+
skip: void 0,
|
|
114
|
+
projection: void 0
|
|
115
|
+
}), g = 0, _ = m.scanHasOpenChildren, v = null;
|
|
116
|
+
for (let t of h) {
|
|
117
|
+
let n = i.decodeUnknownSync(f)(t);
|
|
118
|
+
if (v = n.id, n.parentClosePolicy !== null && n.parentClosePolicy !== "abandon") {
|
|
119
|
+
if (n.parentGeneration === void 0 || n.parentGeneration === null) throw Error("Parent closure cannot attribute a child without its parent generation");
|
|
120
|
+
n.parentGeneration === m.generation && ((n.status === "running" || n.status === "suspended") && (_ = !0), await p(e, t, m) && (g++, n.status === "suspended" && typeof n.runnerGeneration == "string" && await r(e, {
|
|
121
|
+
runId: n.id,
|
|
122
|
+
workflowName: n.tag,
|
|
123
|
+
executionId: n.executionId,
|
|
124
|
+
generation: n.runnerGeneration
|
|
125
|
+
}, o)));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
let y = h.length < 100, b = y && !_ && !await t(e, m.id);
|
|
129
|
+
if (await e.update(l, m.id, {
|
|
130
|
+
afterChildId: y ? null : v,
|
|
131
|
+
scanHasOpenChildren: !y && _,
|
|
132
|
+
completedAt: b ? new Date(o) : null
|
|
133
|
+
}) === null) throw Error("Parent closure disappeared before saving its cursor");
|
|
134
|
+
return {
|
|
135
|
+
scanned: h.length,
|
|
136
|
+
controls: g,
|
|
137
|
+
wrapped: y
|
|
138
|
+
};
|
|
139
|
+
};
|
|
140
|
+
//#endregion
|
|
141
|
+
export { p as stageParentClosureAtChildEntry, m as stageWorkflowParentClosureInTransaction };
|