@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.
Files changed (89) hide show
  1. package/CHANGELOG.md +1215 -0
  2. package/THIRD-PARTY-NOTICES.md +5 -151
  3. package/dist/admission.js +140 -0
  4. package/dist/admissionDrainer.js +705 -0
  5. package/dist/admissionGate.js +115 -0
  6. package/dist/admissionStore.js +347 -0
  7. package/dist/admissionSubmission.js +297 -0
  8. package/dist/admissionTables.js +137 -0
  9. package/dist/admissionTransaction.js +21 -0
  10. package/dist/awaitEvent.js +82 -0
  11. package/dist/budgetHold.js +136 -0
  12. package/dist/cancelOnPlan.js +75 -0
  13. package/dist/cancelOnSweep.js +188 -0
  14. package/dist/cancelPendingStart.js +50 -0
  15. package/dist/cluster.d.ts +304 -280
  16. package/dist/cluster.js +8 -2
  17. package/dist/clusterCron.js +11 -0
  18. package/dist/clusterDiagnostics.js +20 -0
  19. package/dist/clusterDiagnosticsSql.js +145 -0
  20. package/dist/clusterLayer.js +110 -0
  21. package/dist/clusterMigrationGate.js +61 -0
  22. package/dist/clusterRunnerLayer.js +21 -0
  23. package/dist/clusterTestSuite.d.ts +11 -11
  24. package/dist/clusterTestSuite.js +257 -257
  25. package/dist/controlMonitor.js +13 -0
  26. package/dist/controlRequest.js +367 -0
  27. package/dist/executionRefusal.js +162 -0
  28. package/dist/failureHandoff.js +183 -0
  29. package/dist/failureMessage.js +12 -0
  30. package/dist/failureRecovery.js +50 -0
  31. package/dist/failureReportStore.js +60 -0
  32. package/dist/flowControl.js +142 -0
  33. package/dist/forwardStartReceipts.js +41 -0
  34. package/dist/inMemoryLayer.js +7 -0
  35. package/dist/inMemoryRecorder.js +56 -0
  36. package/dist/index.d.ts +456 -360
  37. package/dist/index.js +49 -5
  38. package/dist/inspectWorkflow.js +101 -0
  39. package/dist/journalEncryption.js +147 -0
  40. package/dist/messages.js +92 -0
  41. package/dist/nondeterminism.js +51 -0
  42. package/dist/parentClosure.js +141 -0
  43. package/dist/parentClosureRecovery.js +54 -0
  44. package/dist/pendingSubmission.js +85 -0
  45. package/dist/prepareSubmissionDispatch.js +17 -0
  46. package/dist/preparedExecution.js +14 -0
  47. package/dist/primitives.d.ts +56 -31
  48. package/dist/primitives.js +225 -2
  49. package/dist/queuedCancellationRequest.js +364 -0
  50. package/dist/queuedControl.js +21 -0
  51. package/dist/recorder.js +11 -0
  52. package/dist/residentExecutionEvidence.js +64 -0
  53. package/dist/retryPolicy.js +57 -0
  54. package/dist/runEventsTable.js +17 -0
  55. package/dist/runGeneration.js +345 -0
  56. package/dist/runRecording.js +615 -0
  57. package/dist/runStepsTable.js +28 -0
  58. package/dist/runnerStorageGuard.js +29 -0
  59. package/dist/runsTable.js +42 -0
  60. package/dist/scheduleDeclaration.js +44 -0
  61. package/dist/signalHint.js +23 -0
  62. package/dist/signals.js +70 -0
  63. package/dist/signalsSuspending.js +57 -0
  64. package/dist/sqliteWorkflowOwnership.js +26 -0
  65. package/dist/stalenessSweep.js +191 -0
  66. package/dist/startContextsTable.js +20 -0
  67. package/dist/startReceipt.js +143 -0
  68. package/dist/submissionRecovery.js +122 -0
  69. package/dist/submissionRejection.js +10 -0
  70. package/dist/submissionRetry.js +71 -0
  71. package/dist/suspensionUnavailable.js +9 -0
  72. package/dist/updates.js +87 -0
  73. package/dist/watermarkTable.js +9 -0
  74. package/dist/webCrypto.js +17 -0
  75. package/dist/workflowDelivery.js +24 -0
  76. package/dist/workflowJournal.js +124 -0
  77. package/dist/workflowJournalReset.js +111 -0
  78. package/dist/workflowReadSelections.js +12 -0
  79. package/dist/workflowRestartDispatch.js +29 -0
  80. package/dist/workflowRestartObservation.js +60 -0
  81. package/dist/workflowRestartPreparation.js +109 -0
  82. package/dist/workflowRestartReservation.js +426 -0
  83. package/dist/workflowResumeDispatch.js +29 -0
  84. package/package.json +6 -9
  85. package/dist/cluster-i3frC3Da.js +0 -646
  86. package/dist/clusterDiagnostics-CGUtnJkX.js +0 -2084
  87. package/dist/journalEncryption--n5VDdYO.js +0 -148
  88. package/dist/primitives-Btjhjm8P.js +0 -483
  89. package/dist/src-DP-lKqaG.js +0 -3867
@@ -0,0 +1,54 @@
1
+ import { stageWorkflowParentClosureInTransaction as e } from "./parentClosure.js";
2
+ import { and as t, eq as n, gt as r, isNull as i } from "@voltro/database";
3
+ //#region src/parentClosureRecovery.ts
4
+ var a = "_voltro_workflow_parent_closures", o = /* @__PURE__ */ new WeakMap(), s = async (s, c, l) => {
5
+ let u = o.get(s), d = await s.store.query({
6
+ table: a,
7
+ predicate: t(i("completedAt"), ...u === void 0 ? [] : [r("id", u.afterId)]),
8
+ order: [{
9
+ column: "id",
10
+ direction: "asc"
11
+ }],
12
+ take: l,
13
+ skip: void 0,
14
+ projection: void 0
15
+ }), f = 0, p = u?.nextDueAt, m = () => {
16
+ p = Math.min(p ?? c + 1e3, c + 1e3);
17
+ };
18
+ for (let t of d) try {
19
+ if (typeof t.id != "string" || t.id.length === 0) throw Error("Parent closure has no identity");
20
+ let r = t.id;
21
+ await s.transaction(async (t) => {
22
+ await e(t, r, c);
23
+ let [i] = await t.query({
24
+ table: a,
25
+ predicate: n("id", r),
26
+ order: [],
27
+ take: 1,
28
+ skip: void 0,
29
+ projection: ["completedAt"]
30
+ });
31
+ if (i === void 0) throw Error("Parent closure disappeared");
32
+ return i.completedAt instanceof Date && Number.isFinite(i.completedAt.getTime());
33
+ }) || m();
34
+ } catch {
35
+ f++, m(), s.log?.warn?.("workflow parent closure could not be reconciled", { closureId: typeof t.id == "string" ? t.id : null });
36
+ }
37
+ let h = d.at(-1);
38
+ return d.length === l && typeof h?.id == "string" ? (o.set(s, {
39
+ afterId: h.id,
40
+ nextDueAt: p
41
+ }), {
42
+ scanned: d.length,
43
+ failed: f,
44
+ nextDueAt: c,
45
+ examined: !0
46
+ }) : (o.delete(s), {
47
+ scanned: d.length,
48
+ failed: f,
49
+ nextDueAt: p,
50
+ examined: d.length > 0
51
+ });
52
+ };
53
+ //#endregion
54
+ export { s as recoverWorkflowParentClosures };
@@ -0,0 +1,85 @@
1
+ import { withAdmissionTransaction as e } from "./admissionTransaction.js";
2
+ import { persistReservedSubmission as t, readAdmissionSubmission as n, reserveAdmissionSubmissionInTransaction as r } from "./admissionSubmission.js";
3
+ import { bindWorkflowStartReceipts as i } from "./startReceipt.js";
4
+ import { PENDING_TABLE as a, toPendingIntent as o } from "./admissionStore.js";
5
+ import { eq as s } from "@voltro/database";
6
+ //#region src/pendingSubmission.ts
7
+ var c = async (e, r) => {
8
+ if (new Set(r.intentIds).size !== r.intentIds.length) throw Error("Admitted transfer requires distinct pending identities");
9
+ let c = await n(e, r.id);
10
+ if (c !== void 0) {
11
+ if (c.workflowName !== r.workflowName || c.tenantId !== r.tenantId || c.ledgerId !== r.ledgerId || !c.receiptsBound) throw Error("Admitted transfer contradicts its existing submission");
12
+ return c;
13
+ }
14
+ for (let t of r.intentIds) {
15
+ let n = await e.query({
16
+ table: a,
17
+ predicate: s("id", t),
18
+ order: [],
19
+ take: 1,
20
+ skip: void 0,
21
+ projection: void 0,
22
+ lock: "update"
23
+ });
24
+ if (n[0] === void 0) throw Error("Admitted transfer lost a selected input");
25
+ let i = o(n[0]);
26
+ if (i.workflowName !== r.workflowName || i.tenantId !== r.tenantId || i.deadLetteredAt !== void 0) throw Error("Admitted transfer selected a foreign or dead-lettered input");
27
+ }
28
+ let l = await t(e, r);
29
+ await i(e, l.id);
30
+ for (let t of l.intentIds) if (!await e.delete("_voltro_workflow_pending", t)) throw Error("Admitted input disappeared during submission transfer");
31
+ return {
32
+ ...l,
33
+ receiptsBound: !0
34
+ };
35
+ }, l = async (t, n) => e(t, (e) => u(e, n)), u = async (e, t) => {
36
+ if (t.id.length === 0 || t.intentIds.length === 0 || new Set(t.intentIds).size !== t.intentIds.length) throw Error("Queue transfer requires a submission identity and distinct pending identities");
37
+ let c = await n(e, t.id);
38
+ if (c !== void 0) {
39
+ if (c.workflowName !== t.workflowName || c.tenantId !== t.tenantId) throw Error("Admission submission identity belongs to a different workflow or tenant");
40
+ if (!c.receiptsBound) throw Error("Submission exists without completed queue transfer");
41
+ return {
42
+ kind: "reserved",
43
+ submission: c,
44
+ reused: !0
45
+ };
46
+ }
47
+ let l = [];
48
+ for (let n of t.intentIds) {
49
+ let r = await e.query({
50
+ table: a,
51
+ predicate: s("id", n),
52
+ order: [],
53
+ take: 1,
54
+ skip: void 0,
55
+ projection: void 0,
56
+ lock: "update"
57
+ });
58
+ if (r[0] === void 0) return { kind: "selection-unavailable" };
59
+ let i = o(r[0]);
60
+ if (i.workflowName !== t.workflowName || i.tenantId !== t.tenantId) throw Error("Selected pending start belongs to a different workflow or tenant");
61
+ if (i.deadLetteredAt !== void 0 || i.dueAt > t.now) return { kind: "selection-unavailable" };
62
+ l.push(i);
63
+ }
64
+ let u = t.prepare(l);
65
+ if (u.control.workflowName !== t.workflowName) throw Error("Prepared submission belongs to a different workflow");
66
+ let d = await r(e, {
67
+ ...u,
68
+ id: t.id,
69
+ tenantId: t.tenantId,
70
+ intentIds: t.intentIds,
71
+ now: t.now
72
+ });
73
+ if (d.kind !== "reserved") return d;
74
+ await i(e, t.id);
75
+ for (let t of l) if (!await e.delete("_voltro_workflow_pending", t.id)) throw Error("Pending start disappeared during queue transfer");
76
+ return {
77
+ ...d,
78
+ submission: {
79
+ ...d.submission,
80
+ receiptsBound: !0
81
+ }
82
+ };
83
+ };
84
+ //#endregion
85
+ export { c as takeAdmittedSubmissionInTransaction, l as takePendingAdmissionSubmission, u as takePendingAdmissionSubmissionInTransaction };
@@ -0,0 +1,17 @@
1
+ import { prepareAdmissionSubmissionExecutionInTransaction as e, readAdmissionSubmission as t } from "./admissionSubmission.js";
2
+ //#region src/prepareSubmissionDispatch.ts
3
+ var n = async (n, r, i) => {
4
+ let a = await n.transaction((e) => t(e, r.id));
5
+ if (a === void 0 || a.workflowName !== r.workflowName || a.tenantId !== r.tenantId || a.ledgerId !== r.ledgerId) throw Error("Submission dispatch lost its resident owner");
6
+ if (!a.receiptsBound || a.failureId !== null) throw Error("Cannot dispatch an incomplete or rejected submission");
7
+ if (a.preparedExecutionId !== null) {
8
+ if (a.executionId !== null && a.executionId !== a.preparedExecutionId) throw Error("Submission acceptance contradicts its prepared identity");
9
+ return a.preparedExecutionId;
10
+ }
11
+ if (a.dispatchAttempts !== 0 || a.executionId !== null) throw Error("Submission has an unbound prior dispatch; reconciliation required");
12
+ let o = await n.resolveExecutionId(r.workflowName, i), s = await n.transaction((t) => e(t, r.id, o));
13
+ if (s.preparedExecutionId === null) throw Error("Submission preparation returned no execution identity");
14
+ return s.preparedExecutionId;
15
+ };
16
+ //#endregion
17
+ export { n as prepareSubmissionDispatch };
@@ -0,0 +1,14 @@
1
+ import { Effect as e } from "effect";
2
+ //#region src/preparedExecution.ts
3
+ var t = Symbol.for("@voltro/workflow/PreparedExecution"), n = (e, n) => {
4
+ Object.defineProperty(e, t, {
5
+ value: n,
6
+ enumerable: !0
7
+ });
8
+ }, r = (e) => (typeof e == "object" || typeof e == "function") && e !== null && typeof e[t] == "function", i = (n, r, i, a) => e.suspend(() => {
9
+ if (i.length === 0) return e.die(/* @__PURE__ */ Error("Prepared workflow execution requires a non-empty identity"));
10
+ let o = n[t];
11
+ return typeof o == "function" ? o(r, i, a?.discard ?? !0) : e.die(/* @__PURE__ */ Error("Workflow definition has no prepared-execution capability"));
12
+ });
13
+ //#endregion
14
+ export { n as attachPreparedWorkflowExecution, i as executePreparedWorkflow, r as hasPreparedWorkflowExecution };
@@ -1,13 +1,14 @@
1
- import { DurableClock as durableClock } from '@effect/workflow';
2
- import { DurableQueue as durableQueueModule } from '@effect/workflow';
3
- import { DurableRateLimiter as durableRateLimiterModule } from '@effect/workflow';
1
+ import { Context } from 'effect';
2
+ import { DurableClock as durableClock } from 'effect/workflow';
3
+ import { DurableQueue as durableQueueModule } from 'effect/workflow';
4
4
  import { Duration } from 'effect';
5
5
  import { Effect } from 'effect';
6
- import { FiberRef } from 'effect';
6
+ import { RateLimiter } from 'effect/persistence';
7
7
  import { Schema } from 'effect';
8
- import { Activity as stepModule } from '@effect/workflow';
8
+ import { Activity as stepModule } from 'effect/workflow';
9
9
  import { WorkflowAccessOptions } from '@voltro/protocol';
10
- import { Workflow as workflowModule } from '@effect/workflow';
10
+ import { WorkflowEngine } from 'effect/workflow';
11
+ import { Workflow as workflowModule } from 'effect/workflow';
11
12
 
12
13
  /**
13
14
  * Assert every workflow sharing a `concurrency.pool` declares the SAME limit.
@@ -34,7 +35,7 @@ export declare const assertConsistentPools: (controls: ReadonlyArray<ResolvedFlo
34
35
  * whose row already exists). A first entry has no prior shape, so the whole
35
36
  * mechanism costs one `FiberRef` read per step and nothing else.
36
37
  */
37
- export declare const CurrentWorkflowReplayShape: FiberRef.FiberRef<ReplayShapeTracker | undefined>;
38
+ export declare const CurrentWorkflowReplayShape: Context.Reference<ReplayShapeTracker | undefined>;
38
39
 
39
40
  /** The DECODED payload type. Mirrors `Workflow.make`'s own `idempotencyKey`
40
41
  * parameter, so the two never disagree about what a payload is. */
@@ -65,18 +66,16 @@ export declare const deferringControlsOf: (control: ResolvedFlowControl | undefi
65
66
  export { durableClock }
66
67
 
67
68
  /** Define a durable queue for concurrency-controlled side work. */
68
- export declare const durableQueue: typeof durableQueueModule.make & (<Options extends Parameters<typeof durableQueueModule.make>[0] & {
69
+ export declare const durableQueue: <Payload extends Schema.Top | Schema.Struct.Fields, Success extends Schema.Top = typeof Schema.Void, Error extends Schema.Top = typeof Schema.Never>(options: Parameters<typeof durableQueueModule.make<Payload, Success, Error>>[0] & {
69
70
  readonly encrypted?: boolean;
70
- }>(options: Options) => ReturnType<typeof durableQueueModule.make>);
71
+ }) => ReturnType<typeof durableQueueModule.make<Payload, Success, Error>>;
71
72
 
72
73
  export { durableQueueModule }
73
74
 
74
- export { durableRateLimiterModule }
75
-
76
75
  /** A duration in any shape Effect accepts: `'15 minutes'`, `900_000`,
77
76
  * `Duration.minutes(15)`. Same input type `sleep({ duration })` takes, so
78
77
  * there is one duration vocabulary in the whole workflow surface. */
79
- export declare type FlowDuration = Duration.DurationInput;
78
+ export declare type FlowDuration = Duration.Input;
80
79
 
81
80
  /** The resolved flow-control declaration attached to a workflow definition, or
82
81
  * `undefined` when it declares none — in which case every start takes exactly
@@ -102,6 +101,10 @@ export declare const hasCancelOn: (control: ResolvedFlowControl | undefined) =>
102
101
  * two writes per start for a decision that is always "admit". */
103
102
  export declare const hasFlowControl: (control: ResolvedFlowControl | undefined) => boolean;
104
103
 
104
+ /** A value that can carry definition metadata: a workflow definition is a
105
+ * callable in v4 (`Workflow.make` returns a function), a queue is an object. */
106
+ export declare const isCarrier: (value: unknown) => value is object;
107
+
105
108
  export declare const isWorkflowWorkerLayer: (value: unknown) => value is WorkflowWorkerLayerBrand;
106
109
 
107
110
  /**
@@ -135,7 +138,7 @@ export declare type NondeterminismKind = 'unreached-step' | 'extra-step-occurren
135
138
  declare type NormaliseWorkflowMessages<M extends WorkflowMessageSchemas | undefined> = {
136
139
  readonly signals: M extends {
137
140
  readonly signals: infer Signals;
138
- } ? NonNullable<Signals> & Readonly<Record<string, Schema.Schema.Any>> : {};
141
+ } ? NonNullable<Signals> & Readonly<Record<string, Schema.Top>> : {};
139
142
  readonly updates: M extends {
140
143
  readonly updates: infer Updates;
141
144
  } ? NonNullable<Updates> & Readonly<Record<string, WorkflowMessagePairSchemas>> : {};
@@ -176,7 +179,7 @@ declare type NormaliseWorkflowMessages<M extends WorkflowMessageSchemas | undefi
176
179
  * however many times it replays and whatever the deployed code says — which is
177
180
  * the property that makes the branch deterministic across a redeploy.
178
181
  *
179
- * Under `@effect/workflow` the naive implementation does the opposite: an
182
+ * Under `effect/workflow` the naive implementation does the opposite: an
180
183
  * activity that is ABSENT from an old run's journal EXECUTES on replay (the
181
184
  * journal is keyed name/attempt), so a marker journaled by an activity would
182
185
  * answer `true` for exactly the old runs it must answer `false` for. Reading
@@ -214,8 +217,26 @@ export declare const processQueue: typeof durableQueueModule.process;
214
217
  * inferred type) is what emits in the `.d.ts`, so it stays portable. */
215
218
  export declare const queueWorker: typeof durableQueueModule.worker;
216
219
 
217
- /** Durable rate limiter activity. Delays through the workflow clock. */
218
- export declare const rateLimit: typeof durableRateLimiterModule.rateLimit;
220
+ /**
221
+ * Durable rate limit. Consumes from the shared limiter; when the window is
222
+ * exhausted the wait is a durable clock sleep under `name`, so a deploy or a
223
+ * worker crash does not lose the delay and a replay does not consume twice.
224
+ */
225
+ export declare const rateLimit: (options: RateLimitOptions) => Effect.Effect<void, RateLimiter.RateLimiterError, RateLimiter.RateLimiter | WorkflowEngine.WorkflowEngine | WorkflowEngine.WorkflowInstance>;
226
+
227
+ /** What `rateLimit` admits: one unit of work under `limit` per `window` for
228
+ * `key`, counted by the `RateLimiter` service the boot provides. */
229
+ export declare interface RateLimitOptions {
230
+ /** Names this ADMISSION within the run: the decision is journaled under it, so a
231
+ * replay reads it back instead of consuming again. Two calls with the same name
232
+ * in one run share one decision — give each call its own (`send/${i}` in a loop). */
233
+ readonly name: string;
234
+ readonly window: Duration.Input;
235
+ readonly limit: number;
236
+ readonly key: string;
237
+ readonly algorithm?: 'fixed-window' | 'token-bucket' | undefined;
238
+ readonly tokens?: number | undefined;
239
+ }
219
240
 
220
241
  /** The slice of a `_voltro_workflow_run_steps` row this needs. */
221
242
  export declare interface RecordedStepShape {
@@ -256,7 +277,7 @@ export declare const reportNondeterminism: (findings: ReadonlyArray<Nondetermini
256
277
  * event at all". */
257
278
  export declare interface ResolvedCancelOn {
258
279
  readonly event: string;
259
- readonly schema: Schema.Schema.Any;
280
+ readonly schema: Schema.Top;
260
281
  readonly match: (event: unknown, payload: unknown) => boolean;
261
282
  readonly withinMs?: number;
262
283
  readonly reason: string;
@@ -370,7 +391,7 @@ export declare const sleepUntil: (options: {
370
391
  readonly until: Date | number;
371
392
  }) => Effect.Effect<void, never, never>;
372
393
 
373
- export declare const step: <R, Success extends Schema.Schema.Any = typeof Schema.Void, Error extends Schema.Schema.All = typeof Schema.Never>(options: StepOptions<R, Success, Error>) => ReturnType<typeof stepModule.make<R, Success, Error>>;
394
+ export declare const step: <R, Success extends Schema.Top = typeof Schema.Void, Error extends Schema.Top = typeof Schema.Never>(options: StepOptions<R, Success, Error>) => ReturnType<typeof stepModule.make<R, Success, Error>>;
374
395
 
375
396
  /**
376
397
  * Derive a deterministic idempotency key for the current workflow run,
@@ -389,7 +410,7 @@ export { stepModule }
389
410
  /**
390
411
  * Define a checkpointed step (activity) inside a workflow body.
391
412
  *
392
- * Wraps `@effect/workflow`'s `Activity.make` to record every
413
+ * Wraps `effect/workflow`'s `Activity.make` to record every
393
414
  * invocation in `_voltro_workflow_run_steps`. The wrapping is
394
415
  * transparent — accepts everything `Activity.make` accepts, plus an
395
416
  * optional `input` field whose value is persisted to the step row
@@ -408,7 +429,7 @@ export { stepModule }
408
429
  * Without the recorder service in scope (unit tests, etc.) the input
409
430
  * is dropped and the wrap is a no-op.
410
431
  */
411
- declare type StepOptions<R, Success extends Schema.Schema.Any, Error extends Schema.Schema.All> = {
432
+ declare type StepOptions<R, Success extends Schema.Top, Error extends Schema.Top> = {
412
433
  readonly name: string;
413
434
  readonly success?: Success | undefined;
414
435
  readonly error?: Error | undefined;
@@ -518,7 +539,9 @@ export declare const withCompensation: typeof workflowModule.withCompensation;
518
539
 
519
540
  export declare const workflow: WorkflowFn;
520
541
 
521
- declare type WorkflowBaseOptions = Parameters<WorkflowMake>[0];
542
+ declare type WorkflowBaseOptions = Parameters<WorkflowMake>[1] & {
543
+ readonly name: Parameters<WorkflowMake>[0];
544
+ };
522
545
 
523
546
  /**
524
547
  * Collect many starts into ONE run over an array of items.
@@ -577,7 +600,7 @@ export declare interface WorkflowBatch<Item> {
577
600
  * }],
578
601
  * ```
579
602
  */
580
- export declare interface WorkflowCancelOn<EventSchema extends Schema.Schema.Any, Payload> {
603
+ export declare interface WorkflowCancelOn<EventSchema extends Schema.Top, Payload> {
581
604
  /** The event NAME, exactly as `ctx.events.publish` writes it. */
582
605
  readonly event: string;
583
606
  /** Decoded before `match` sees it, so the predicate reads the domain type
@@ -611,7 +634,7 @@ export declare interface WorkflowCancelOn<EventSchema extends Schema.Schema.Any,
611
634
  * the per-entry-inferred {@link WorkflowCancelOnList}; this is what survives
612
635
  * erasure, and it is deliberately not the public spelling. */
613
636
  export declare interface WorkflowCancelOnDeclared {
614
- readonly cancelOn?: ReadonlyArray<WorkflowCancelOn<Schema.Schema.Any, never>>;
637
+ readonly cancelOn?: ReadonlyArray<WorkflowCancelOn<Schema.Top, never>>;
615
638
  }
616
639
 
617
640
  /** The `cancelOn` array as declared, with each entry's event type inferred
@@ -619,7 +642,7 @@ export declare interface WorkflowCancelOnDeclared {
619
642
  * per-entry inference work — a plain `ReadonlyArray<WorkflowCancelOn<…>>`
620
643
  * collapses every entry's event to the constraint (`any`), which is how the
621
644
  * predicate silently stops being checked. */
622
- export declare type WorkflowCancelOnList<Cancels extends ReadonlyArray<Schema.Schema.Any>, Payload> = {
645
+ export declare type WorkflowCancelOnList<Cancels extends ReadonlyArray<Schema.Top>, Payload> = {
623
646
  readonly [I in keyof Cancels]: WorkflowCancelOn<Cancels[I], Payload>;
624
647
  };
625
648
 
@@ -820,7 +843,7 @@ export declare const WorkflowFlowControlProperty = "__voltroWorkflowFlowControl"
820
843
  * meaning anything if this ever regresses to `any` — which is precisely what
821
844
  * all three failed attempts did.
822
845
  */
823
- declare type WorkflowFn = <const Name extends string, Payload extends WorkflowPayloadInput, Success extends Schema.Schema.Any = typeof Schema.Void, Error extends Schema.Schema.All = typeof Schema.Never, const Messages extends WorkflowMessageSchemas | undefined = undefined, Cancels extends ReadonlyArray<Schema.Schema.Any> = readonly []>(options: {
846
+ declare type WorkflowFn = <const Name extends string, Payload extends WorkflowPayloadInput, Success extends Schema.Top = typeof Schema.Void, Error extends Schema.Top = typeof Schema.Never, const Messages extends WorkflowMessageSchemas | undefined = undefined, Cancels extends ReadonlyArray<Schema.Top> = readonly []>(options: {
824
847
  readonly name: Name;
825
848
  readonly payload: Payload;
826
849
  readonly idempotencyKey: (payload: DecodedPayload<Payload>) => string;
@@ -838,13 +861,15 @@ declare type WorkflowFn = <const Name extends string, Payload extends WorkflowPa
838
861
  readonly schedule?: WorkflowScheduleDeclaration<DecodedPayload<Payload>>;
839
862
  } & Omit<WorkflowBaseOptions, 'name' | 'payload' | 'idempotencyKey' | 'success' | 'error'> & WorkflowVersionOptions & {
840
863
  readonly messages?: Messages;
841
- } & WorkflowFlowControl<DecodedPayload<Payload>> & WorkflowAccessOptions<DecodedPayload<Payload>>) => workflowModule.Workflow<Name, PayloadSchemaOf<Payload>, Success, Error> & WorkflowMessagesCarrier<NormaliseWorkflowMessages<Messages>>;
864
+ } & WorkflowFlowControl<DecodedPayload<Payload>> & WorkflowAccessOptions<DecodedPayload<Payload>>) => workflowModule.Workflow<Name, PayloadSchemaOf<Payload>, Success, Error> & {
865
+ readonly name: Name;
866
+ } & WorkflowMessagesCarrier<NormaliseWorkflowMessages<Messages>>;
842
867
 
843
868
  declare type WorkflowMake = typeof workflowModule.make;
844
869
 
845
870
  export declare interface WorkflowMessagePairSchemas {
846
- readonly payload: Schema.Schema.Any;
847
- readonly success: Schema.Schema.Any;
871
+ readonly payload: Schema.Top;
872
+ readonly success: Schema.Top;
848
873
  }
849
874
 
850
875
  export declare interface WorkflowMessagesCarrier<M extends WorkflowMessagesMetadata = WorkflowMessagesMetadata> {
@@ -862,12 +887,12 @@ export declare interface WorkflowMessagesCarrier<M extends WorkflowMessagesMetad
862
887
  * and updates (synchronous, with a result) are the channels that exist.
863
888
  */
864
889
  export declare interface WorkflowMessageSchemas {
865
- readonly signals?: Readonly<Record<string, Schema.Schema.Any>>;
890
+ readonly signals?: Readonly<Record<string, Schema.Top>>;
866
891
  readonly updates?: Readonly<Record<string, WorkflowMessagePairSchemas>>;
867
892
  }
868
893
 
869
894
  export declare interface WorkflowMessagesMetadata {
870
- readonly signals: Readonly<Record<string, Schema.Schema.Any>>;
895
+ readonly signals: Readonly<Record<string, Schema.Top>>;
871
896
  readonly updates: Readonly<Record<string, WorkflowMessagePairSchemas>>;
872
897
  }
873
898
 
@@ -1049,7 +1074,7 @@ export declare interface WorkflowVersionOptions {
1049
1074
  * suspended-on-failure run shows up under `--status suspended`, NOT in the
1050
1075
  * dead-letter view — it is recoverable, not dead.
1051
1076
  *
1052
- * Maps to `@effect/workflow`'s `SuspendOnFailure` annotation.
1077
+ * Maps to `effect/workflow`'s `SuspendOnFailure` annotation.
1053
1078
  */
1054
1079
  readonly suspendOnFailure?: boolean;
1055
1080
  }
@@ -1,2 +1,225 @@
1
- import { A as e, C as t, D as n, E as r, G as i, J as a, K as o, O as s, S as c, T as l, U as u, W as d, _ as f, a as p, b as m, c as h, d as g, f as _, g as v, h as y, i as b, j as x, k as S, l as C, m as w, n as T, o as E, p as D, q as O, r as k, s as A, t as j, u as M, v as N, w as P, x as F, y as I } from "./primitives-Btjhjm8P.js";
2
- export { P as CurrentWorkflowReplayShape, s as DEFAULT_WORKFLOW_SCHEDULE_MAX_RUNTIME_MS, u as DEFERRING_CONTROLS, j as WorkflowFlowControlProperty, T as WorkflowMessagesProperty, S as WorkflowScheduleProperty, k as WorkflowVersionTypeId, b as WorkflowWorkerLayerTypeId, d as assertConsistentPools, i as deferringControlsOf, p as durableClock, E as durableQueue, A as durableQueueModule, h as durableRateLimiterModule, C as getWorkflowFlowControl, e as getWorkflowSchedule, M as getWorkflowVersionMetadata, o as hasCancelOn, O as hasFlowControl, g as isWorkflowWorkerLayer, l as makeReplayShapeTracker, r as nondeterminismEventPayload, _ as patch, D as processQueue, w as queueWorker, y as rateLimit, n as reportNondeterminism, v as sleep, f as sleepUntil, N as step, I as stepIdempotencyKey, m as stepModule, a as validateFlowControl, x as validateWorkflowSchedule, F as withCompensation, c as workflow, t as workflowModule };
1
+ import { failureMessage as e } from "./failureMessage.js";
2
+ import { attachPreparedWorkflowExecution as t } from "./preparedExecution.js";
3
+ import { CurrentWorkflowEncrypted as n, isQueueEncrypted as r, markQueueEncrypted as i, markWorkflowEncrypted as a, openDefect as o, sealDefect as s, sealedPayloadFields as c, sealedSchema as l } from "./journalEncryption.js";
4
+ import { DEFERRING_CONTROLS as u, assertConsistentPools as d, deferringControlsOf as f, hasCancelOn as p, hasFlowControl as m, validateFlowControl as h } from "./flowControl.js";
5
+ import { CurrentWorkflowPatches as g, CurrentWorkflowRunId as _, CurrentWorkflowStep as v, CurrentWorkflowWakeTenant as ee, WorkflowRunRecorder as y, WorkflowStepInterceptorTag as b } from "./recorder.js";
6
+ import { DEFAULT_WORKFLOW_SCHEDULE_MAX_RUNTIME_MS as x, WorkflowScheduleProperty as S, getWorkflowSchedule as C, validateWorkflowSchedule as w } from "./scheduleDeclaration.js";
7
+ import { CurrentWorkflowReplayShape as T, makeReplayShapeTracker as E, nondeterminismEventPayload as D, reportNondeterminism as O } from "./nondeterminism.js";
8
+ import { applyRetryPolicy as k } from "./retryPolicy.js";
9
+ import { Activity as A, Activity as j, DurableClock as M, DurableClock as N, DurableQueue as P, DurableQueue as te, Workflow as F, Workflow as ne, WorkflowEngine as I } from "effect/workflow";
10
+ import { RateLimiter as L } from "effect/persistence";
11
+ import { Cause as R, Duration as z, Effect as B, Effectable as V, Schema as H } from "effect";
12
+ import { attachWorkflowAccess as U, resolveWorkflowAccess as W } from "@voltro/protocol";
13
+ //#region src/primitives.ts
14
+ var G = Symbol.for("voltro.workflow.workerLayer"), K = Symbol.for("voltro.workflow.version"), q = "__voltroWorkflowMessages", J = "__voltroWorkflowFlowControl", Y = (e) => typeof e == "object" && !!e && e[G] === !0, X = (e) => (typeof e == "object" || typeof e == "function") && e !== null, re = (e) => X(e) && e[K] !== void 0 ? e[K] : {
15
+ version: "1",
16
+ compatibleWith: ["1"],
17
+ patches: []
18
+ }, Z = (e) => {
19
+ let t = e, r = `workflow '${e.name}' defect`;
20
+ return Object.assign(Object.create(Object.getPrototypeOf(e)), e, {
21
+ toLayer: (e) => t.toLayer((t, i) => B.provideService(e(t, i), n, !0).pipe(B.catchDefect((e) => B.die(s(e, r))))),
22
+ execute: (...e) => t.execute(...e).pipe(B.catchDefect((e) => B.die(o(e, r)))),
23
+ annotate: (...e) => Z(t.annotate(...e)),
24
+ annotateContext: (...e) => Z(t.annotateContext(...e))
25
+ });
26
+ }, ie = ((e) => {
27
+ let n = e.encrypted === !0, r = F.make(e.name, n ? {
28
+ ...e,
29
+ payload: c(e.name, e.payload),
30
+ ...e.success === void 0 ? {} : { success: l(e.success, `workflow '${e.name}' result`) },
31
+ ...e.error === void 0 ? {} : { error: l(e.error, `workflow '${e.name}' failure`) }
32
+ } : e);
33
+ n && a(e.name);
34
+ let i = e.suspendOnFailure === !0 ? r.annotate(F.SuspendOnFailure, !0) : r, o = n ? Z(i) : i;
35
+ Object.defineProperty(o, "name", {
36
+ value: e.name,
37
+ enumerable: !0
38
+ }), t(o, (t, n, r) => B.gen(function* () {
39
+ let i = o.payloadSchema.make(t), a = yield* I.WorkflowEngine;
40
+ return yield* B.annotateCurrentSpan({ executionId: n }), yield* a.execute(o, {
41
+ executionId: n,
42
+ payload: i,
43
+ discard: r,
44
+ suspendedRetrySchedule: e.suspendedRetrySchedule
45
+ });
46
+ }).pipe(B.withSpan(`${e.name}.execute`)));
47
+ let s = String(e.version ?? "1"), u = {
48
+ version: s,
49
+ compatibleWith: (e.compatibleWith ?? [s]).map(String),
50
+ patches: [...e.patches ?? []]
51
+ }, d = {
52
+ signals: { ...e.messages?.signals ?? {} },
53
+ updates: { ...e.messages?.updates ?? {} }
54
+ };
55
+ Object.defineProperty(o, K, {
56
+ value: u,
57
+ enumerable: !1
58
+ }), Object.defineProperty(o, q, {
59
+ value: d,
60
+ enumerable: !1
61
+ }), U(o, W(e.name, e));
62
+ let f = h({
63
+ workflowName: e.name,
64
+ payloadSchema: H.isSchema(e.payload) ? e.payload : H.Struct(e.payload),
65
+ control: e
66
+ });
67
+ f !== void 0 && Object.defineProperty(o, J, {
68
+ value: f,
69
+ enumerable: !1
70
+ });
71
+ let p = w(e.name, e.schedule);
72
+ return p !== void 0 && Object.defineProperty(o, S, {
73
+ value: p,
74
+ enumerable: !1
75
+ }), o;
76
+ }), ae = (e) => {
77
+ if (!X(e)) return;
78
+ let t = e[J];
79
+ return t === void 0 ? void 0 : t;
80
+ }, oe = (e) => {
81
+ if (e.encrypted !== !0) return P.make(e);
82
+ i(e.name);
83
+ let t = H.isSchema(e.payload) ? e.payload : H.Struct(e.payload);
84
+ return P.make({
85
+ ...e,
86
+ payload: l(t, `queue '${e.name}' payload`),
87
+ success: l(e.success ?? H.Void, `queue '${e.name}' result`),
88
+ error: l(e.error ?? H.Never, `queue '${e.name}' failure`)
89
+ });
90
+ }, se = ((e, ...t) => B.flatMap(n, (n) => n && !r(e.name) ? B.die(/* @__PURE__ */ Error(`an encrypted workflow enqueued into durable queue '${e.name}', which is not encrypted: the queue's journal would hold the value in plaintext. Declare \`durableQueue({ …, encrypted: true })\`.`)) : P.process(e, ...t))), Q = ((...e) => {
91
+ let t = P.worker(...e);
92
+ return Object.defineProperty(t, G, {
93
+ value: !0,
94
+ enumerable: !1
95
+ }), t;
96
+ }), ce = (e) => B.gen(function* () {
97
+ let t = yield* A.make({
98
+ name: `${e.name}/rateLimit`,
99
+ success: H.Number,
100
+ error: L.RateLimiterError,
101
+ execute: B.gen(function* () {
102
+ let t = yield* (yield* L.RateLimiter).consume({
103
+ ...e,
104
+ onExceeded: "delay"
105
+ });
106
+ return z.toMillis(t.delay);
107
+ })
108
+ });
109
+ t > 0 && (yield* M.sleep({
110
+ name: `${e.name}/rateLimit`,
111
+ duration: z.millis(t)
112
+ }));
113
+ }), $ = (e) => B.gen(function* () {
114
+ let t = yield* _, n = yield* B.serviceOption(y), r = z.toMillis(z.fromInputUnsafe(e.duration));
115
+ if (t !== void 0 && n._tag === "Some") {
116
+ let i = n.value, a = new Date(Date.now() + r).toISOString(), o = yield* ee;
117
+ yield* B.promise(() => i.recordEvent({
118
+ runId: t,
119
+ eventType: "timer-set",
120
+ payload: {
121
+ name: e.name,
122
+ durationMs: r,
123
+ scheduledWakeAt: a,
124
+ ...o === void 0 ? {} : { tenantId: o }
125
+ }
126
+ }).catch(() => {}));
127
+ let s = Date.now();
128
+ yield* M.sleep(e), yield* B.promise(() => i.recordEvent({
129
+ runId: t,
130
+ eventType: "timer-fired",
131
+ payload: {
132
+ name: e.name,
133
+ actualDurationMs: Date.now() - s,
134
+ ...o === void 0 ? {} : { tenantId: o }
135
+ }
136
+ }).catch(() => {}));
137
+ } else yield* M.sleep(e);
138
+ }), le = (e) => B.gen(function* () {
139
+ let t = (yield* A.make({
140
+ name: `sleepUntil:${e.name}`,
141
+ success: H.Number,
142
+ execute: B.sync(() => e.until instanceof Date ? e.until.getTime() : e.until)
143
+ })) - Date.now();
144
+ t <= 0 || (yield* $({
145
+ name: e.name,
146
+ duration: `${t} millis`
147
+ }));
148
+ }), ue = (t, r, i, a) => B.gen(function* () {
149
+ let o = yield* _, s = yield* A.CurrentAttempt, c = yield* B.serviceOption(y), l = yield* B.serviceOption(b), u = l._tag === "Some" ? l.value.interceptor(r, {
150
+ runId: o ?? "unrecorded",
151
+ stepName: t,
152
+ attempt: s
153
+ }) : r, d, f, p = !1;
154
+ if (o !== void 0 && c._tag === "Some") {
155
+ f = c.value;
156
+ let e = a === void 0 ? void 0 : (({ retryable: e, ...t }) => t)(a);
157
+ p = yield* n;
158
+ try {
159
+ d = yield* B.promise(() => f.startStep({
160
+ runId: o,
161
+ stepName: t,
162
+ attempt: s,
163
+ stepInput: i,
164
+ sealed: p,
165
+ ...e === void 0 ? {} : { retryPolicy: e }
166
+ }));
167
+ } catch {
168
+ d = void 0;
169
+ }
170
+ }
171
+ let m = Date.now();
172
+ return yield* B.provideService(k(u, a), v, t).pipe(B.tap((e) => d && f ? B.promise(async () => {
173
+ try {
174
+ await f.endStepSuccess({
175
+ stepRecordId: d,
176
+ sealed: p,
177
+ output: e,
178
+ durationMs: Date.now() - m
179
+ });
180
+ } catch {}
181
+ }) : B.void), B.tapCause((t) => d && f && !R.hasInterruptsOnly(t) ? B.promise(async () => {
182
+ try {
183
+ let n = R.findErrorOption(t), r = t.reasons.filter(R.isFailReason).map((e) => e.error), i = t.reasons.filter(R.isDieReason).map((e) => e.defect), a = n._tag === "Some" ? n.value : i[0] ?? R.squash(t), o = e(a), s = a && typeof a == "object" && "_tag" in a ? String(a._tag) : null;
184
+ await f.endStepFailure({
185
+ stepRecordId: d,
186
+ sealed: p,
187
+ errorTag: s,
188
+ errorMessage: o,
189
+ errorCause: {
190
+ pretty: R.pretty(t),
191
+ failures: r,
192
+ defects: i
193
+ },
194
+ durationMs: Date.now() - m
195
+ });
196
+ } catch {}
197
+ }) : B.void));
198
+ }), de = (e) => B.gen(function* () {
199
+ let t = yield* T;
200
+ if (t === void 0) return;
201
+ let n = t.reach(e);
202
+ n !== void 0 && (yield* O([n]));
203
+ }), fe = (e, t, r) => {
204
+ let i = e;
205
+ return {
206
+ ...e,
207
+ ...V.Prototype({
208
+ label: "Activity",
209
+ evaluate: () => B.andThen(de(t), r === void 0 ? i : B.flatMap(n, (e) => e ? r().pipe(B.catchDefect((e) => B.die(o(e, `step '${t}' defect`)))) : i))
210
+ })
211
+ };
212
+ }, pe = (e) => {
213
+ let { input: t, retry: n, ...r } = e, i = ue(r.name, r.execute, t, n), a = A.make({
214
+ ...r,
215
+ execute: i
216
+ }), o, c = `step '${r.name}' defect`;
217
+ return fe(a, r.name, () => o ??= A.make({
218
+ ...r,
219
+ success: l(r.success ?? H.Void, `step '${r.name}' result`),
220
+ error: l(r.error ?? H.Never, `step '${r.name}' failure`),
221
+ execute: i.pipe(B.catchDefect((e) => B.die(s(e, c))))
222
+ }));
223
+ }, me = (e) => B.map(g, (t) => t.includes(e)), he = F.withCompensation, ge = A.idempotencyKey;
224
+ //#endregion
225
+ export { T as CurrentWorkflowReplayShape, x as DEFAULT_WORKFLOW_SCHEDULE_MAX_RUNTIME_MS, u as DEFERRING_CONTROLS, J as WorkflowFlowControlProperty, q as WorkflowMessagesProperty, S as WorkflowScheduleProperty, K as WorkflowVersionTypeId, G as WorkflowWorkerLayerTypeId, d as assertConsistentPools, f as deferringControlsOf, N as durableClock, oe as durableQueue, te as durableQueueModule, ae as getWorkflowFlowControl, C as getWorkflowSchedule, re as getWorkflowVersionMetadata, p as hasCancelOn, m as hasFlowControl, X as isCarrier, Y as isWorkflowWorkerLayer, E as makeReplayShapeTracker, D as nondeterminismEventPayload, me as patch, se as processQueue, Q as queueWorker, ce as rateLimit, O as reportNondeterminism, $ as sleep, le as sleepUntil, pe as step, ge as stepIdempotencyKey, j as stepModule, h as validateFlowControl, w as validateWorkflowSchedule, he as withCompensation, ie as workflow, ne as workflowModule };