@voltro/workflow 0.69.0 → 0.69.1

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/dist/index.d.ts CHANGED
@@ -687,6 +687,48 @@ export declare interface CloseWorkflowChildrenForParentOptions {
687
687
  readonly interruptChild: (workflowName: string, executionId: string, policy: Exclude<WorkflowParentClosePolicy, 'abandon'>) => Promise<void>;
688
688
  }
689
689
 
690
+ /** The engine's own re-read rule: an unprocessed message whose `last_read` is
691
+ * older than this is re-delivered by the shard's owner on its next poll. A
692
+ * message older than this that is STILL unread has no owner reading it. */
693
+ export declare const CLUSTER_REREAD_WINDOW_MS: number;
694
+
695
+ export declare class ClusterDiagnostics extends ClusterDiagnostics_base {
696
+ }
697
+
698
+ declare const ClusterDiagnostics_base: Context.TagClass<ClusterDiagnostics, "@voltro/workflow/ClusterDiagnostics", ClusterDiagnosticsOps>;
699
+
700
+ export declare interface ClusterDiagnosticsOps {
701
+ /** This runner's advertised address — what keys its locks and its runner row. */
702
+ readonly ownAddress: string;
703
+ readonly shardLockMode: 'advisory' | 'row' | 'none';
704
+ /** Every message addressed to an entity — a workflow's `run` and its activities. */
705
+ readonly messagesFor: (entityId: string) => Effect.Effect<ReadonlyArray<ClusterMessageState>>;
706
+ /** Unprocessed, deliverable messages no runner has read for longer than
707
+ * `olderThanMs` (default: the engine's re-read window). */
708
+ readonly unreadMessages: (olderThanMs?: number) => Effect.Effect<ReadonlyArray<UnreadMessage>>;
709
+ /** Who holds the locks on these shards. Empty where the dialect cannot say
710
+ * (an advisory lock on MySQL has no holder view the framework reads). */
711
+ readonly shardLockHolders: (shardIds: ReadonlyArray<string>) => Effect.Effect<ReadonlyArray<ShardLockHolder>>;
712
+ /** The runner table — every address that registered, with its heartbeat. */
713
+ readonly runners: () => Effect.Effect<ReadonlyArray<ClusterRunner>>;
714
+ }
715
+
716
+ export declare interface ClusterMessageState {
717
+ /** The rpc tag — `run` for the workflow itself, `activity/<name>/<attempt>` for a step. */
718
+ readonly tag: string | null;
719
+ readonly entityType: string;
720
+ readonly entityId: string;
721
+ readonly shardId: string;
722
+ readonly processed: boolean;
723
+ readonly lastRead: Date | null;
724
+ }
725
+
726
+ export declare interface ClusterRunner {
727
+ readonly address: string;
728
+ readonly lastHeartbeat: Date | null;
729
+ readonly healthy: boolean;
730
+ }
731
+
690
732
  /**
691
733
  * Order pending rows for admission.
692
734
  *
@@ -918,6 +960,15 @@ export declare const deferringControlsOf: (control: ResolvedFlowControl | undefi
918
960
  * own. Use {@link discardIntent} for a start that is being dropped. */
919
961
  export declare const deleteIntent: (store: AdmissionDataStore, id: string) => Promise<boolean>;
920
962
 
963
+ /**
964
+ * The cluster half of a stalled run's report, built from the diagnostics: the
965
+ * run's messages and, for the unprocessed ones, who holds their shards. Pure
966
+ * over the two reads, so the sweep's caller and a test agree on its shape.
967
+ * `undefined` when the engine has no message for the run at all — an
968
+ * in-memory engine, or a run whose journal was cleared.
969
+ */
970
+ export declare const describeStalledRun: (ops: ClusterDiagnosticsOps, executionId: string, now?: number) => Effect.Effect<StalledRunClusterState | undefined>;
971
+
921
972
  export declare interface DiscardDecision {
922
973
  readonly intentId: string;
923
974
  readonly reason: string;
@@ -977,14 +1028,23 @@ export declare interface DrainOutcome {
977
1028
  */
978
1029
  readonly examined: boolean;
979
1030
  /**
980
- * When the earliest not-yet-due pending row comes due, as an epoch ms — the
1031
+ * When the earliest not-yet-due pending row comes due — OR the earliest
1032
+ * `timeouts.finish` deadline of a run still running — as an epoch ms: the
981
1033
  * number that lets the drainer arm for that instant instead of polling until
982
1034
  * it arrives.
983
1035
  *
984
- * `undefined` means "nothing in the read window is waiting". It is a LOWER
985
- * bound on the true next deadline (the window is capped by `batchSize`), which
986
- * is the safe direction: an understated deadline costs one early tick, an
987
- * overstated one misses a start.
1036
+ * The finish deadline is part of it because the drain tick is what ENFORCES
1037
+ * `timeouts.finish`, and a running run writes nothing to the queue: a drainer
1038
+ * that disarmed on an empty queue while a run approached its bound would
1039
+ * not cancel it at the bound but at the next arrival that happened to wake
1040
+ * it — measured as a cancellation landing tens of minutes after the declared
1041
+ * limit, by an amount that depended on unrelated traffic.
1042
+ *
1043
+ * `undefined` means "nothing in the read window is waiting and no controlled
1044
+ * run is under a finish bound". It is a LOWER bound on the true next deadline
1045
+ * (the window is capped by `batchSize`), which is the safe direction: an
1046
+ * understated deadline costs one early tick, an overstated one misses a
1047
+ * start or a cancellation.
988
1048
  */
989
1049
  readonly nextDueAt?: number;
990
1050
  }
@@ -1836,6 +1896,18 @@ export declare const serialiseWorkflowRowForWire: (row: Record<string, unknown>)
1836
1896
  */
1837
1897
  export declare const setSuspendSignalHintMs: (ms: number | undefined) => void;
1838
1898
 
1899
+ export declare interface ShardLockHolder {
1900
+ readonly shardId: string;
1901
+ readonly mode: 'advisory' | 'row';
1902
+ /** Who holds it: `pid <n> from <client>` for a postgres advisory lock, the
1903
+ * runner address for a row lease. */
1904
+ readonly holder: string;
1905
+ /** `true` when the holder is THIS runner's own lock session/address. */
1906
+ readonly own: boolean;
1907
+ readonly since: Date | null;
1908
+ readonly detail?: Record<string, unknown>;
1909
+ }
1910
+
1839
1911
  /**
1840
1912
  * Durable sleep — wake time journaled in the cluster. Wrapper around
1841
1913
  * `DurableClock.sleep` that emits `timer-set` / `timer-fired` events
@@ -1896,6 +1968,15 @@ export declare interface StalenessSweepDeps {
1896
1968
  /** App-supplied reaction — page someone, open a ticket. Must not throw;
1897
1969
  * a rejection is collected as a failure and the sweep continues. */
1898
1970
  readonly onStalled?: (run: StalledRun) => Promise<void>;
1971
+ /**
1972
+ * What else the report should carry about THIS run — the cluster engine's
1973
+ * view of it (its messages, who holds their shards), attached by the CLI
1974
+ * from `ClusterDiagnostics`. Best-effort: a rejection is collected as a
1975
+ * failure and the report goes out without it. The fields land on the
1976
+ * `run-stalled` event payload and on the warning line, so the report says
1977
+ * where the run is stuck and not only that it is.
1978
+ */
1979
+ readonly describeRun?: (run: StalledRun) => Promise<Record<string, unknown> | undefined>;
1899
1980
  readonly now?: () => number;
1900
1981
  readonly log?: {
1901
1982
  readonly info: (message: string, fields?: Record<string, unknown>) => void;
@@ -1940,6 +2021,20 @@ export declare interface StalledRun {
1940
2021
  readonly reason: StallReason;
1941
2022
  }
1942
2023
 
2024
+ /** A `run-stalled` report's cluster half, as the sweep attaches it. */
2025
+ export declare interface StalledRunClusterState {
2026
+ readonly runner: string;
2027
+ readonly shardLockMode: ClusterDiagnosticsOps['shardLockMode'];
2028
+ readonly messages: ReadonlyArray<{
2029
+ readonly tag: string | null;
2030
+ readonly shardId: string;
2031
+ readonly processed: boolean;
2032
+ readonly lastRead: string | null;
2033
+ readonly unreadForMs: number | null;
2034
+ }>;
2035
+ readonly shardLocks: ReadonlyArray<ShardLockHolder>;
2036
+ }
2037
+
1943
2038
  /** Why the sweep believes this run is not moving. Diagnostic, not a taxonomy
1944
2039
  * the caller should branch on for correctness. */
1945
2040
  export declare type StallReason =
@@ -2150,6 +2245,11 @@ export declare const sweepStalledRuns: (deps: StalenessSweepDeps, options?: Stal
2150
2245
 
2151
2246
  export declare const truncateWorkflowValue: (value: unknown, bytes?: number) => unknown;
2152
2247
 
2248
+ export declare interface UnreadMessage extends ClusterMessageState {
2249
+ /** How long ago the last runner read it. */
2250
+ readonly unreadForMs: number;
2251
+ }
2252
+
2153
2253
  /**
2154
2254
  * Validate + resolve a declaration. Throws at DEFINITION time (module load,
2155
2255
  * i.e. boot) with a message naming the workflow and the field.
@@ -2499,12 +2599,22 @@ export declare interface WorkflowExecuteRecordingOptions extends WorkflowRunReco
2499
2599
  *
2500
2600
  * Called on success AND on failure, and DELIBERATELY not on suspend: a
2501
2601
  * suspended run is still holding the resource it was admitted for.
2602
+ *
2603
+ * On a failure it also carries the payload and the error, so the caller
2604
+ * can raise the workflow's `onFailure` — the one route into that signal
2605
+ * that produces a `failed` row, and the one that was not wired: the
2606
+ * flow-control paths (an expired start, a finish timeout, a dead-lettered
2607
+ * intent) notified, and a body that failed did not.
2502
2608
  */
2503
2609
  readonly onTerminal?: (input: {
2504
2610
  readonly workflowName: string;
2505
2611
  readonly executionId: string;
2506
2612
  readonly runId?: string;
2507
2613
  readonly status: 'succeeded' | 'failed';
2614
+ /** The run's payload — present on `failed`, for the failure report. */
2615
+ readonly payload?: unknown;
2616
+ readonly errorTag?: string | null;
2617
+ readonly errorMessage?: string | null;
2508
2618
  }) => Promise<void>;
2509
2619
  /**
2510
2620
  * CRASH-LOOP BREAKER — how many CONSECUTIVE runner deaths this run may cost
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  import { A as e, B as t, C as n, D as r, E as i, G as a, H as o, I as s, L as c, M as l, N as u, O as d, P as f, R as p, S as m, T as h, U as g, V as _, W as v, _ as y, a as b, b as x, c as S, d as C, f as w, g as T, h as E, i as D, j as O, k, l as A, m as j, n as M, o as N, p as P, r as F, s as I, t as L, u as R, v as z, w as B, x as V, y as H, z as U } from "./primitives-CqHxfASq.js";
2
- import { $ as W, A as G, At as K, B as q, Bt as J, C as Y, Ct as X, D as Z, Dt as Q, E as $, Et as ee, F as te, Ft as ne, G as re, H as ie, I as ae, It as oe, J as se, K as ce, L as le, Lt as ue, M as de, Mt as fe, N as pe, Nt as me, O as he, Ot as ge, P as _e, Pt as ve, Q as ye, R as be, Rt as xe, S as Se, St as Ce, T as we, Tt as Te, U as Ee, V as De, Vt as Oe, W as ke, X as Ae, Y as je, Z as Me, _ as Ne, _t as Pe, a as Fe, at as Ie, b as Le, bt as Re, c as ze, ct as Be, d as Ve, dt as He, et as Ue, f as We, ft as Ge, g as Ke, gt as qe, h as Je, ht as Ye, i as Xe, it as Ze, j as Qe, jt as $e, k as et, kt as tt, l as nt, lt as rt, m as it, mt as at, n as ot, nt as st, o as ct, ot as lt, p as ut, pt as dt, q as ft, r as pt, rt as mt, s as ht, st as gt, t as _t, tt as vt, u as yt, ut as bt, v as xt, vt as St, w as Ct, wt, x as Tt, xt as Et, y as Dt, yt as Ot, z as kt, zt as At } from "./src-Dj8r1Kcn.js";
3
- export { mt as ADMISSIONS_TABLE, ut as BUDGET_HOLDS_TABLE, it as BudgetHoldExpired, ke as CANCEL_ON_WATERMARK, l as CurrentWorkflowExecutionId, u as CurrentWorkflowPatches, B as CurrentWorkflowReplayShape, f as CurrentWorkflowRunId, Je as DEFAULT_BUDGET_HOLD_TIMEOUT_MS, re as DEFAULT_COLD_LOOKBACK_MS, be as DEFAULT_DRAIN_BATCH, ce as DEFAULT_EVENT_BATCH, Ze as DEFAULT_LEASE_MS, Xe as DEFAULT_MAX_RUN_RECLAIMS, Fe as DEFAULT_REPLAY_SHAPE_LIMIT, q as DEFAULT_STALL_AFTER_MS, De as DEFAULT_STALL_EVENT_LOOKBACK, ie as DEFAULT_STALL_RUN_PAGE, pe as DEFAULT_SUSPEND_HINT_MS, d as DEFAULT_WORKFLOW_SCHEDULE_MAX_RUNTIME_MS, t as DEFERRING_CONTROLS, ft as EVENTS_TABLE, ee as FlowControlKeyError, Ie as PAUSES_TABLE, lt as PENDING_TABLE, se as WATERMARKS_TABLE, L as WorkflowFlowControlProperty, M as WorkflowMessagesProperty, s as WorkflowRunRecorder, k as WorkflowScheduleProperty, c as WorkflowStepInterceptorTag, F as WorkflowVersionTypeId, D as WorkflowWorkerLayerTypeId, Ke as _voltroBudgetHoldsTable, ve as _voltroWorkflowAdmissionsTable, ne as _voltroWorkflowPausesTable, oe as _voltroWorkflowPendingTable, xe as _voltroWorkflowRunEventsTable, At as _voltroWorkflowRunStepsTable, J as _voltroWorkflowRunsTable, ue as _voltroWorkflowStartContextsTable, Ue as _voltroWorkflowWatermarksTable, vt as admitStart, gt as allIntents, _ as assertConsistentPools, Qe as awaitEvent, de as awaitSignal, Ct as awaitSignalSuspending, We as awaitUpdate, Ne as budgetHoldGeneration, xt as budgetHoldKey, Dt as budgetHoldSignalName, pt as closeWorkflowChildrenForParent, Q as comparePendingOrder, we as completeSuspendingSignal, Be as deadLetterIntent, ge as decideAdmission, o as deferringControlsOf, rt as deleteIntent, bt as discardIntent, kt as drainTick, He as dueIntents, b as durableClock, N as durableQueue, I as durableQueueModule, S as durableRateLimiterModule, Ge as evaluateAdmission, p as getCurrentWorkflowExecutionId, U as getCurrentWorkflowRunId, A as getWorkflowFlowControl, e as getWorkflowSchedule, R as getWorkflowVersionMetadata, g as hasCancelOn, v as hasFlowControl, Le as heldBudgets, Oe as inMemoryWorkflowEngineLayer, ot as inspectWorkflow, tt as isFinishExpired, K as isStartExpired, C as isWorkflowWorkerLayer, st as linkExecution, _t as makeInMemoryRecorder, h as makeReplayShapeTracker, ct as makeWorkflowRunRecorder, Z as makeWorkflowUpdateId, _e as maybeHintSuspendingSignal, ye as newestEventAt, $e as nextSlotAt, i as nondeterminismEventPayload, ht as normaliseWorkflowPatches, dt as noteIntentAttempt, at as parkDelayedStart, w as patch, Ye as pauseWorkflow, Tt as pendingBudgetHolds, qe as pendingSlotId, Pe as pendingWindow, St as persistDefer, W as planCancellations, fe as pooledConcurrencyKey, P as processQueue, Ot as pruneAdmissions, j as queueWorker, E as rateLimit, Re as readAdmissionState, Et as readPausedWorkflows, je as readWatermark, Ce as recordAdmission, Se as releaseBudgetHolds, X as releaseLease, r as reportNondeterminism, te as resetSuspendHintsForTest, me as resolveAdmissionKeys, ze as resolveRunGuardTuning, ae as resolveSuspendHintMs, he as resolveWorkflowMessageRun, wt as resumeWorkflow, Te as retryDeadLetterIntent, et as sendWorkflowSignal, G as sendWorkflowUpdate, nt as serialiseWorkflowRowForWire, le as setSuspendSignalHintMs, T as sleep, y as sleepUntil, z as step, H as stepIdempotencyKey, x as stepModule, Y as suspendForBudget, $ as suspendingSignalDeferredName, Ae as sweepCancelOn, Ee as sweepStalledRuns, yt as truncateWorkflowValue, a as validateFlowControl, O as validateWorkflowSchedule, V as withCompensation, m as workflow, n as workflowModule, Ve as wrapWorkflowExecuteWithRunRecording, Me as writeWatermark };
2
+ import { $ as W, A as G, At as K, B as q, Bt as J, C as Y, Ct as X, D as Z, Dt as Q, E as $, Et as ee, F as te, Ft as ne, G as re, H as ie, I as ae, It as oe, J as se, K as ce, L as le, Lt as ue, M as de, Mt as fe, N as pe, Nt as me, O as he, Ot as ge, P as _e, Pt as ve, Q as ye, R as be, Rt as xe, S as Se, St as Ce, T as we, Tt as Te, U as Ee, V as De, Vt as Oe, W as ke, X as Ae, Y as je, Z as Me, _ as Ne, _t as Pe, a as Fe, at as Ie, b as Le, bt as Re, c as ze, ct as Be, d as Ve, dt as He, et as Ue, f as We, ft as Ge, g as Ke, gt as qe, h as Je, ht as Ye, i as Xe, it as Ze, j as Qe, jt as $e, k as et, kt as tt, l as nt, lt as rt, m as it, mt as at, n as ot, nt as st, o as ct, ot as lt, p as ut, pt as dt, q as ft, r as pt, rt as mt, s as ht, st as gt, t as _t, tt as vt, u as yt, ut as bt, v as xt, vt as St, w as Ct, wt, x as Tt, xt as Et, y as Dt, yt as Ot, z as kt, zt as At } from "./src-TRpoU54e.js";
3
+ import { n as jt, r as Mt, t as Nt } from "./clusterDiagnostics-CNtl5LX9.js";
4
+ export { mt as ADMISSIONS_TABLE, ut as BUDGET_HOLDS_TABLE, it as BudgetHoldExpired, ke as CANCEL_ON_WATERMARK, Nt as CLUSTER_REREAD_WINDOW_MS, jt as ClusterDiagnostics, l as CurrentWorkflowExecutionId, u as CurrentWorkflowPatches, B as CurrentWorkflowReplayShape, f as CurrentWorkflowRunId, Je as DEFAULT_BUDGET_HOLD_TIMEOUT_MS, re as DEFAULT_COLD_LOOKBACK_MS, be as DEFAULT_DRAIN_BATCH, ce as DEFAULT_EVENT_BATCH, Ze as DEFAULT_LEASE_MS, Xe as DEFAULT_MAX_RUN_RECLAIMS, Fe as DEFAULT_REPLAY_SHAPE_LIMIT, q as DEFAULT_STALL_AFTER_MS, De as DEFAULT_STALL_EVENT_LOOKBACK, ie as DEFAULT_STALL_RUN_PAGE, pe as DEFAULT_SUSPEND_HINT_MS, d as DEFAULT_WORKFLOW_SCHEDULE_MAX_RUNTIME_MS, t as DEFERRING_CONTROLS, ft as EVENTS_TABLE, ee as FlowControlKeyError, Ie as PAUSES_TABLE, lt as PENDING_TABLE, se as WATERMARKS_TABLE, L as WorkflowFlowControlProperty, M as WorkflowMessagesProperty, s as WorkflowRunRecorder, k as WorkflowScheduleProperty, c as WorkflowStepInterceptorTag, F as WorkflowVersionTypeId, D as WorkflowWorkerLayerTypeId, Ke as _voltroBudgetHoldsTable, ve as _voltroWorkflowAdmissionsTable, ne as _voltroWorkflowPausesTable, oe as _voltroWorkflowPendingTable, xe as _voltroWorkflowRunEventsTable, At as _voltroWorkflowRunStepsTable, J as _voltroWorkflowRunsTable, ue as _voltroWorkflowStartContextsTable, Ue as _voltroWorkflowWatermarksTable, vt as admitStart, gt as allIntents, _ as assertConsistentPools, Qe as awaitEvent, de as awaitSignal, Ct as awaitSignalSuspending, We as awaitUpdate, Ne as budgetHoldGeneration, xt as budgetHoldKey, Dt as budgetHoldSignalName, pt as closeWorkflowChildrenForParent, Q as comparePendingOrder, we as completeSuspendingSignal, Be as deadLetterIntent, ge as decideAdmission, o as deferringControlsOf, rt as deleteIntent, Mt as describeStalledRun, bt as discardIntent, kt as drainTick, He as dueIntents, b as durableClock, N as durableQueue, I as durableQueueModule, S as durableRateLimiterModule, Ge as evaluateAdmission, p as getCurrentWorkflowExecutionId, U as getCurrentWorkflowRunId, A as getWorkflowFlowControl, e as getWorkflowSchedule, R as getWorkflowVersionMetadata, g as hasCancelOn, v as hasFlowControl, Le as heldBudgets, Oe as inMemoryWorkflowEngineLayer, ot as inspectWorkflow, tt as isFinishExpired, K as isStartExpired, C as isWorkflowWorkerLayer, st as linkExecution, _t as makeInMemoryRecorder, h as makeReplayShapeTracker, ct as makeWorkflowRunRecorder, Z as makeWorkflowUpdateId, _e as maybeHintSuspendingSignal, ye as newestEventAt, $e as nextSlotAt, i as nondeterminismEventPayload, ht as normaliseWorkflowPatches, dt as noteIntentAttempt, at as parkDelayedStart, w as patch, Ye as pauseWorkflow, Tt as pendingBudgetHolds, qe as pendingSlotId, Pe as pendingWindow, St as persistDefer, W as planCancellations, fe as pooledConcurrencyKey, P as processQueue, Ot as pruneAdmissions, j as queueWorker, E as rateLimit, Re as readAdmissionState, Et as readPausedWorkflows, je as readWatermark, Ce as recordAdmission, Se as releaseBudgetHolds, X as releaseLease, r as reportNondeterminism, te as resetSuspendHintsForTest, me as resolveAdmissionKeys, ze as resolveRunGuardTuning, ae as resolveSuspendHintMs, he as resolveWorkflowMessageRun, wt as resumeWorkflow, Te as retryDeadLetterIntent, et as sendWorkflowSignal, G as sendWorkflowUpdate, nt as serialiseWorkflowRowForWire, le as setSuspendSignalHintMs, T as sleep, y as sleepUntil, z as step, H as stepIdempotencyKey, x as stepModule, Y as suspendForBudget, $ as suspendingSignalDeferredName, Ae as sweepCancelOn, Ee as sweepStalledRuns, yt as truncateWorkflowValue, a as validateFlowControl, O as validateWorkflowSchedule, V as withCompensation, m as workflow, n as workflowModule, Ve as wrapWorkflowExecuteWithRunRecording, Me as writeWatermark };