@voltro/workflow 0.62.1 → 0.62.3
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 +34 -0
- package/dist/clusterTestSuite.js +1 -1
- package/dist/index.d.ts +34 -0
- package/dist/index.js +2 -2
- package/dist/{src-B1XsZ6OO.js → src-CJ56XxpW.js} +401 -308
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -39,6 +39,35 @@ _Changes staged for the next release accumulate here (rolled up from
|
|
|
39
39
|
|
|
40
40
|
---
|
|
41
41
|
|
|
42
|
+
## [0.62.3] — 2026-09-03
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
|
|
46
|
+
- **@voltro/runtime** — `EffectStore` now exposes the complete Promise-store mutation surface plus transactions that roll back while preserving an inner Effect Cause. `defineSubscriber` accepts `eachReplica: true` so local per-replica work can state its topology explicitly; it cannot be combined with `once`.
|
|
47
|
+
|
|
48
|
+
### Fixed
|
|
49
|
+
|
|
50
|
+
- **@voltro/cli** — `voltro build` no longer starts Vite's HMR WebSocket while pre-rendering. A `RedirectError` from a static loader is now emitted as redirect metadata and served by `voltro start` with its exact status and `Location`; unrelated loader errors still fail the build.
|
|
51
|
+
- **@voltro/cli, @voltro/database, @voltro/plugin-storage** — `voltro doctor` now resolves grouped event bindings and narrows its hand-roll, junction, ownership, nullable-write, singleton-read, and UI reachability checks to evidence they can actually prove. Ids owned by external systems can be declared with `.externalId()`; plugin references and non-FK asset references carry that metadata automatically.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## [0.62.2] — 2026-09-03
|
|
56
|
+
|
|
57
|
+
### Added
|
|
58
|
+
|
|
59
|
+
- **@voltro/client, @voltro/web, @voltro/runtime, @voltro/cli, @voltro/devtools, @voltro/workflow** — Reconnect incidents now have one bounded, payload-free evidence path: browser diagnostics retain runtime/socket/protocol/subscription transitions across a reload, the subscriptions panel exposes recovery progress and stuck re-issues, and `voltro support collect` joins that export to inspect snapshots and exact browser-to-replica socket ids. The opt-in browser fault harness can reproduce a bounded transport cut without a proxy; logs and traces remain excluded from the support bundle unless explicitly requested.
|
|
60
|
+
|
|
61
|
+
Workflow admission rows now retain queue-time app/schema provenance. `voltro workflows flow validate` checks queued payloads against the current release without returning them, while `flow retry <intentId>` re-arms one retained dead letter after its fix. Support bundles also inventory project `conflictColumns` callsites, and `voltro support sentry <eventId>` delegates source-map resolution diagnosis to Sentry's own CLI.
|
|
62
|
+
- **@voltro/runtime** — Successful rpc WebSocket upgrades now emit structured open and close records carrying the serving `replicaId` and a stable per-socket `connectionId`, so connection cuts can be correlated to an api replica without debug traffic.
|
|
63
|
+
|
|
64
|
+
### Fixed
|
|
65
|
+
|
|
66
|
+
- **@voltro/client, @voltro/web, @voltro/react-native** — Subscription recovery now re-issues transport-failed active subscriptions only after the rpc protocol has cleared the previous socket error. A longer outage could previously reopen the WebSocket, immediately reject every re-issued subscription against the stale error, and leave the screen degraded until a reload.
|
|
67
|
+
- **@voltro/workflow, @voltro/cli, @voltro/devtools-ui** — Queued workflow starts whose stored payload no longer decodes now signal `onFailure` once and remain visible as dead-letter intents instead of retrying forever. Inspect or remove them with `voltro workflows flow` and `voltro workflows flow discard <intentId>`; a valid later debounce arrival for the same key replaces the obsolete payload and resumes normal draining.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
42
71
|
## [0.62.1] — 2026-09-02
|
|
43
72
|
|
|
44
73
|
### Fixed
|
|
@@ -46,6 +75,11 @@ _Changes staged for the next release accumulate here (rolled up from
|
|
|
46
75
|
- **@voltro/client, @voltro/web, @voltro/react-native** — `useSubscriptionHealth` now clears failures when replacement subscriptions succeed after a reconnect; each api keeps one error bus across transport, auth-refresh, and subject-reconnect generations.
|
|
47
76
|
- **@voltro/client, @voltro/web, @voltro/react-native** — Active subscriptions whose fibers ended in a transport failure are now re-issued when the rpc socket opens again, preserving their last rows and resume revision; `useConnectionStatus` stays degraded until every affected subscription delivers a later snapshot or delta.
|
|
48
77
|
|
|
78
|
+
**Correction:** In 0.62.1 that reissue runs on the raw WebSocket `open`, before
|
|
79
|
+
the rpc protocol clears the previous socket error. After a longer outage the
|
|
80
|
+
reissued fibers can therefore fail immediately and remain terminal. The next
|
|
81
|
+
patch moves recovery behind the protocol-ready `onOpen` effect.
|
|
82
|
+
|
|
49
83
|
### Internal (no consumer-facing effect)
|
|
50
84
|
|
|
51
85
|
- **@voltro/local-first** — Release dependency floors now exclude the vulnerable `fast-uri` and `@xmldom/xmldom` ranges, and the local-first test toolchain uses the patched Tiptap release.
|
package/dist/clusterTestSuite.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { I as e, P as t, S as n, g as r, v as i } from "./primitives-B-HlFCap.js";
|
|
2
|
-
import { o as a } from "./src-
|
|
2
|
+
import { o as a } from "./src-CJ56XxpW.js";
|
|
3
3
|
import { i as o, p as s } from "./cluster-OUXsLZ2x.js";
|
|
4
4
|
import { Cron as c, Deferred as l, Effect as u, Fiber as d, Layer as f, Schema as p } from "effect";
|
|
5
5
|
import { SqlClient as m } from "@effect/sql";
|
package/dist/index.d.ts
CHANGED
|
@@ -125,6 +125,11 @@ export declare interface AdmissionDrainDeps {
|
|
|
125
125
|
* lastError climb on the row) instead of a silent abandon.
|
|
126
126
|
*/
|
|
127
127
|
readonly registeredWorkflows?: ReadonlySet<string>;
|
|
128
|
+
/** Classify a start failure that retrying the SAME stored payload cannot
|
|
129
|
+
* repair. The CLI wires `WorkflowPayloadError`; unknown engine/store errors
|
|
130
|
+
* stay on the retry path because abandoning transient work is worse than a
|
|
131
|
+
* visible retry. */
|
|
132
|
+
readonly isPermanentStartError?: (cause: unknown) => boolean;
|
|
128
133
|
readonly log?: DrainLogger;
|
|
129
134
|
readonly now?: () => number;
|
|
130
135
|
}
|
|
@@ -243,6 +248,8 @@ export declare interface AdmitStartInput {
|
|
|
243
248
|
readonly payload: unknown;
|
|
244
249
|
readonly callerContext: unknown;
|
|
245
250
|
readonly tenantId: string | null;
|
|
251
|
+
readonly queuedAppVersion?: string | null;
|
|
252
|
+
readonly queuedSchemaFingerprint?: string | null;
|
|
246
253
|
readonly paused: boolean;
|
|
247
254
|
readonly now: number;
|
|
248
255
|
/**
|
|
@@ -760,6 +767,17 @@ export declare const CurrentWorkflowReplayShape: FiberRef.FiberRef<ReplayShapeTr
|
|
|
760
767
|
* `Effect.locally(CurrentWorkflowRunId, runId)`. */
|
|
761
768
|
export declare const CurrentWorkflowRunId: FiberRef.FiberRef<string | undefined>;
|
|
762
769
|
|
|
770
|
+
/**
|
|
771
|
+
* Stop retrying an intent whose exact payload can never start.
|
|
772
|
+
*
|
|
773
|
+
* The row deliberately remains in `_voltro_workflow_pending`: a deleted poison
|
|
774
|
+
* row and work that vanished are indistinguishable, while a retained row keeps
|
|
775
|
+
* the payload, caller context and error available to `voltro workflows flow`
|
|
776
|
+
* until an operator explicitly discards it. `pendingWindow` excludes it, so it
|
|
777
|
+
* cannot consume a drain slot or log again.
|
|
778
|
+
*/
|
|
779
|
+
export declare const deadLetterIntent: (store: AdmissionDataStore, intent: PendingIntent, error: string, now: number) => Promise<boolean>;
|
|
780
|
+
|
|
763
781
|
/**
|
|
764
782
|
* Decide what happens to one start. Pure.
|
|
765
783
|
*
|
|
@@ -935,6 +953,8 @@ export declare interface DrainOutcome {
|
|
|
935
953
|
readonly expired: number;
|
|
936
954
|
readonly evicted: number;
|
|
937
955
|
readonly failed: number;
|
|
956
|
+
/** Pending intents moved out of the live drain set this tick. */
|
|
957
|
+
readonly deadLettered: number;
|
|
938
958
|
/** Runs cancelled by `timeouts.finish` on this tick. */
|
|
939
959
|
readonly timedOut: number;
|
|
940
960
|
/**
|
|
@@ -1277,6 +1297,8 @@ export declare interface ParkDelayedStartInput {
|
|
|
1277
1297
|
readonly payload: unknown;
|
|
1278
1298
|
readonly callerContext: unknown;
|
|
1279
1299
|
readonly tenantId: string | null;
|
|
1300
|
+
readonly queuedAppVersion?: string | null;
|
|
1301
|
+
readonly queuedSchemaFingerprint?: string | null;
|
|
1280
1302
|
/** Epoch ms the start becomes an ARRIVAL. Must be in the future — the facade
|
|
1281
1303
|
* starts a past-`at` immediately and never calls in here. */
|
|
1282
1304
|
readonly at: number;
|
|
@@ -1367,6 +1389,8 @@ export declare interface PendingIntent {
|
|
|
1367
1389
|
readonly mode: 'debounce' | 'batch' | 'throttle' | 'concurrency' | 'paused' | 'delayed';
|
|
1368
1390
|
readonly payload: unknown;
|
|
1369
1391
|
readonly callerContext: unknown;
|
|
1392
|
+
readonly queuedAppVersion: string | null;
|
|
1393
|
+
readonly queuedSchemaFingerprint: string | null;
|
|
1370
1394
|
readonly priority: number;
|
|
1371
1395
|
readonly dueAt: number;
|
|
1372
1396
|
readonly deadlineAt: number | undefined;
|
|
@@ -1377,6 +1401,9 @@ export declare interface PendingIntent {
|
|
|
1377
1401
|
* poison intent, and a poison intent that only ever manifested as "nothing
|
|
1378
1402
|
* ran" is the failure this column removes. */
|
|
1379
1403
|
readonly lastError: string | null;
|
|
1404
|
+
/** Present once this exact payload was classified as permanently unable to
|
|
1405
|
+
* start. Such rows remain inspectable but are not returned to the drainer. */
|
|
1406
|
+
readonly deadLetteredAt: number | undefined;
|
|
1380
1407
|
}
|
|
1381
1408
|
|
|
1382
1409
|
/**
|
|
@@ -1429,6 +1456,8 @@ declare interface PersistDeferInput {
|
|
|
1429
1456
|
readonly payload: unknown;
|
|
1430
1457
|
readonly callerContext: unknown;
|
|
1431
1458
|
readonly tenantId: string | null;
|
|
1459
|
+
readonly queuedAppVersion?: string | null;
|
|
1460
|
+
readonly queuedSchemaFingerprint?: string | null;
|
|
1432
1461
|
readonly now: number;
|
|
1433
1462
|
/** Set when the drainer is re-deferring a row it already holds. */
|
|
1434
1463
|
readonly existingId?: string;
|
|
@@ -1762,6 +1791,11 @@ export declare const resolveWorkflowMessageRun: (store: WorkflowMessageStore, ta
|
|
|
1762
1791
|
|
|
1763
1792
|
export declare const resumeWorkflow: (store: AdmissionDataStore, workflowName: string) => Promise<boolean>;
|
|
1764
1793
|
|
|
1794
|
+
/** Re-arm one dead-lettered intent after an operator has deployed a schema or
|
|
1795
|
+
* handler fix. The payload and its queue-time provenance stay untouched; only
|
|
1796
|
+
* the terminal classification and retry history are reset. */
|
|
1797
|
+
export declare const retryDeadLetterIntent: (store: AdmissionDataStore, intentId: string, now: number) => Promise<boolean>;
|
|
1798
|
+
|
|
1765
1799
|
export declare const sendWorkflowSignal: (input: {
|
|
1766
1800
|
readonly store: WorkflowMessageStore;
|
|
1767
1801
|
readonly recorder: WorkflowRunRecorderService;
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
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-B-HlFCap.js";
|
|
2
|
-
import { $ as W, A as G, At as K, B as q,
|
|
3
|
-
export {
|
|
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-CJ56XxpW.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 };
|