@demlik/tea 0.15.0 → 0.17.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-4NTCPTNQ.js +64 -0
- package/dist/chunk-4NTCPTNQ.js.map +1 -0
- package/dist/{chunk-3B5X7SBB.js → chunk-4PXNZ5UY.js} +11 -9
- package/dist/chunk-4PXNZ5UY.js.map +1 -0
- package/dist/{chunk-AYS5N6WY.js → chunk-6XBEYZME.js} +62 -172
- package/dist/chunk-6XBEYZME.js.map +1 -0
- package/dist/chunk-C4U5D5HP.js +380 -0
- package/dist/chunk-C4U5D5HP.js.map +1 -0
- package/dist/{chunk-QPEVCJ5Q.js → chunk-DFUEAA6L.js} +13 -6
- package/dist/chunk-DFUEAA6L.js.map +1 -0
- package/dist/{chunk-22POWGFA.js → chunk-GWWCCSDH.js} +46 -20
- package/dist/chunk-GWWCCSDH.js.map +1 -0
- package/dist/chunk-K4ETBNKS.js +733 -0
- package/dist/chunk-K4ETBNKS.js.map +1 -0
- package/dist/chunk-KWNCM6XM.js +539 -0
- package/dist/chunk-KWNCM6XM.js.map +1 -0
- package/dist/{chunk-V46HSVCK.js → chunk-LYVOGOBC.js} +3 -3
- package/dist/{chunk-V46HSVCK.js.map → chunk-LYVOGOBC.js.map} +1 -1
- package/dist/{chunk-VTQI2NHP.js → chunk-OPH6Y4UT.js} +9 -8
- package/dist/chunk-OPH6Y4UT.js.map +1 -0
- package/dist/{chunk-Q5CQTBFA.js → chunk-OYR7ENKU.js} +20 -30
- package/dist/chunk-OYR7ENKU.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-QWIPH4YH.js +98 -0
- package/dist/chunk-QWIPH4YH.js.map +1 -0
- package/dist/{chunk-TCLBCERH.js → chunk-XBZQT2TD.js} +238 -212
- package/dist/chunk-XBZQT2TD.js.map +1 -0
- package/dist/{core-DnzqWy6u.d.ts → core-rDbOaJTN.d.ts} +236 -140
- 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-CNaw97Be.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-KXqTRJyb.d.ts → index-BOrsbdAf.d.ts} +19 -96
- package/dist/{index-DrIRb_Ch.d.ts → index-B_BxplWi.d.ts} +1 -1
- package/dist/index-CWmsXNdX.d.ts +207 -0
- package/dist/{index-C2DwkjlP.d.ts → index-Cberb5Rr.d.ts} +57 -45
- package/dist/{index-CSyMYDAB.d.ts → index-CcrKLtse.d.ts} +1 -1
- package/dist/{index-CuNO9m8i.d.ts → index-Cx0F2M34.d.ts} +14 -16
- package/dist/{index-HSYgG2Yt.d.ts → index-DaX_P35Q.d.ts} +247 -211
- package/dist/{index-CA_7I5g9.d.ts → index-q1PoukOZ.d.ts} +137 -246
- 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-BcfCFMYF.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 +10 -12
- 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-B62Ucnxr.d.ts} +132 -389
- package/dist/testing/index.d.ts +33 -113
- package/dist/testing/index.js +39 -181
- 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-DPm5YCDQ.d.ts} +2 -2
- package/dist/work-queue/index.d.ts +5 -6
- package/package.json +20 -7
- 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-rDbOaJTN.js';
|
|
4
|
+
import { Q as QueueItem } from '../index-CcrKLtse.js';
|
|
5
|
+
import '@standard-schema/spec';
|
|
6
|
+
import '../runtime-types-B62Ucnxr.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-OPH6Y4UT.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-C4U5D5HP.js';
|
|
6
|
+
import '../chunk-K4ETBNKS.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-rDbOaJTN.js';
|
|
2
|
+
import { S as SnapshotWriteCmd, a as SnapshotState, b as SnapshotSavedMsg } from './index-CWmsXNdX.js';
|
|
3
|
+
import { D as DeadlineExceeded, a as DeadlineSub } from './index-DaX_P35Q.js';
|
|
4
|
+
import { Q as QueueItem } from './index-CcrKLtse.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-rDbOaJTN.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,6 +1,5 @@
|
|
|
1
|
-
import { C as Cmd } from './core-
|
|
2
|
-
import {
|
|
3
|
-
import { D as DeadlineExceeded, a as DeadlineSub } from './index-HSYgG2Yt.js';
|
|
1
|
+
import { C as Cmd, T as TimerDeps, d as Subscribe } from './core-rDbOaJTN.js';
|
|
2
|
+
import { D as DeadlineExceeded, a as DeadlineSub, b as DeadlinesSub } from './index-DaX_P35Q.js';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* internal/flow/batch-window — coalesce a stream of items into size- or
|
|
@@ -8,14 +7,13 @@ import { D as DeadlineExceeded, a as DeadlineSub } from './index-HSYgG2Yt.js';
|
|
|
8
7
|
*
|
|
9
8
|
* What this module actually DELEGATES to, vs. what it merely RE-EXPORTS:
|
|
10
9
|
*
|
|
11
|
-
* - `../deadline` — REAL delegation (the only one). The window timer
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* fires at the correct moment.
|
|
10
|
+
* - `../deadline` — REAL delegation (the only one). The window timer's Msg
|
|
11
|
+
* is `deadlineExceeded`, keyed on the window's identity. `timerFor` arms it
|
|
12
|
+
* through the engine's built-in `timer` Sub: `maxMs` counted from the
|
|
13
|
+
* transition that opened the window, so a machine needs no runner. The
|
|
14
|
+
* absolute-instant form is still here too — `subsFor` lists the same
|
|
15
|
+
* deadline for `deadlinesSub` + `subscribeDeadline`, which re-arms for the
|
|
16
|
+
* REMAINING time after a `Store` rehydrate rather than a fresh `maxMs`.
|
|
19
17
|
* - `../work-queue` — TYPE re-export only, NOT a sink this module calls. A
|
|
20
18
|
* flush emits a Cmd; the CONSUMER's interpret handler is what enqueues onto a
|
|
21
19
|
* `createQueue(store)`. This module never touches queue status — it has no
|
|
@@ -48,10 +46,10 @@ import { D as DeadlineExceeded, a as DeadlineSub } from './index-HSYgG2Yt.js';
|
|
|
48
46
|
* // Model: { batch: BatchWindow<LogLine>, ... }
|
|
49
47
|
* // init: (loaded) => [loaded ?? { batch: bw.init(), ... }, []]
|
|
50
48
|
* // update cells:
|
|
51
|
-
* // LogArrived:
|
|
52
|
-
* //
|
|
53
|
-
* //
|
|
54
|
-
* //
|
|
49
|
+
* // LogArrived: (s, m) => mapBatch(s, bw.add(s.batch, m.line, m.at))
|
|
50
|
+
* // deadline_exceeded: (s, m) => mapBatch(s, bw.onWindow(s.batch, m.atMs))
|
|
51
|
+
* // subs: [{ type: "timer", deps: (s: Model) => bw.timer(s.batch) }]
|
|
52
|
+
* // at run: run(machine, { interpret }) // `timer` is built in
|
|
55
53
|
*
|
|
56
54
|
* where `mapBatch(s, [batch, cmds]) => [{ ...s, batch }, cmds]` lifts the slice
|
|
57
55
|
* transition into the consumer's Model. The `FlushBatch` Cmd's interpret handler
|
|
@@ -118,26 +116,26 @@ interface BatchWindow<I> {
|
|
|
118
116
|
/** The starting slice: closed window, empty buffer. */
|
|
119
117
|
declare function initBatchWindow<I>(): BatchWindow<I>;
|
|
120
118
|
/**
|
|
121
|
-
* The
|
|
119
|
+
* The deadline a batch window's open timer lists: it IS `../deadline`'s
|
|
122
120
|
* `DeadlineSub`, not a re-tagged copy. `atMs` is the absolute flush-by instant
|
|
123
121
|
* (`openedAt + maxMs`). Aliasing the deadline type (rather than redeclaring an
|
|
124
122
|
* identical shape) is what lets `subsFor` return `deadlineSub(...)` with no
|
|
125
123
|
* cast — the value's static type already satisfies this name. Consumers running
|
|
126
|
-
* several windows route each one by the
|
|
124
|
+
* several windows route each one by the deadline's `id`, not by a distinct type.
|
|
127
125
|
*/
|
|
128
126
|
type BatchWindowSub = DeadlineSub;
|
|
129
127
|
/** The Msg a closed-by-time window dispatches. Alias of `deadline`'s Msg. */
|
|
130
128
|
type BatchWindowExpired = DeadlineExceeded;
|
|
131
129
|
/**
|
|
132
130
|
* Construct the window-expired Msg for the window identified by `id`, flushing
|
|
133
|
-
* by `atMs`. Re-exported alias of `deadlineExceeded` so the
|
|
131
|
+
* by `atMs`. Re-exported alias of `deadlineExceeded` so the runner and
|
|
134
132
|
* the consumer's reducer share one constructor rather than two literals that
|
|
135
133
|
* can drift. The consumer handles it in a reducer cell by calling `onWindow`.
|
|
136
134
|
*/
|
|
137
135
|
declare function batchWindowExpired(id: string, atMs: number): BatchWindowExpired;
|
|
138
136
|
/**
|
|
139
137
|
* The bound knob returned by `createBatchWindow`. `init` + the two pure verbs +
|
|
140
|
-
* `
|
|
138
|
+
* `timer` + `subs`, all closing over one `BatchWindowConfig`. The verbs
|
|
141
139
|
* return `readonly [BatchWindow<I>, readonly C[]]`: the next slice and the Cmds
|
|
142
140
|
* to emit (one `flush` Cmd when a window closes, none otherwise).
|
|
143
141
|
*/
|
|
@@ -154,18 +152,16 @@ interface BatchWindowKnob<I, C extends Cmd> {
|
|
|
154
152
|
*/
|
|
155
153
|
onWindow(state: BatchWindow<I>, at: number): readonly [BatchWindow<I>, readonly C[]];
|
|
156
154
|
/**
|
|
157
|
-
* The
|
|
158
|
-
* `id` keys the
|
|
155
|
+
* The built-in `timer` Sub's deps while a window is open, `null` while it is
|
|
156
|
+
* closed. See `timerFor`. `id` keys the Msg so several windows on one
|
|
157
|
+
* machine route distinctly.
|
|
159
158
|
*/
|
|
160
|
-
|
|
159
|
+
timer(state: BatchWindow<I>, id?: string): TimerDeps<BatchWindowExpired> | null;
|
|
161
160
|
/**
|
|
162
|
-
* The
|
|
163
|
-
*
|
|
164
|
-
* into the consumer's subscribe map: `subscribe: { ...bw.handlers() }`.
|
|
161
|
+
* The window timer as an absolute deadline, listed only while a window is
|
|
162
|
+
* open — for `deadlinesSub` + `subscribeBatchWindow`. See `subsFor`.
|
|
165
163
|
*/
|
|
166
|
-
|
|
167
|
-
deadline: SubscribeHandler<BatchWindowSub, BatchWindowExpired, unknown>;
|
|
168
|
-
};
|
|
164
|
+
subs(state: BatchWindow<I>, id?: string): readonly BatchWindowSub[];
|
|
169
165
|
}
|
|
170
166
|
/**
|
|
171
167
|
* Buffer `item` and decide whether the size trigger fires. PURE.
|
|
@@ -215,18 +211,18 @@ declare function addItem<I, C extends Cmd>(config: BatchWindowConfig<I, C>, stat
|
|
|
215
211
|
*/
|
|
216
212
|
declare function onWindow<I, C extends Cmd>(config: BatchWindowConfig<I, C>, state: BatchWindow<I>, _at: number): readonly [BatchWindow<I>, readonly C[]];
|
|
217
213
|
/**
|
|
218
|
-
* The window timer
|
|
214
|
+
* The window timer deadline, derived from the slice. PURE.
|
|
219
215
|
*
|
|
220
|
-
* Returns the single
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
* (clearing the pending `setTimeout`) when the
|
|
224
|
-
* that empties the buffer auto-cancels the now-irrelevant time
|
|
225
|
-
* next transition.
|
|
216
|
+
* Returns the single deadline targeting `openedAt + maxMs` while a window is
|
|
217
|
+
* open (buffer non-empty), or `[]` while it is closed. Fed through
|
|
218
|
+
* `deadlinesSub`, the engine arms the timer when the list gains the deadline
|
|
219
|
+
* and disarms it (clearing the pending `setTimeout`) when the list loses it —
|
|
220
|
+
* so a size-flush that empties the buffer auto-cancels the now-irrelevant time
|
|
221
|
+
* trigger on the next transition.
|
|
226
222
|
*
|
|
227
223
|
* `id` defaults to `"batch-window"`; pass a distinct id per window when a
|
|
228
|
-
* machine runs several so the dispatched `BatchWindowExpired` Msg
|
|
229
|
-
*
|
|
224
|
+
* machine runs several so the dispatched `BatchWindowExpired` Msg routes to the
|
|
225
|
+
* right one.
|
|
230
226
|
*
|
|
231
227
|
* @param config the knob (maxMs)
|
|
232
228
|
* @param state the current slice
|
|
@@ -235,22 +231,38 @@ declare function onWindow<I, C extends Cmd>(config: BatchWindowConfig<I, C>, sta
|
|
|
235
231
|
*/
|
|
236
232
|
declare function subsFor<I, C extends Cmd>(config: BatchWindowConfig<I, C>, state: BatchWindow<I>, id?: string): readonly BatchWindowSub[];
|
|
237
233
|
/**
|
|
238
|
-
* The `
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
234
|
+
* The built-in `timer` Sub's deps for a batch window. PURE.
|
|
235
|
+
*
|
|
236
|
+
* While a window is open it counts `maxMs` down from the transition that
|
|
237
|
+
* opened it — the deps are fixed for the window's life (`openedAt` never moves
|
|
238
|
+
* while items append), so the engine starts the countdown exactly once — and
|
|
239
|
+
* fires `batchWindowExpired(id, openedAt + maxMs)`. A closed window is `null`,
|
|
240
|
+
* so a size-flush that empties the buffer cancels the countdown on the next
|
|
241
|
+
* transition.
|
|
242
|
+
*
|
|
243
|
+
* Relative by construction: a process that rehydrates an open window counts a
|
|
244
|
+
* fresh `maxMs`. Reach for `subsFor` + `subscribeBatchWindow` when the flush
|
|
245
|
+
* must land at the original absolute instant.
|
|
246
|
+
*/
|
|
247
|
+
declare function timerFor<I, C extends Cmd>(config: BatchWindowConfig<I, C>, state: BatchWindow<I>, id?: string): TimerDeps<BatchWindowExpired> | null;
|
|
248
|
+
/**
|
|
249
|
+
* The `deadline` runner for a batch window's absolute timer — the exact
|
|
250
|
+
* `../deadline` runner. Arms a one-shot timer per listed deadline for
|
|
251
|
+
* `max(0, atMs - now)` and dispatches `batchWindowExpired(...)`; returns a
|
|
252
|
+
* cleanup that clears them. Hand it to `run` as `subscribe.deadline` when the
|
|
253
|
+
* machine declares `deadlinesSub((s) => bw.subs(s.batch))`.
|
|
242
254
|
*/
|
|
243
|
-
declare const subscribeBatchWindow:
|
|
255
|
+
declare const subscribeBatchWindow: Subscribe<BatchWindowExpired, DeadlinesSub, unknown>["deadline"];
|
|
244
256
|
/**
|
|
245
257
|
* Build a batch window knob from a config. Combinator form (the default L2
|
|
246
258
|
* ergonomic): hand it the config, splice the ~4 returned hooks into your
|
|
247
259
|
* machine. The pure verbs (`add` / `onWindow`) close over the config so the
|
|
248
|
-
* consumer's reducer cells stay a uniform `(state, ...args)` shape; `
|
|
249
|
-
*
|
|
260
|
+
* consumer's reducer cells stay a uniform `(state, ...args)` shape; `timer`
|
|
261
|
+
* arms the window timer.
|
|
250
262
|
*
|
|
251
263
|
* @typeParam I the item type buffered into each batch
|
|
252
264
|
* @typeParam C the Cmd type `config.flush` returns
|
|
253
265
|
*/
|
|
254
266
|
declare function createBatchWindow<I, C extends Cmd>(config: BatchWindowConfig<I, C>): BatchWindowKnob<I, C>;
|
|
255
267
|
|
|
256
|
-
export { type BatchWindow as B, type BatchWindowSub as a, type BatchWindowExpired as b, type BatchWindowConfig as c, type BatchWindowKnob as d, addItem as e, batchWindowExpired as f, createBatchWindow as g, subscribeBatchWindow as h, initBatchWindow as i, onWindow as o, subsFor as s };
|
|
268
|
+
export { type BatchWindow as B, type BatchWindowSub as a, type BatchWindowExpired as b, type BatchWindowConfig as c, type BatchWindowKnob as d, addItem as e, batchWindowExpired as f, createBatchWindow as g, subscribeBatchWindow as h, initBatchWindow as i, onWindow as o, subsFor as s, timerFor as t };
|