@demlik/tea 0.1.0 → 0.1.2
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/LICENSE +21 -0
- package/dist/agent/index.d.ts +907 -0
- package/dist/agent/index.js +20 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/authed-call/index.d.ts +119 -0
- package/dist/authed-call/index.js +148 -0
- package/dist/authed-call/index.js.map +1 -0
- package/dist/await-terminal/index.d.ts +99 -0
- package/dist/await-terminal/index.js +75 -0
- package/dist/await-terminal/index.js.map +1 -0
- package/dist/batch-window/index.d.ts +259 -0
- package/dist/batch-window/index.js +43 -0
- package/dist/batch-window/index.js.map +1 -0
- package/dist/cache/index.d.ts +2 -2
- package/dist/cache/index.js +2 -50
- package/dist/cache/index.js.map +1 -1
- package/dist/chunk-27N2SPTN.js +222 -0
- package/dist/chunk-27N2SPTN.js.map +1 -0
- package/dist/chunk-2YOE5PIS.js +45 -0
- package/dist/chunk-2YOE5PIS.js.map +1 -0
- package/dist/chunk-3545BOYL.js +65 -0
- package/dist/chunk-3545BOYL.js.map +1 -0
- package/dist/chunk-3XJWC7VW.js +61 -0
- package/dist/chunk-3XJWC7VW.js.map +1 -0
- package/dist/chunk-5DEQ5I3U.js +132 -0
- package/dist/chunk-5DEQ5I3U.js.map +1 -0
- package/dist/chunk-5VNWZADP.js +49 -0
- package/dist/chunk-5VNWZADP.js.map +1 -0
- package/dist/chunk-6RGBKODV.js +268 -0
- package/dist/chunk-6RGBKODV.js.map +1 -0
- package/dist/{chunk-ZRUST6BK.js → chunk-7FYQGDMF.js} +2 -2
- package/dist/chunk-7FYQGDMF.js.map +1 -0
- package/dist/chunk-7W4LMPUW.js +186 -0
- package/dist/chunk-7W4LMPUW.js.map +1 -0
- package/dist/chunk-BYQUGDD3.js +16 -0
- package/dist/chunk-BYQUGDD3.js.map +1 -0
- package/dist/{chunk-PYBQREFU.js → chunk-DILMKOZ7.js} +22 -26
- package/dist/chunk-DILMKOZ7.js.map +1 -0
- package/dist/chunk-EHIX7NYZ.js +93 -0
- package/dist/chunk-EHIX7NYZ.js.map +1 -0
- package/dist/chunk-HCEVHFJ7.js +54 -0
- package/dist/chunk-HCEVHFJ7.js.map +1 -0
- package/dist/chunk-HJO6VNQI.js +15 -0
- package/dist/chunk-HJO6VNQI.js.map +1 -0
- package/dist/chunk-IN33Q4VJ.js +52 -0
- package/dist/chunk-IN33Q4VJ.js.map +1 -0
- package/dist/chunk-J6527VRQ.js +56 -0
- package/dist/chunk-J6527VRQ.js.map +1 -0
- package/dist/chunk-JELSZN25.js +47 -0
- package/dist/chunk-JELSZN25.js.map +1 -0
- package/dist/chunk-K575PT4S.js +58 -0
- package/dist/chunk-K575PT4S.js.map +1 -0
- package/dist/chunk-K7Q23EQ4.js +20 -0
- package/dist/chunk-K7Q23EQ4.js.map +1 -0
- package/dist/chunk-LEC4U6CX.js +91 -0
- package/dist/chunk-LEC4U6CX.js.map +1 -0
- package/dist/{chunk-PYOCUBQJ.js → chunk-LP7VQBRG.js} +22 -15
- package/dist/chunk-LP7VQBRG.js.map +1 -0
- package/dist/{chunk-CMG2KMWX.js → chunk-MMH7CW5K.js} +220 -189
- package/dist/chunk-MMH7CW5K.js.map +1 -0
- package/dist/{chunk-Y5JM3UUH.js → chunk-NSDFA6M6.js} +75 -3
- package/dist/chunk-NSDFA6M6.js.map +1 -0
- package/dist/chunk-ON24RKSE.js +60 -0
- package/dist/chunk-ON24RKSE.js.map +1 -0
- package/dist/chunk-PS23H6KQ.js +87 -0
- package/dist/chunk-PS23H6KQ.js.map +1 -0
- package/dist/chunk-QLA76GIT.js +162 -0
- package/dist/chunk-QLA76GIT.js.map +1 -0
- package/dist/chunk-S3FQN4SL.js +506 -0
- package/dist/chunk-S3FQN4SL.js.map +1 -0
- package/dist/chunk-SC3FAFZN.js +53 -0
- package/dist/chunk-SC3FAFZN.js.map +1 -0
- package/dist/chunk-SINXE47Y.js +55 -0
- package/dist/chunk-SINXE47Y.js.map +1 -0
- package/dist/chunk-SQTCS44W.js +33 -0
- package/dist/chunk-SQTCS44W.js.map +1 -0
- package/dist/chunk-TGG26XMK.js +52 -0
- package/dist/chunk-TGG26XMK.js.map +1 -0
- package/dist/chunk-UV6UWGEO.js +147 -0
- package/dist/chunk-UV6UWGEO.js.map +1 -0
- package/dist/chunk-UYWUVEP6.js +158 -0
- package/dist/chunk-UYWUVEP6.js.map +1 -0
- package/dist/chunk-VLGARN6H.js +202 -0
- package/dist/chunk-VLGARN6H.js.map +1 -0
- package/dist/circuit-breaker/index.js +1 -51
- package/dist/circuit-breaker/index.js.map +1 -1
- package/dist/core-BoB6t7dB.d.ts +188 -0
- package/dist/deadline/index.d.ts +24 -5
- package/dist/deadline/index.js +4 -18
- package/dist/deadline/index.js.map +1 -1
- package/dist/debounce/index.d.ts +6 -0
- package/dist/debounce/index.js +1 -54
- package/dist/debounce/index.js.map +1 -1
- package/dist/devtools/index.d.ts +1 -1
- package/dist/devtools/index.js +18 -6
- package/dist/devtools/index.js.map +1 -1
- package/dist/do/index.d.ts +1723 -92
- package/dist/do/index.js +673 -31
- package/dist/do/index.js.map +1 -1
- package/dist/durable-effects-CO9Uh971.d.ts +180 -0
- package/dist/extension/index.d.ts +31 -13
- package/dist/extension/index.js +5 -3
- package/dist/extension/index.js.map +1 -1
- package/dist/extension/react.js +8 -3
- package/dist/extension/react.js.map +1 -1
- package/dist/extension/subs/index.d.ts +2 -2
- package/dist/extension/subs/index.js.map +1 -1
- package/dist/extension/test-utils.js +11 -3
- package/dist/extension/test-utils.js.map +1 -1
- package/dist/fan-out/index.d.ts +239 -0
- package/dist/fan-out/index.js +5 -0
- package/dist/fan-out/index.js.map +1 -0
- package/dist/idempotency/adapter.d.ts +62 -0
- package/dist/idempotency/adapter.js +4 -0
- package/dist/idempotency/adapter.js.map +1 -0
- package/dist/idempotency/index.js +1 -56
- package/dist/idempotency/index.js.map +1 -1
- package/dist/idempotent-intake/index.d.ts +186 -0
- package/dist/idempotent-intake/index.js +7 -0
- package/dist/idempotent-intake/index.js.map +1 -0
- package/dist/index.d.ts +341 -191
- package/dist/index.js +2 -1
- package/dist/llm-call/index.d.ts +309 -0
- package/dist/llm-call/index.js +14 -0
- package/dist/llm-call/index.js.map +1 -0
- package/dist/machine-viz/index.d.ts +4 -4
- package/dist/machine-viz/index.js +5 -9
- package/dist/machine-viz/index.js.map +1 -1
- package/dist/mem/index.d.ts +1 -0
- package/dist/monitored-run/index.d.ts +253 -0
- package/dist/monitored-run/index.js +10 -0
- package/dist/monitored-run/index.js.map +1 -0
- package/dist/node/index.d.ts +5 -5
- package/dist/node/index.js.map +1 -1
- package/dist/paginated-walk/index.d.ts +234 -0
- package/dist/paginated-walk/index.js +15 -0
- package/dist/paginated-walk/index.js.map +1 -0
- package/dist/paginator/index.d.ts +271 -0
- package/dist/paginator/index.js +3 -0
- package/dist/paginator/index.js.map +1 -0
- package/dist/parity/index.d.ts +92 -0
- package/dist/parity/index.js +78 -0
- package/dist/parity/index.js.map +1 -0
- package/dist/pbt/arbitraries/index.d.ts +1 -1
- package/dist/pbt/arbitraries/index.js +1 -1
- package/dist/pbt/index.d.ts +15 -8
- package/dist/pbt/index.js +6 -11
- package/dist/pbt/index.js.map +1 -1
- package/dist/pbt/runners/index.d.ts +1 -1
- package/dist/pbt/runners/index.js +3 -2
- package/dist/poller/index.d.ts +288 -0
- package/dist/poller/index.js +79 -0
- package/dist/poller/index.js.map +1 -0
- package/dist/prediction/index.d.ts +130 -0
- package/dist/prediction/index.js +4 -0
- package/dist/prediction/index.js.map +1 -0
- package/dist/protocol-B5YmJr0d.d.ts +45 -0
- package/dist/pure/index.d.ts +2 -0
- package/dist/pure/index.js +4 -0
- package/dist/pure/index.js.map +1 -0
- package/dist/raft/demo.d.ts +105 -0
- package/dist/raft/demo.js +172 -0
- package/dist/raft/demo.js.map +1 -0
- package/dist/raft/index.d.ts +548 -0
- package/dist/raft/index.js +7 -0
- package/dist/raft/index.js.map +1 -0
- package/dist/raft/sim.d.ts +222 -0
- package/dist/raft/sim.js +8 -0
- package/dist/raft/sim.js.map +1 -0
- package/dist/raft/timeline.d.ts +46 -0
- package/dist/raft/timeline.js +62 -0
- package/dist/raft/timeline.js.map +1 -0
- package/dist/rate-limit/index.js +1 -43
- package/dist/rate-limit/index.js.map +1 -1
- package/dist/react/index.d.ts +2 -1
- package/dist/react/index.js +43 -20
- package/dist/react/index.js.map +1 -1
- package/dist/reconciler/index.d.ts +192 -0
- package/dist/reconciler/index.js +166 -0
- package/dist/reconciler/index.js.map +1 -0
- package/dist/recorder/index.d.ts +7 -3
- package/dist/recorder/index.js +1 -155
- package/dist/recorder/index.js.map +1 -1
- package/dist/resilient-call/index.d.ts +294 -0
- package/dist/resilient-call/index.js +13 -0
- package/dist/resilient-call/index.js.map +1 -0
- package/dist/retry-backoff/index.d.ts +42 -5
- package/dist/retry-backoff/index.js +1 -35
- package/dist/retry-backoff/index.js.map +1 -1
- package/dist/retry-to-success/index.d.ts +109 -0
- package/dist/retry-to-success/index.js +35 -0
- package/dist/retry-to-success/index.js.map +1 -0
- package/dist/saga/index.d.ts +238 -0
- package/dist/saga/index.js +150 -0
- package/dist/saga/index.js.map +1 -0
- package/dist/snapshot/index.d.ts +334 -0
- package/dist/snapshot/index.js +5 -0
- package/dist/snapshot/index.js.map +1 -0
- package/dist/subs/index.d.ts +48 -10
- package/dist/subs/index.js +1 -1
- package/dist/testing/index.d.ts +107 -2
- package/dist/testing/index.js +204 -6
- package/dist/testing/index.js.map +1 -1
- package/dist/throttle/index.d.ts +9 -0
- package/dist/throttle/index.js +1 -52
- package/dist/throttle/index.js.map +1 -1
- package/dist/throttled-input/index.d.ts +380 -0
- package/dist/throttled-input/index.js +88 -0
- package/dist/throttled-input/index.js.map +1 -0
- package/dist/token-refresh/index.d.ts +215 -0
- package/dist/token-refresh/index.js +6 -0
- package/dist/token-refresh/index.js.map +1 -0
- package/dist/trace-replay/index.d.ts +11 -2
- package/dist/trace-replay/index.js +3 -55
- package/dist/trace-replay/index.js.map +1 -1
- package/dist/{types-CwBC5wMn.d.ts → types-B-8bcAp8.d.ts} +1 -1
- package/dist/with-deadline/index.d.ts +196 -0
- package/dist/with-deadline/index.js +111 -0
- package/dist/with-deadline/index.js.map +1 -0
- package/dist/with-resilience/index.d.ts +205 -0
- package/dist/with-resilience/index.js +251 -0
- package/dist/with-resilience/index.js.map +1 -0
- package/dist/with-telemetry/index.d.ts +149 -0
- package/dist/with-telemetry/index.js +70 -0
- package/dist/with-telemetry/index.js.map +1 -0
- package/dist/work-queue/adapter.d.ts +82 -0
- package/dist/work-queue/adapter.js +4 -0
- package/dist/work-queue/adapter.js.map +1 -0
- package/dist/work-queue/index.d.ts +25 -11
- package/dist/work-queue/index.js +1 -46
- package/dist/work-queue/index.js.map +1 -1
- package/dist/work-queue/ops.d.ts +69 -0
- package/dist/work-queue/ops.js +3 -0
- package/dist/work-queue/ops.js.map +1 -0
- package/dist/workflow/index.d.ts +450 -0
- package/dist/workflow/index.js +225 -0
- package/dist/workflow/index.js.map +1 -0
- package/package.json +168 -25
- package/dist/chunk-CMG2KMWX.js.map +0 -1
- package/dist/chunk-PYBQREFU.js.map +0 -1
- package/dist/chunk-PYOCUBQJ.js.map +0 -1
- package/dist/chunk-Y5JM3UUH.js.map +0 -1
- package/dist/chunk-ZRUST6BK.js.map +0 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { IdempotencyStore } from '../idempotency/index.js';
|
|
2
|
+
import { C as Cmd } from '../core-BoB6t7dB.js';
|
|
3
|
+
import { QueueItem } from '../work-queue/index.js';
|
|
4
|
+
import '../index.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @demlik/tea/idempotent-intake — receive-once intake for webhooks / queue
|
|
8
|
+
* messages: dedupe by key, enqueue the new ones, replay the cached result to
|
|
9
|
+
* the duplicates. The "process this payload exactly once even though it
|
|
10
|
+
* arrives N times" knob.
|
|
11
|
+
*
|
|
12
|
+
* **The recipe.** This is a Level-2 composition — it owns no primitive
|
|
13
|
+
* queue/cache logic of its own, it *splices two L1 bricks into one Model slice*
|
|
14
|
+
* and DELEGATES every transition to their VERB SEAMS — `IdempotencyMemory`
|
|
15
|
+
* (`../idempotency/adapter`) and `QueueAdapter` (`../work-queue/adapter`) —
|
|
16
|
+
* so the store ops and the `QueueItem` / `IdempotencyStore` shapes stay
|
|
17
|
+
* insulated behind verbs the intake calls:
|
|
18
|
+
*
|
|
19
|
+
* - `../idempotency/adapter` — the dedupe-by-key + last-result cache. The
|
|
20
|
+
* `seen` half of the slice is its `IdempotencyStore`, keyed by
|
|
21
|
+
* `keyOf(payload)`. A key is recorded once `receive` calls `memory.remember`;
|
|
22
|
+
* `complete` calls `memory.remember` again to swap its cached value from
|
|
23
|
+
* `pending` to the finished `result`. The cache write is the brick's, never
|
|
24
|
+
* re-rolled here.
|
|
25
|
+
* - `../work-queue/adapter` — the pending-work list. The `queue` half of the
|
|
26
|
+
* slice is its `QueueItem<P>[]`. Every status flip routes through the
|
|
27
|
+
* adapter verbs: `receive` enqueues via `queue.enqueue`, `claimNext` stamps
|
|
28
|
+
* the `running` claim via `queue.patch`, `boot` re-arms a dead worker's
|
|
29
|
+
* claim via `queue.patch`. Intake owns only the SELECTION (which item,
|
|
30
|
+
* gated on the done-cache reconcile below) — the array transition is the
|
|
31
|
+
* brick's. The consumer drains it (claim → process → `complete`) at its own
|
|
32
|
+
* pace.
|
|
33
|
+
*
|
|
34
|
+
* Both bricks are pure-state + pure-ops, host- and clock-agnostic by
|
|
35
|
+
* construction, so the combined slice inherits TEA's two non-negotiables:
|
|
36
|
+
*
|
|
37
|
+
* - **Durable** — the slice is a plain serializable value (a record-backed
|
|
38
|
+
* idempotency store + an array of queue items, no `Map`, no closures), so
|
|
39
|
+
* it survives a Durable-Object eviction / reload and rehydrates whole.
|
|
40
|
+
* - **Replayable** — every verb is a pure `(state, …) => [state, Cmd[]]`
|
|
41
|
+
* transition; no `Date.now()`, no `Math.random()`, no I/O inside a verb.
|
|
42
|
+
* `at` (the clock) and `id` (the queue-item id) are *injected* at the call
|
|
43
|
+
* site, so `trace-replay` reconstructs each transition exactly.
|
|
44
|
+
*
|
|
45
|
+
* **The decision lives in a Cmd, not in a return shape.** `receive` cannot
|
|
46
|
+
* "return" what it decided (the knob contract pins the shape to
|
|
47
|
+
* `[State, Cmd[]]`), so the decision is *reified as a Cmd* the runtime
|
|
48
|
+
* performs:
|
|
49
|
+
*
|
|
50
|
+
* - first sighting of a key → mark it `pending`, enqueue the payload, emit
|
|
51
|
+
* `IntakeProcess` (go run the work).
|
|
52
|
+
* - a key already `pending` → drop silently (the original is in flight);
|
|
53
|
+
* emit nothing.
|
|
54
|
+
* - a key already `done` → emit `IntakeReplay` carrying the cached
|
|
55
|
+
* result so the duplicate caller gets the SAME response the first one
|
|
56
|
+
* produced, with zero re-execution of the side effect.
|
|
57
|
+
*
|
|
58
|
+
* **Two crash-safety guarantees the verbs enforce (and the unit specs alone
|
|
59
|
+
* missed — see the wired-machine test):**
|
|
60
|
+
*
|
|
61
|
+
* - *A slow worker is never double-enqueued.* The TTL clock starts at
|
|
62
|
+
* `complete`, not at `receive`: a `pending` entry NEVER ages out, so a
|
|
63
|
+
* duplicate of an in-flight key is always dropped no matter how long the
|
|
64
|
+
* worker takes. Only a `done` entry expires (see `liveEntry`).
|
|
65
|
+
* - *A complete-then-crash never re-runs.* `boot` and `claimNext` reconcile
|
|
66
|
+
* the queue against the done cache: a queue item whose key already resolved
|
|
67
|
+
* to `done` in `seen` is skipped (never reset to pending, never claimed),
|
|
68
|
+
* so a worker that finished and cached its result before the DO evicted is
|
|
69
|
+
* not re-executed on resume.
|
|
70
|
+
*
|
|
71
|
+
* Typical wiring (the combinator form — splice ~3 hooks into a host machine):
|
|
72
|
+
*
|
|
73
|
+
* const intake = createIntake<StripeEvent, ChargeResult>({
|
|
74
|
+
* keyOf: (e) => e.id, // Stripe's idempotency key
|
|
75
|
+
* ttlMs: 24 * 60 * 60 * 1000, // a replayed webhook 24h after it COMPLETED is re-run
|
|
76
|
+
* });
|
|
77
|
+
*
|
|
78
|
+
* // in `init`:
|
|
79
|
+
* intake: intake.init(),
|
|
80
|
+
* // in `update`, on the inbound-webhook Msg:
|
|
81
|
+
* const [next, cmds] = intake.receive(state.intake, payload, at, id);
|
|
82
|
+
* // …route `IntakeProcess` to your worker, `IntakeReplay` to the responder.
|
|
83
|
+
* // on the worker's done Msg:
|
|
84
|
+
* const [next, _] = intake.complete(state.intake, key, result, at);
|
|
85
|
+
* // once, after boot (DO reload), before resuming the drain:
|
|
86
|
+
* const [next, _] = intake.boot(state.intake);
|
|
87
|
+
*
|
|
88
|
+
* Escape hatch: reach the raw L1 ops via `@demlik/tea/idempotency` and
|
|
89
|
+
* `@demlik/tea/work-queue` and thread them by hand.
|
|
90
|
+
*/
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* A cached intake entry: either a key whose work is still in flight
|
|
94
|
+
* (`pending`) or one whose work has finished and whose `result` is held for
|
|
95
|
+
* replay to later duplicates (`done`). Discriminated on `phase` — `pending`
|
|
96
|
+
* carries no payload, `done` carries the result `R`.
|
|
97
|
+
*
|
|
98
|
+
* Lives inside the `seen` half of the slice (`IdempotencyStore<IntakeEntry<R>>`).
|
|
99
|
+
* It is the dedupe ledger's *value*; the ledger's *key* is `keyOf(payload)`.
|
|
100
|
+
*/
|
|
101
|
+
type IntakeEntry<R> = {
|
|
102
|
+
readonly phase: "pending";
|
|
103
|
+
} | {
|
|
104
|
+
readonly phase: "done";
|
|
105
|
+
readonly result: R;
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* The intake knob's config — `keyOf` derives the idempotency key from a
|
|
109
|
+
* payload, `ttlMs` (optional) ages a *completed* cached key out so a webhook
|
|
110
|
+
* replayed long after the work finished is treated as new and re-processed.
|
|
111
|
+
*
|
|
112
|
+
* **The TTL clock starts at `complete`, not at `receive`.** A `pending` entry
|
|
113
|
+
* (work still in flight) NEVER ages out, no matter how slow the worker is —
|
|
114
|
+
* ageing a pending key would let the duplicate re-enqueue the in-flight
|
|
115
|
+
* payload and double-process it. Only a `done` entry expires, measured from
|
|
116
|
+
* the `at` passed to `complete` (the moment the result was cached). Inside the
|
|
117
|
+
* window a duplicate replays the cached result; at/after the window it is
|
|
118
|
+
* re-accepted and re-processed.
|
|
119
|
+
*
|
|
120
|
+
* Omit `ttlMs` for a cache whose `done` entries never expire by age (keys live
|
|
121
|
+
* forever — fine for a bounded universe of ids, unbounded growth otherwise).
|
|
122
|
+
*
|
|
123
|
+
* The TTL is owned HERE, not delegated to the composed `IdempotencyStore`: the
|
|
124
|
+
* store's uniform per-entry TTL cannot tell `pending` from `done`, so intake
|
|
125
|
+
* keeps the store TTL-free and applies the phase-aware rule itself (see
|
|
126
|
+
* `liveEntry`).
|
|
127
|
+
*/
|
|
128
|
+
interface IntakeConfig<P> {
|
|
129
|
+
/** Derive the idempotency key from a payload. Must be pure + deterministic. */
|
|
130
|
+
readonly keyOf: (payload: P) => string;
|
|
131
|
+
/**
|
|
132
|
+
* Age a *completed* key out after this many ms, measured from the `at`
|
|
133
|
+
* passed to `complete`. Pending keys never age out.
|
|
134
|
+
*/
|
|
135
|
+
readonly ttlMs?: number;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* The Model slice this knob owns. `seen` is the dedupe + last-result cache
|
|
139
|
+
* (the `../idempotency` brick); `queue` is the pending-work list (the
|
|
140
|
+
* `../work-queue` brick). Both are plain serializable values — the whole slice
|
|
141
|
+
* round-trips through `JSON` so it survives eviction and replays exactly.
|
|
142
|
+
*/
|
|
143
|
+
interface IntakeState<P, R> {
|
|
144
|
+
readonly seen: IdempotencyStore<IntakeEntry<R>>;
|
|
145
|
+
readonly queue: readonly QueueItem<P>[];
|
|
146
|
+
}
|
|
147
|
+
/** A genuinely-new payload was accepted and enqueued — go run the work. */
|
|
148
|
+
interface IntakeProcessCmd<P> extends Cmd<"intake:process"> {
|
|
149
|
+
/** The dedupe key the payload was filed under. */
|
|
150
|
+
readonly key: string;
|
|
151
|
+
/** The enqueued queue-item id (the same `id` passed to `receive`). */
|
|
152
|
+
readonly itemId: string;
|
|
153
|
+
/** The original payload, for the worker to process. */
|
|
154
|
+
readonly payload: P;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* A duplicate of an already-completed key arrived — replay the cached result
|
|
158
|
+
* to the caller instead of re-running the side effect.
|
|
159
|
+
*/
|
|
160
|
+
interface IntakeReplayCmd<R> extends Cmd<"intake:replay"> {
|
|
161
|
+
/** The dedupe key whose cached result is being replayed. */
|
|
162
|
+
readonly key: string;
|
|
163
|
+
/** The result the ORIGINAL request produced, recalled from the cache. */
|
|
164
|
+
readonly result: R;
|
|
165
|
+
}
|
|
166
|
+
/** The Cmd union the intake verbs emit. */
|
|
167
|
+
type IntakeCmd<P, R> = IntakeProcessCmd<P> | IntakeReplayCmd<R>;
|
|
168
|
+
/**
|
|
169
|
+
* Build an idempotent-intake knob from `config`. Returns the uniform L2
|
|
170
|
+
* contract — `init()` + the verbs (`receive`, `complete`, `boot`, `claimNext`).
|
|
171
|
+
* No `subs` / `handlers`: intake owns no timers and does no I/O of its own (the
|
|
172
|
+
* composed bricks are pure-ops; the worker that runs `IntakeProcess` and the
|
|
173
|
+
* responder that runs `IntakeReplay` live in the host's interpret map).
|
|
174
|
+
*/
|
|
175
|
+
declare function createIntake<P, R>(config: IntakeConfig<P>): {
|
|
176
|
+
init: () => IntakeState<P, R>;
|
|
177
|
+
receive: (state: IntakeState<P, R>, payload: P, at: number, id: string) => readonly [IntakeState<P, R>, readonly IntakeCmd<P, R>[]];
|
|
178
|
+
complete: (state: IntakeState<P, R>, key: string, result: R, at: number) => readonly [IntakeState<P, R>, readonly IntakeCmd<P, R>[]];
|
|
179
|
+
boot: (state: IntakeState<P, R>) => readonly [IntakeState<P, R>, readonly IntakeCmd<P, R>[]];
|
|
180
|
+
claimNext: (state: IntakeState<P, R>, at: number) => {
|
|
181
|
+
readonly state: IntakeState<P, R>;
|
|
182
|
+
readonly claimed: QueueItem<P>;
|
|
183
|
+
} | null;
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
export { type IntakeCmd, type IntakeConfig, type IntakeEntry, type IntakeProcessCmd, type IntakeReplayCmd, type IntakeState, createIntake };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|