@demlik/tea 0.15.0 → 0.16.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/README.md +30 -7
- package/dist/agent/index.d.ts +49 -37
- package/dist/agent/index.js +12 -8
- package/dist/chunk-4LPY67E4.js +18 -0
- package/dist/chunk-4LPY67E4.js.map +1 -0
- package/dist/chunk-5XU6ZJO2.js +533 -0
- package/dist/chunk-5XU6ZJO2.js.map +1 -0
- package/dist/{chunk-AYS5N6WY.js → chunk-6NG4V5SB.js} +62 -172
- package/dist/chunk-6NG4V5SB.js.map +1 -0
- package/dist/{chunk-3B5X7SBB.js → chunk-7MGXQZPW.js} +11 -9
- package/dist/chunk-7MGXQZPW.js.map +1 -0
- package/dist/{chunk-V46HSVCK.js → chunk-BCTEOVOU.js} +3 -3
- package/dist/{chunk-V46HSVCK.js.map → chunk-BCTEOVOU.js.map} +1 -1
- package/dist/chunk-CH5KTOEZ.js +710 -0
- package/dist/chunk-CH5KTOEZ.js.map +1 -0
- package/dist/chunk-CIHSHLQX.js +64 -0
- package/dist/chunk-CIHSHLQX.js.map +1 -0
- package/dist/{chunk-TCLBCERH.js → chunk-EHUDXAKC.js} +238 -212
- package/dist/chunk-EHUDXAKC.js.map +1 -0
- package/dist/chunk-GOX2CYIM.js +380 -0
- package/dist/chunk-GOX2CYIM.js.map +1 -0
- package/dist/{chunk-22POWGFA.js → chunk-IVJP3GKJ.js} +46 -20
- package/dist/chunk-IVJP3GKJ.js.map +1 -0
- package/dist/{chunk-QPEVCJ5Q.js → chunk-MVZS5FDM.js} +13 -6
- package/dist/chunk-MVZS5FDM.js.map +1 -0
- package/dist/{chunk-VTQI2NHP.js → chunk-MYNLY3HP.js} +9 -8
- package/dist/chunk-MYNLY3HP.js.map +1 -0
- package/dist/{chunk-Q5CQTBFA.js → chunk-NSIAORRY.js} +20 -30
- package/dist/chunk-NSIAORRY.js.map +1 -0
- package/dist/{chunk-MYXFNWAJ.js → chunk-QNGYQMZB.js} +4 -4
- package/dist/chunk-QNGYQMZB.js.map +1 -0
- package/dist/chunk-WT5PBPLB.js +98 -0
- package/dist/chunk-WT5PBPLB.js.map +1 -0
- package/dist/{core-DnzqWy6u.d.ts → core-BbgtiXdg.d.ts} +231 -139
- package/dist/do/index.d.ts +37 -33
- package/dist/do/index.js +21 -14
- package/dist/do/index.js.map +1 -1
- package/dist/{durable-effects-CWzA-o2B.d.ts → durable-effects-7MTK_jnj.d.ts} +1 -1
- package/dist/effect/index.d.ts +151 -0
- package/dist/effect/index.js +98 -0
- package/dist/effect/index.js.map +1 -0
- package/dist/extension/index.d.ts +6 -7
- package/dist/extension/index.js +3 -2
- package/dist/extension/index.js.map +1 -1
- package/dist/flow/index.d.ts +68 -59
- package/dist/flow/index.js +32 -27
- package/dist/flow/index.js.map +1 -1
- package/dist/idempotency/index.d.ts +6 -7
- package/dist/idempotency/index.js +4 -2
- package/dist/{index-CSyMYDAB.d.ts → index-7vV8xmsD.d.ts} +1 -1
- package/dist/{index-KXqTRJyb.d.ts → index-Bz5Rh9Ga.d.ts} +19 -96
- package/dist/index-CjFDUBeq.d.ts +207 -0
- package/dist/{index-CuNO9m8i.d.ts → index-CkFYA9Y6.d.ts} +14 -16
- package/dist/{index-CA_7I5g9.d.ts → index-Cou86-GX.d.ts} +137 -246
- package/dist/{index-DrIRb_Ch.d.ts → index-DU6JpQ8G.d.ts} +1 -1
- package/dist/{index-HSYgG2Yt.d.ts → index-Xufl55W8.d.ts} +247 -211
- package/dist/{index-C2DwkjlP.d.ts → index-_dOR3xqA.d.ts} +57 -45
- package/dist/index.d.ts +121 -385
- package/dist/index.js +2 -1
- package/dist/jev/index.d.ts +133 -97
- package/dist/jev/index.js +205 -161
- package/dist/jev/index.js.map +1 -1
- package/dist/{machine-DGlPWCWI.d.ts → machine-BQzTV8On.d.ts} +171 -288
- package/dist/machine-viz/index.d.ts +5 -5
- package/dist/machine-viz/index.js +8 -4
- package/dist/machine-viz/index.js.map +1 -1
- package/dist/mem/index.d.ts +3 -4
- package/dist/mem/index.js +2 -1
- package/dist/mem/index.js.map +1 -1
- package/dist/node/index.d.ts +119 -78
- package/dist/node/index.js +52 -38
- package/dist/node/index.js.map +1 -1
- package/dist/paginate/index.d.ts +27 -22
- package/dist/paginate/index.js +6 -4
- package/dist/parity/index.d.ts +4 -5
- package/dist/parity/index.js +3 -2
- package/dist/parity/index.js.map +1 -1
- package/dist/pbt/index.d.ts +2 -2
- package/dist/pbt/index.js +2 -1
- package/dist/pbt/index.js.map +1 -1
- package/dist/persistence/index.d.ts +6 -7
- package/dist/persistence/index.js +5 -3
- package/dist/promise/index.d.ts +186 -0
- package/dist/promise/index.js +5 -0
- package/dist/promise/index.js.map +1 -0
- package/dist/{protocol-D8VbH-VH.d.ts → protocol-ClRZBhHQ.d.ts} +7 -8
- package/dist/react/index.d.ts +36 -17
- package/dist/react/index.js +27 -4
- package/dist/react/index.js.map +1 -1
- package/dist/resilience/index.d.ts +63 -456
- package/dist/resilience/index.js +37 -483
- package/dist/resilience/index.js.map +1 -1
- package/dist/{runtime-types-CMF13BBh.d.ts → runtime-types-CiVpC0HN.d.ts} +131 -388
- package/dist/testing/index.d.ts +22 -16
- package/dist/testing/index.js +15 -7
- package/dist/testing/index.js.map +1 -1
- package/dist/timing/index.d.ts +25 -22
- package/dist/timing/index.js +4 -3
- package/dist/timing/index.js.map +1 -1
- package/dist/{types-BseNPIhr.d.ts → types-LxZxGYda.d.ts} +2 -2
- package/dist/work-queue/index.d.ts +5 -6
- package/package.json +18 -5
- package/dist/chunk-22POWGFA.js.map +0 -1
- package/dist/chunk-3B5X7SBB.js.map +0 -1
- package/dist/chunk-66PY5WYF.js +0 -1816
- package/dist/chunk-66PY5WYF.js.map +0 -1
- package/dist/chunk-AYS5N6WY.js.map +0 -1
- package/dist/chunk-L3TND7LA.js +0 -97
- package/dist/chunk-L3TND7LA.js.map +0 -1
- package/dist/chunk-MYXFNWAJ.js.map +0 -1
- package/dist/chunk-Q5CQTBFA.js.map +0 -1
- package/dist/chunk-QPEVCJ5Q.js.map +0 -1
- package/dist/chunk-TCLBCERH.js.map +0 -1
- package/dist/chunk-VTQI2NHP.js.map +0 -1
- package/dist/index-ZCMhnVKN.d.ts +0 -272
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { I as IdempotencyStore } from '../index-Bc40JWVl.js';
|
|
2
2
|
export { a as IdempotencyEntry, e as evictExpired, i as initStore, r as recall, b as remember, s as seen } from '../index-Bc40JWVl.js';
|
|
3
|
-
import {
|
|
4
|
-
import { Q as QueueItem } from '../index-
|
|
5
|
-
import '
|
|
6
|
-
import '../runtime-types-
|
|
7
|
-
import 'better-result';
|
|
3
|
+
import { c as CmdOf, b as CmdDef } from '../core-BbgtiXdg.js';
|
|
4
|
+
import { Q as QueueItem } from '../index-7vV8xmsD.js';
|
|
5
|
+
import '@standard-schema/spec';
|
|
6
|
+
import '../runtime-types-CiVpC0HN.js';
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* A cached intake entry: either a key whose work is still in flight
|
|
@@ -69,7 +68,7 @@ declare function intakeProcessDef<P>(): CmdDef<"intake:process", {
|
|
|
69
68
|
readonly itemId: string;
|
|
70
69
|
/** The original payload, for the worker to process. */
|
|
71
70
|
readonly payload: P;
|
|
72
|
-
},
|
|
71
|
+
}, undefined, never>;
|
|
73
72
|
type IntakeProcessCmd<P> = CmdOf<ReturnType<typeof intakeProcessDef<P>>>;
|
|
74
73
|
/**
|
|
75
74
|
* A duplicate of an already-completed key arrived — replay the cached result
|
|
@@ -80,7 +79,7 @@ declare function intakeReplayDef<R>(): CmdDef<"intake:replay", {
|
|
|
80
79
|
readonly key: string;
|
|
81
80
|
/** The result the ORIGINAL request produced, recalled from the cache. */
|
|
82
81
|
readonly result: R;
|
|
83
|
-
},
|
|
82
|
+
}, undefined, never>;
|
|
84
83
|
type IntakeReplayCmd<R> = CmdOf<ReturnType<typeof intakeReplayDef<R>>>;
|
|
85
84
|
/** The Cmd union the intake verbs emit. */
|
|
86
85
|
type IntakeCmd<P, R> = IntakeProcessCmd<P> | IntakeReplayCmd<R>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
export { createIntake, intakeProcessDef, intakeReplayDef } from '../chunk-
|
|
1
|
+
export { createIntake, intakeProcessDef, intakeReplayDef } from '../chunk-MYNLY3HP.js';
|
|
2
2
|
export { evictExpired, initStore, recall, remember, seen } from '../chunk-PR6TB3BL.js';
|
|
3
3
|
import '../chunk-TXN2KFHF.js';
|
|
4
|
-
import '../chunk-
|
|
4
|
+
import '../chunk-4LPY67E4.js';
|
|
5
|
+
import '../chunk-GOX2CYIM.js';
|
|
6
|
+
import '../chunk-CH5KTOEZ.js';
|
|
5
7
|
//# sourceMappingURL=index.js.map
|
|
6
8
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,89 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { S as SnapshotWriteCmd, a as SnapshotState, b as
|
|
3
|
-
import { D as DeadlineExceeded, a as DeadlineSub } from './index-
|
|
4
|
-
import { Q as QueueItem } from './index-
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* internal/flow/monitored-run — a long-running operation that is BOTH staged and
|
|
8
|
-
* watched: an ordered stage pipeline whose POSITION survives eviction, wrapped
|
|
9
|
-
* by a no-progress safety deadline and (optionally) a periodic durable
|
|
10
|
-
* checkpoint.
|
|
11
|
-
*
|
|
12
|
-
* This is the merge of two field-guide concerns the audit-agent machine
|
|
13
|
-
* hand-wired together (`seed/audit-agent-machine`): the OUTER pipeline position
|
|
14
|
-
* (`RunStage` — planning → testing → summarizing → reporting, replayed on cold
|
|
15
|
-
* wake by re-emitting the one outstanding effect) and the no-progress safety
|
|
16
|
-
* alarm (`subs.ts`, keyed on `progressSeq` so every progress event retires the
|
|
17
|
-
* old alarm and arms a fresh one). `monitored-run` lifts both into one config-
|
|
18
|
-
* driven knob with the uniform L2 contract `resilient-call` established:
|
|
19
|
-
* `init()`, the verbs (`start` / `advance` / `progress` / `onDeadline` /
|
|
20
|
-
* `boot`), `subs(state)`, and `handlers(ports)`.
|
|
21
|
-
*
|
|
22
|
-
* - It is **staged, optionally**. Omit `stages` and the run is single-shot:
|
|
23
|
-
* `start` enters `running`, `advance` finishes it to `done`. Provide
|
|
24
|
-
* `stages` and it becomes an ordered pipeline — each `advance` retires the
|
|
25
|
-
* current stage and claims the next, finishing to `done` only when the last
|
|
26
|
-
* stage is retired. The pipeline POSITION lives in the Model (a
|
|
27
|
-
* `work-queue` of stage items), so an eviction mid-pipeline resumes at the
|
|
28
|
-
* same stage via `boot` — the audit machine's "pipeline position survives
|
|
29
|
-
* eviction" property, generalized.
|
|
30
|
-
* - It is **watched**. While `running`, a no-progress deadline is armed at
|
|
31
|
-
* `lastProgressAt + deadlineMs` and keyed on `progressSeq`. Every
|
|
32
|
-
* `progress` / `advance` bumps the seq, so the substrate retires the old
|
|
33
|
-
* alarm and arms a new one — a self-rearming watchdog. If the alarm fires
|
|
34
|
-
* (`onDeadline`) the run goes `failed` with a deadline reason. Omit
|
|
35
|
-
* `deadlineMs` → no watchdog (the `stale` phase is never reachable).
|
|
36
|
-
* - It **checkpoints, optionally**. Provide `snapshotEvery` and every
|
|
37
|
-
* progress unit is accounted to a `../snapshot` slice; once the cadence is
|
|
38
|
-
* reached a checkpoint Cmd is emitted (interpreted by the spliced snapshot
|
|
39
|
-
* `handlers`), so a crashed run restarts from the last durable checkpoint
|
|
40
|
-
* rather than from zero. Omit it → no checkpointing.
|
|
41
|
-
*
|
|
42
|
-
* ## Why the run lifecycle is INLINE (run-tracker not extracted)
|
|
43
|
-
*
|
|
44
|
-
* The phase union (`idle` / `running` / `stale` / `done` / `failed` / `cancelled`, a
|
|
45
|
-
* discriminated union carrying only each phase's own data) and its bookkeeping
|
|
46
|
-
* (`runId`, `startedAt`, `lastProgressAt`, `progressSeq`) live directly on this
|
|
47
|
-
* slice rather than behind a `run-tracker` sub-knob.
|
|
48
|
-
* Extraction earns its keep when two independent axes vary; here the lifecycle
|
|
49
|
-
* has exactly one anchoring axis (this run), so a separate module would be a
|
|
50
|
-
* premature seam. The two genuinely independent axes — the safety DEADLINE and
|
|
51
|
-
* the periodic SNAPSHOT — ARE extracted (`../deadline`, `../snapshot`), and the
|
|
52
|
-
* stage list is a `../work-queue` slice (`QueueItem<Stage>[]`) whose every
|
|
53
|
-
* status flip is DELEGATED to the blessed `../work-queue/ops` (`enqueueOp` /
|
|
54
|
-
* `claimNextOp` / `markDoneOp`) — never re-rolled here. The lifecycle is the
|
|
55
|
-
* glue between them.
|
|
56
|
-
*
|
|
57
|
-
* ## The two non-negotiables (canon)
|
|
58
|
-
*
|
|
59
|
-
* - **Durable** — the slice is plain data (the stage queue is a
|
|
60
|
-
* JSON-serializable `QueueItem<Stage>[]`, the snapshot slice is plain
|
|
61
|
-
* numbers), so it survives DO eviction / reload.
|
|
62
|
-
* - **Replayable** — every transition is a pure verb returning new state +
|
|
63
|
-
* Cmds; nothing here reads the clock or RNG. Time arrives as an `at` / `atMs`
|
|
64
|
-
* parameter; the only clock read is `Date.now()` inside the snapshot
|
|
65
|
-
* `handlers` port (the effect boundary), exactly as `../snapshot` stamps it.
|
|
66
|
-
*
|
|
67
|
-
* ## Typical wiring
|
|
68
|
-
*
|
|
69
|
-
* const run = createMonitoredRun<MyStage, MyState>({
|
|
70
|
-
* stages: ["plan", "test", "report"],
|
|
71
|
-
* deadlineMs: 10 * 60_000,
|
|
72
|
-
* snapshotEvery: 25,
|
|
73
|
-
* });
|
|
74
|
-
*
|
|
75
|
-
* init: (loaded) => loaded ? [loaded, []] : [{ run: run.init() }, []],
|
|
76
|
-
* update: {
|
|
77
|
-
* begin: (s, m) => lift(s, run.start(s.run, m.runId, m.at)),
|
|
78
|
-
* advance: (s, m) => lift(s, run.advance(s.run, checkpoint(s), m.result, m.at)),
|
|
79
|
-
* progress: (s, m) => lift(s, run.progress(s.run, checkpoint(s), m.at)),
|
|
80
|
-
* run_deadline: (s, m) => lift(s, run.onDeadline(s.run, m)),
|
|
81
|
-
* boot: (s, m) => lift(s, run.boot(s.run, m.at)),
|
|
82
|
-
* },
|
|
83
|
-
* subscriptions: (s) => run.subs(s.run),
|
|
84
|
-
* subscribe: { deadline: subscribeDeadline },
|
|
85
|
-
* interpret: run.handlers({ store: r2 }),
|
|
86
|
-
*/
|
|
1
|
+
import { b as CmdDef, T as TimerDeps, C as Cmd } from './core-BbgtiXdg.js';
|
|
2
|
+
import { S as SnapshotWriteCmd, a as SnapshotState, b as SnapshotSavedMsg } from './index-CjFDUBeq.js';
|
|
3
|
+
import { D as DeadlineExceeded, a as DeadlineSub } from './index-Xufl55W8.js';
|
|
4
|
+
import { Q as QueueItem } from './index-7vV8xmsD.js';
|
|
87
5
|
|
|
88
6
|
/**
|
|
89
7
|
* The monitored-run knob. EVERY field is optional:
|
|
@@ -263,11 +181,6 @@ type StageResult = {
|
|
|
263
181
|
type MonitoredRunCmd<V> = SnapshotWriteCmd<V>;
|
|
264
182
|
/** The deadline Msg the safety alarm dispatches when the watchdog fires. */
|
|
265
183
|
type MonitoredRunTimerMsg = DeadlineExceeded;
|
|
266
|
-
/** Ports the consumer supplies to `handlers` — just the checkpoint store. */
|
|
267
|
-
interface MonitoredRunPorts<V> {
|
|
268
|
-
/** Where periodic checkpoints are written (R2 / KV / DO sub-key / Map). */
|
|
269
|
-
readonly store: SnapshotStore<V>;
|
|
270
|
-
}
|
|
271
184
|
/**
|
|
272
185
|
* Build a monitored-run knob from `config`. `Stage` is the consumer's stage
|
|
273
186
|
* identifier type; `V` is the consumer's checkpoint value type (what
|
|
@@ -275,9 +188,19 @@ interface MonitoredRunPorts<V> {
|
|
|
275
188
|
*
|
|
276
189
|
* No `rng` parameter: unlike `resilient-call`, nothing here jitters — the only
|
|
277
190
|
* external inputs are time (an `at` / `atMs` parameter) and the consumer's
|
|
278
|
-
* stage outcomes.
|
|
191
|
+
* stage outcomes.
|
|
279
192
|
*/
|
|
280
193
|
declare function createMonitoredRun<Stage, V = unknown>(config?: MonitoredRunConfig<Stage>): {
|
|
194
|
+
/** The `snapshot_write` Cmd def — list it in `cmds` when checkpointing. */
|
|
195
|
+
checkpoint: CmdDef<"snapshot_write", {
|
|
196
|
+
readonly key: string;
|
|
197
|
+
readonly seq: number;
|
|
198
|
+
readonly at: number;
|
|
199
|
+
readonly payload: V;
|
|
200
|
+
}, undefined, {
|
|
201
|
+
readonly [detail: string]: unknown;
|
|
202
|
+
readonly _tag: "snapshot_write_failed";
|
|
203
|
+
}>;
|
|
281
204
|
init: () => MonitoredRunState<Stage>;
|
|
282
205
|
start: (s: MonitoredRunState<Stage>, runId: string, at: number) => readonly [MonitoredRunState<Stage>, readonly MonitoredRunCmd<V>[]];
|
|
283
206
|
progress: (s: MonitoredRunState<Stage>, payload: V, at: number) => readonly [MonitoredRunState<Stage>, readonly MonitoredRunCmd<V>[]];
|
|
@@ -286,9 +209,9 @@ declare function createMonitoredRun<Stage, V = unknown>(config?: MonitoredRunCon
|
|
|
286
209
|
advance: (s: MonitoredRunState<Stage>, payload: V, result: StageResult, at: number) => readonly [MonitoredRunState<Stage>, readonly MonitoredRunCmd<V>[]];
|
|
287
210
|
onDeadline: (s: MonitoredRunState<Stage>, msg: MonitoredRunTimerMsg) => readonly [MonitoredRunState<Stage>, readonly MonitoredRunCmd<V>[]];
|
|
288
211
|
boot: (s: MonitoredRunState<Stage>, at: number) => readonly [MonitoredRunState<Stage>, readonly MonitoredRunCmd<V>[]];
|
|
289
|
-
confirmSnapshot: (s: MonitoredRunState<Stage>, msg: SnapshotSavedMsg) => MonitoredRunState<Stage>;
|
|
290
|
-
|
|
291
|
-
|
|
212
|
+
confirmSnapshot: (s: MonitoredRunState<Stage>, msg: SnapshotSavedMsg<V>) => MonitoredRunState<Stage>;
|
|
213
|
+
deadlines: (s: MonitoredRunState<Stage>) => readonly DeadlineSub[];
|
|
214
|
+
timer: (s: MonitoredRunState<Stage>) => TimerDeps<MonitoredRunTimerMsg> | null;
|
|
292
215
|
};
|
|
293
216
|
/**
|
|
294
217
|
* Lift a knob result `[slice, cmds]` into a host `[State, cmds]` where the
|
|
@@ -300,4 +223,4 @@ declare function liftRun<S extends {
|
|
|
300
223
|
run: MonitoredRunState<Stage>;
|
|
301
224
|
}, Stage, C extends Cmd>(state: S, [slice, cmds]: readonly [MonitoredRunState<Stage>, readonly C[]]): readonly [S, readonly C[]];
|
|
302
225
|
|
|
303
|
-
export { type EndedRun as E, type MonitoredRunCmd as M, type RunFailure as R, type StageResult as S, type MonitoredRunState as a, type MonitoredRunConfig as b, type
|
|
226
|
+
export { type EndedRun as E, type MonitoredRunCmd as M, type RunFailure as R, type StageResult as S, type MonitoredRunState as a, type MonitoredRunConfig as b, type MonitoredRunTimerMsg as c, createMonitoredRun as d, liftRun as l };
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { c as CmdOf, b as CmdDef, e as SettledOk, f as SettledErr, g as TaggedError, C as Cmd } from './core-BbgtiXdg.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The snapshot knob.
|
|
5
|
+
*
|
|
6
|
+
* `every` is the cadence: a checkpoint is written once `every` units of
|
|
7
|
+
* progress have accumulated since the last one (see `record`). It is the
|
|
8
|
+
* `snapshotEvery` field `monitored-run` threads through to this module.
|
|
9
|
+
*
|
|
10
|
+
* `key` is the store key the checkpoint is written under. A single machine
|
|
11
|
+
* keeps a single rolling checkpoint, so the key is fixed at config time rather
|
|
12
|
+
* than passed per write — the latest checkpoint overwrites the previous one
|
|
13
|
+
* (R2/KV are last-write-wins on a key). Defaults to `"@@snapshot"`, mirroring
|
|
14
|
+
* `doStore`'s `@@state` default-key convention.
|
|
15
|
+
*/
|
|
16
|
+
interface SnapshotConfig {
|
|
17
|
+
/**
|
|
18
|
+
* Write a checkpoint once this many progress units have accumulated since the
|
|
19
|
+
* last write. `every: 1` checkpoints on every `record`; a value `<= 0` is
|
|
20
|
+
* treated as `1` (every progress unit triggers a write) — a non-positive
|
|
21
|
+
* cadence has no other sensible meaning, and clamping keeps `record` from
|
|
22
|
+
* never checkpointing on a misconfigured `0`.
|
|
23
|
+
*/
|
|
24
|
+
readonly every: number;
|
|
25
|
+
/** Store key the rolling checkpoint is written under. Defaults to `"@@snapshot"`. */
|
|
26
|
+
readonly key?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The snapshot bookkeeping slice. Plain data — JSON-serializable so it rides
|
|
30
|
+
* inside the consumer's `Store<S>` blob and survives DO eviction / reload (the
|
|
31
|
+
* "durable" non-negotiable). It carries NO payload: the thing being
|
|
32
|
+
* checkpointed lives elsewhere in the machine's state; this slice only tracks
|
|
33
|
+
* *when* to checkpoint and *what has been acknowledged durable*.
|
|
34
|
+
*
|
|
35
|
+
* - `sinceLast` — progress units accumulated since the last checkpoint
|
|
36
|
+
* DECISION (reset to 0 the moment `record` decides to write, not when the
|
|
37
|
+
* write lands). The cadence counter.
|
|
38
|
+
* - `seq` — monotonic checkpoint sequence. Bumped each time a write is
|
|
39
|
+
* emitted, so the write Cmd and its later acknowledgement can be matched
|
|
40
|
+
* even if several are in flight. The "version" of the latest emitted
|
|
41
|
+
* checkpoint.
|
|
42
|
+
* - `lastSavedSeq` — the highest `seq` whose write the host has confirmed
|
|
43
|
+
* durable (via `confirm`). `null` until the first confirmed write. The gap
|
|
44
|
+
* `seq - lastSavedSeq` is the "writes emitted but not yet acknowledged"
|
|
45
|
+
* depth — observable for backpressure / health.
|
|
46
|
+
* - `lastSavedAt` — the `at` of the most recent confirmed write (epoch ms),
|
|
47
|
+
* `null` until the first. Carried for observability, never compared inside
|
|
48
|
+
* a verb (time is injected, never read here).
|
|
49
|
+
*/
|
|
50
|
+
interface SnapshotState {
|
|
51
|
+
readonly sinceLast: number;
|
|
52
|
+
readonly seq: number;
|
|
53
|
+
readonly lastSavedSeq: number | null;
|
|
54
|
+
readonly lastSavedAt: number | null;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The checkpoint-write Cmd a `record` / `force` decision emits. Plain data
|
|
58
|
+
* (invariant 1 — Cmds are data, not closures): it carries the `payload` to
|
|
59
|
+
* write, the `key` to write it under, the `seq` it represents, and the `at` it
|
|
60
|
+
* was decided.
|
|
61
|
+
*
|
|
62
|
+
* `payload` is `V` — the consumer's serializable checkpoint value (the run
|
|
63
|
+
* state, the cursor, whatever the machine wants restartable). The verb takes it
|
|
64
|
+
* as an argument so the snapshot slice never has to hold a copy of the
|
|
65
|
+
* machine's domain state.
|
|
66
|
+
*
|
|
67
|
+
* `Cmd.define`d (ADR 0014, 0021), minted per `V` by a factory the way
|
|
68
|
+
* `workflowActivityDef<A>()` is, since the payload type is the knob's own
|
|
69
|
+
* parameter. The handler you write puts the payload in your store and returns
|
|
70
|
+
* `ok(undefined)`, or `err({ _tag: "snapshot_write_failed", … })`; the engine
|
|
71
|
+
* mints `snapshot_write_ok` / `snapshot_write_err`.
|
|
72
|
+
*/
|
|
73
|
+
declare function snapshotWriteDef<V>(): CmdDef<"snapshot_write", {
|
|
74
|
+
readonly key: string;
|
|
75
|
+
readonly seq: number;
|
|
76
|
+
readonly at: number;
|
|
77
|
+
readonly payload: V;
|
|
78
|
+
}, undefined, {
|
|
79
|
+
readonly [detail: string]: unknown;
|
|
80
|
+
readonly _tag: "snapshot_write_failed";
|
|
81
|
+
}>;
|
|
82
|
+
type SnapshotWriteCmd<V> = CmdOf<ReturnType<typeof snapshotWriteDef<V>>>;
|
|
83
|
+
/**
|
|
84
|
+
* The checkpoint-READ Cmd a `requestLoad` decision emits — the recovery half of
|
|
85
|
+
* the module. Plain data (invariant 1): it carries only the `key` to read. The
|
|
86
|
+
* handler you write reads the store and returns `ok(payload)` — `null` when
|
|
87
|
+
* the store has no checkpoint under `key` — or
|
|
88
|
+
* `err({ _tag: "snapshot_load_failed", … })`.
|
|
89
|
+
*
|
|
90
|
+
* Distinct from `snapshot_write`: a write carries a payload OUT to the store; a
|
|
91
|
+
* load asks the store to hand a payload BACK. The consumer dispatches the
|
|
92
|
+
* triggering Msg once on resume (a `boot` Msg, never `init`'s rehydrate branch —
|
|
93
|
+
* invariant 2), folds the recovered payload into its run slice, then continues.
|
|
94
|
+
*/
|
|
95
|
+
declare function snapshotLoadDef<V>(): CmdDef<"snapshot_load", {
|
|
96
|
+
readonly key: string;
|
|
97
|
+
}, V | null, {
|
|
98
|
+
readonly [detail: string]: unknown;
|
|
99
|
+
readonly _tag: "snapshot_load_failed";
|
|
100
|
+
}>;
|
|
101
|
+
type SnapshotLoadCmd<V = unknown> = CmdOf<ReturnType<typeof snapshotLoadDef<V>>>;
|
|
102
|
+
/**
|
|
103
|
+
* The Msg the engine mints when a write lands. Fold it through
|
|
104
|
+
* `confirm(state, msg)` to advance `lastSavedSeq` / `lastSavedAt`. It carries
|
|
105
|
+
* the write Cmd, so `msg.cmd.seq` matches the emitting decision and a late
|
|
106
|
+
* acknowledgement of an older write can never regress a newer confirmed one.
|
|
107
|
+
*/
|
|
108
|
+
type SnapshotSavedMsg<V = unknown> = SettledOk<"snapshot_write", SnapshotWriteCmd<V>, undefined>;
|
|
109
|
+
/**
|
|
110
|
+
* The Msg the engine mints when a write fails. Errors are data (never
|
|
111
|
+
* swallowed): the consumer's reducer decides whether a failed checkpoint is
|
|
112
|
+
* fatal, retryable (compose `@demlik/tea/retry-backoff`), or merely logged.
|
|
113
|
+
* `msg.cmd.seq` identifies which checkpoint failed.
|
|
114
|
+
*/
|
|
115
|
+
type SnapshotFailedMsg<V = unknown> = SettledErr<"snapshot_write", SnapshotWriteCmd<V>, TaggedError<"snapshot_write_failed">>;
|
|
116
|
+
/**
|
|
117
|
+
* The Msg the engine mints when a read resolves. `value` is the recovered
|
|
118
|
+
* checkpoint, or `null` when the store has no checkpoint under `key` (fresh
|
|
119
|
+
* boot — never checkpointed, or a wiped store). `null` is NOT an error — "no
|
|
120
|
+
* checkpoint yet" is a normal first-run state, distinct from "the read failed"
|
|
121
|
+
* (`snapshot_load_err`).
|
|
122
|
+
*/
|
|
123
|
+
type SnapshotLoadedMsg<V> = SettledOk<"snapshot_load", SnapshotLoadCmd<V>, V | null>;
|
|
124
|
+
/**
|
|
125
|
+
* The Msg the engine mints when a read fails. Errors are data: a failed
|
|
126
|
+
* recovery read is a visible signal the consumer's reducer decides on
|
|
127
|
+
* (fatal-abort, retry, or boot-fresh-and-log). Kept apart from a `null` load
|
|
128
|
+
* so "the store has no checkpoint" can never masquerade as "the read failed".
|
|
129
|
+
*/
|
|
130
|
+
type SnapshotLoadFailedMsg<V = unknown> = SettledErr<"snapshot_load", SnapshotLoadCmd<V>, TaggedError<"snapshot_load_failed">>;
|
|
131
|
+
/**
|
|
132
|
+
* The bundle `createSnapshot` returns: plain functions plus the two Cmd defs to
|
|
133
|
+
* list in `cmds`. There are no subs: a checkpoint is driven by progress (a
|
|
134
|
+
* `record` call from the consumer's reducer), not by a timer.
|
|
135
|
+
*/
|
|
136
|
+
interface SnapshotKnob<V> {
|
|
137
|
+
/** The `snapshot_write` Cmd def — list it in the machine's `cmds`. */
|
|
138
|
+
readonly write: ReturnType<typeof snapshotWriteDef<V>>;
|
|
139
|
+
/** The `snapshot_load` Cmd def — list it in the machine's `cmds`. */
|
|
140
|
+
readonly load: ReturnType<typeof snapshotLoadDef<V>>;
|
|
141
|
+
/** The initial slice — zero progress, no checkpoint emitted or confirmed yet. */
|
|
142
|
+
init(): SnapshotState;
|
|
143
|
+
/**
|
|
144
|
+
* Account one unit of progress. PURE. Increments `sinceLast`; once the
|
|
145
|
+
* accumulated count reaches the configured cadence, DECIDES to checkpoint:
|
|
146
|
+
* resets `sinceLast` to 0, bumps `seq`, and emits a single `snapshot_write`
|
|
147
|
+
* Cmd carrying `payload` + `key` + the new `seq` + `at`. Below the cadence it
|
|
148
|
+
* returns the bumped slice and NO Cmd.
|
|
149
|
+
*
|
|
150
|
+
* `payload` is the checkpoint value to persist (the consumer's domain state);
|
|
151
|
+
* `at` is the caller-stamped time the progress occurred (epoch ms) — injected,
|
|
152
|
+
* never read from the clock here.
|
|
153
|
+
*/
|
|
154
|
+
record(state: SnapshotState, payload: V, at: number): readonly [SnapshotState, readonly SnapshotWriteCmd<V>[]];
|
|
155
|
+
/**
|
|
156
|
+
* Force a checkpoint regardless of the cadence counter. PURE. Always bumps
|
|
157
|
+
* `seq`, resets `sinceLast`, and emits the write Cmd. Use on a phase boundary
|
|
158
|
+
* the cadence would otherwise miss — e.g. "the run just finished, checkpoint
|
|
159
|
+
* the terminal state now" — so the last durable checkpoint is the final state,
|
|
160
|
+
* not whatever the modulo happened to land on.
|
|
161
|
+
*/
|
|
162
|
+
force(state: SnapshotState, payload: V, at: number): readonly [SnapshotState, readonly SnapshotWriteCmd<V>[]];
|
|
163
|
+
/**
|
|
164
|
+
* Record a confirmed durable write. PURE. Advances `lastSavedSeq` /
|
|
165
|
+
* `lastSavedAt` to the acknowledged write's `seq` / `at`, but only forward:
|
|
166
|
+
* an out-of-order acknowledgement of an OLDER `seq` (a slow write landing
|
|
167
|
+
* after a newer one) is ignored, so the confirmed watermark is monotonic.
|
|
168
|
+
* Fold the `snapshot_write_ok` Msg here.
|
|
169
|
+
*
|
|
170
|
+
* Returns the reducer-cell shape `readonly [SnapshotState, readonly Cmd[]]`
|
|
171
|
+
* (with `Cmd.none` — an ack emits nothing) for uniformity with every sibling
|
|
172
|
+
* knob, so it drops straight into a `snapshot_write_ok` cell.
|
|
173
|
+
*/
|
|
174
|
+
confirm(state: SnapshotState, msg: SnapshotSavedMsg<V>): readonly [SnapshotState, readonly Cmd[]];
|
|
175
|
+
/**
|
|
176
|
+
* Resume after a reload. PURE. Resets `sinceLast` to 0 because any
|
|
177
|
+
* un-checkpointed progress accumulated before the crash is moot — recovery
|
|
178
|
+
* resumes from the last DURABLE checkpoint, so the cadence counter starts
|
|
179
|
+
* fresh from there. `seq` / `lastSavedSeq` / `lastSavedAt` are preserved
|
|
180
|
+
* (they describe what is durable, which a reload does not change). Call from
|
|
181
|
+
* a `boot` Msg the host dispatches once after `run(...)`, never from `init`'s
|
|
182
|
+
* rehydrate branch (invariant 2).
|
|
183
|
+
*
|
|
184
|
+
* Returns the reducer-cell shape `readonly [SnapshotState, readonly Cmd[]]`
|
|
185
|
+
* (with `Cmd.none` — a resume emits nothing) so it drops straight into a
|
|
186
|
+
* `snapshot_load_ok` cell.
|
|
187
|
+
*/
|
|
188
|
+
boot(state: SnapshotState): readonly [SnapshotState, readonly Cmd[]];
|
|
189
|
+
/**
|
|
190
|
+
* Ask the store for the durable checkpoint. PURE. Emits a single
|
|
191
|
+
* `snapshot_load` Cmd carrying the configured `key`; returns the slice
|
|
192
|
+
* UNCHANGED (a read decides nothing about the cadence bookkeeping — only the
|
|
193
|
+
* later `snapshot_load_ok` fold, via `boot`, touches the slice). This is the
|
|
194
|
+
* entry point of the recovery loop: the consumer dispatches a `boot` Msg once
|
|
195
|
+
* after `run(...)` and folds `requestLoad` there.
|
|
196
|
+
*/
|
|
197
|
+
requestLoad(state: SnapshotState): readonly [SnapshotState, readonly SnapshotLoadCmd<V>[]];
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Create a snapshot knob from a `SnapshotConfig`. The returned bundle is spliced
|
|
201
|
+
* into a consumer machine: `init()` seeds the slice, `record` / `force` are
|
|
202
|
+
* folded in reducer cells, `confirm` / `boot` handle the acknowledgement +
|
|
203
|
+
* resume Msgs, and `write` / `load` are the Cmd defs whose handlers you write.
|
|
204
|
+
*/
|
|
205
|
+
declare function createSnapshot<V>(config: SnapshotConfig): SnapshotKnob<V>;
|
|
206
|
+
|
|
207
|
+
export { type SnapshotWriteCmd as S, type SnapshotState as a, type SnapshotSavedMsg as b, type SnapshotConfig as c, type SnapshotFailedMsg as d, type SnapshotKnob as e, type SnapshotLoadCmd as f, type SnapshotLoadFailedMsg as g, type SnapshotLoadedMsg as h, createSnapshot as i, snapshotWriteDef as j, snapshotLoadDef as s };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as Cmd, P as Port } from './core-
|
|
2
|
-
import { Q as QueueItem } from './index-
|
|
1
|
+
import { C as Cmd, P as Port } from './core-BbgtiXdg.js';
|
|
2
|
+
import { Q as QueueItem } from './index-7vV8xmsD.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* internal/flow/fan-out — scatter-gather over a bounded-concurrency work list.
|
|
@@ -54,15 +54,13 @@ import { Q as QueueItem } from './index-CSyMYDAB.js';
|
|
|
54
54
|
* is supplied by the caller's `idOf` so `scatter` is deterministic, and the
|
|
55
55
|
* launch effects are plain data the runtime performs (invariant 3).
|
|
56
56
|
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* batch completes, for consumers that observe completion out-of-band rather
|
|
65
|
-
* than through the `join` Cmd.
|
|
57
|
+
* Fan-out does NOT own the interpret handler for a launched `of(item)` Cmd: `of`
|
|
58
|
+
* already produces a fully caller-defined Cmd, so the consumer's own
|
|
59
|
+
* `interpret` performs the effect and routes Ok/Err back to the `itemOk` /
|
|
60
|
+
* `itemErr` verbs. `completion(ports)` is the one piece fan-out CAN pre-wire
|
|
61
|
+
* generically: emitting the gathered batch onto a typed Port when the batch
|
|
62
|
+
* completes, for consumers that observe completion out-of-band rather than
|
|
63
|
+
* through the `join` Cmd.
|
|
66
64
|
*
|
|
67
65
|
* NOT a substrate primitive: it depends only on `../work-queue`'s pure types +
|
|
68
66
|
* blessed ops and the core `Cmd` / `Port` types. Internal since #48 — not
|
|
@@ -162,7 +160,7 @@ interface FanOutState<I, R> {
|
|
|
162
160
|
*
|
|
163
161
|
* Field optionality follows the resilient-call rule — omit `join`, omit the
|
|
164
162
|
* completion Cmd (a consumer that observes `isComplete` itself, or wires the
|
|
165
|
-
* `
|
|
163
|
+
* `completion` Port, doesn't need one).
|
|
166
164
|
*/
|
|
167
165
|
interface FanOutConfig<I, R, C extends Cmd, J extends Cmd> {
|
|
168
166
|
/** Max in-flight `of(item)` effects. Clamped to `>= 1` (a 0/negative cap would deadlock). */
|
|
@@ -180,7 +178,7 @@ interface FanOutConfig<I, R, C extends Cmd, J extends Cmd> {
|
|
|
180
178
|
/**
|
|
181
179
|
* Optional: fold the gathered done-results into a single completion Cmd,
|
|
182
180
|
* fired exactly once at the transition that empties `pending` + `running`.
|
|
183
|
-
* Omit to drive completion off `isComplete` (or the `
|
|
181
|
+
* Omit to drive completion off `isComplete` (or the `completion` Port) instead.
|
|
184
182
|
*/
|
|
185
183
|
readonly join?: (results: readonly R[]) => J;
|
|
186
184
|
}
|
|
@@ -199,7 +197,7 @@ declare function initFanOut<I, R>(): FanOutState<I, R>;
|
|
|
199
197
|
declare function isComplete<I, R>(state: FanOutState<I, R>): boolean;
|
|
200
198
|
/**
|
|
201
199
|
* Optional Port for observing batch completion out-of-band. When a consumer
|
|
202
|
-
* passes `
|
|
200
|
+
* passes `completion(ports)` a `complete` Port, the runtime side can emit the
|
|
203
201
|
* gathered results onto it the moment `isComplete` flips true — distinct from
|
|
204
202
|
* the in-band `join` Cmd (which threads back through `update`). Use the Port
|
|
205
203
|
* for "tell the outside world the batch finished" without folding a completion
|
|
@@ -212,7 +210,7 @@ interface FanOutPorts<R> {
|
|
|
212
210
|
/**
|
|
213
211
|
* Build the fan-out knob from `config`. Returns the uniform combinator
|
|
214
212
|
* contract: `init` for the owned slice, the three settle verbs + the derived
|
|
215
|
-
* `isComplete`, and `
|
|
213
|
+
* `isComplete`, and `completion` for the optional out-of-band completion Port.
|
|
216
214
|
*
|
|
217
215
|
* No `subs` — fan-out runs no timers (the spec pins "Subs: none"). The
|
|
218
216
|
* per-item effect's lifetime is owned by the consumer's `interpret`, and
|
|
@@ -225,7 +223,7 @@ declare function createFanOut<I, R, C extends Cmd = Cmd, J extends Cmd = Cmd>(co
|
|
|
225
223
|
itemOk: (state: FanOutState<I, R>, id: string, result: R) => readonly [FanOutState<I, R>, readonly (C | J)[]];
|
|
226
224
|
itemErr: (state: FanOutState<I, R>, id: string, error: unknown) => readonly [FanOutState<I, R>, readonly (C | J)[]];
|
|
227
225
|
isComplete: typeof isComplete;
|
|
228
|
-
|
|
226
|
+
completion: (ports: FanOutPorts<R>) => {
|
|
229
227
|
/**
|
|
230
228
|
* Emit the gathered done-results onto `ports.complete` iff `state` is a
|
|
231
229
|
* just-completed batch. Idempotency is the caller's concern (call it once
|