@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,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as CmdOf, b as CmdDef, g as TaggedError, r as MalformedResult, T as TimerDeps, C as Cmd } from './core-BbgtiXdg.js';
|
|
2
2
|
import { RetryState, AnyRetryPolicy } from './retry-backoff/index.js';
|
|
3
|
-
import { T as TtlCache, D as DeadlineExceeded, a as DeadlineSub
|
|
3
|
+
import { T as TtlCache, D as DeadlineExceeded, a as DeadlineSub } from './index-Xufl55W8.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @packageDocumentation
|
|
@@ -352,18 +352,18 @@ interface DeadlineConfig {
|
|
|
352
352
|
readonly ms: number;
|
|
353
353
|
}
|
|
354
354
|
/**
|
|
355
|
-
* The family every unnamed knob speaks: `resilient_run` / `
|
|
356
|
-
* `
|
|
357
|
-
* the vocabulary of every knob that passes no name.
|
|
355
|
+
* The family every unnamed knob speaks: `resilient_run` / `resilient_run_ok` /
|
|
356
|
+
* `resilient_run_err`. Identical to the `MsgType.Resilient*` literals, which
|
|
357
|
+
* stay the vocabulary of every knob that passes no name.
|
|
358
358
|
*/
|
|
359
359
|
declare const DEFAULT_RESILIENT_NAME = "resilient";
|
|
360
360
|
type DefaultResilientName = typeof DEFAULT_RESILIENT_NAME;
|
|
361
361
|
/** The run Cmd's `type` for the `N` family. */
|
|
362
362
|
type ResilientRunType<N extends string> = `${N}_run`;
|
|
363
|
-
/** The success settle Msg's `type` for the `N` family. */
|
|
364
|
-
type ResilientOkType<N extends string> = `${N}
|
|
365
|
-
/** The failure settle Msg's `type` for the `N` family. */
|
|
366
|
-
type ResilientErrType<N extends string> = `${N}
|
|
363
|
+
/** The success settle Msg's `type` for the `N` family — minted by the engine. */
|
|
364
|
+
type ResilientOkType<N extends string> = `${N}_run_ok`;
|
|
365
|
+
/** The failure settle Msg's `type` for the `N` family — minted by the engine. */
|
|
366
|
+
type ResilientErrType<N extends string> = `${N}_run_err`;
|
|
367
367
|
/**
|
|
368
368
|
* The resilience knob. EVERY field is optional: omit a brick and its gate is
|
|
369
369
|
* skipped entirely (the slice still carries a default brick state so the shape
|
|
@@ -375,12 +375,13 @@ type ResilientErrType<N extends string> = `${N}_err`;
|
|
|
375
375
|
*/
|
|
376
376
|
interface ResilientConfig<N extends string = DefaultResilientName> {
|
|
377
377
|
/**
|
|
378
|
-
* What this knob's Cmd and settle Msgs are called: `<name>_run`,
|
|
379
|
-
* `<name>
|
|
380
|
-
*
|
|
378
|
+
* What this knob's Cmd and settle Msgs are called: `<name>_run`, and the
|
|
379
|
+
* `<name>_run_ok` / `<name>_run_err` the engine mints from the run handler's
|
|
380
|
+
* outcome. Omit it and the family is `resilient` — `resilient_run` /
|
|
381
|
+
* `resilient_run_ok` / `resilient_run_err`.
|
|
381
382
|
*
|
|
382
|
-
* Name a knob when a machine
|
|
383
|
-
* Two unnamed knobs meet in ONE `
|
|
383
|
+
* Name a knob when a machine holds more than one of the resilient family.
|
|
384
|
+
* Two unnamed knobs meet in ONE `resilient_run_ok` cell whose payload is the union
|
|
384
385
|
* of both results, and the consumer discriminates by hand on `key` — which the
|
|
385
386
|
* type checker cannot see. Under distinct names each knob settles into its own
|
|
386
387
|
* cell, already narrowed to its own payload.
|
|
@@ -398,7 +399,7 @@ interface ResilientConfig<N extends string = DefaultResilientName> {
|
|
|
398
399
|
* wall-clock outage budget (`DurationRetryPolicy`), or explicit
|
|
399
400
|
* `unbounded: true`. A duration bound needs no extra wiring: every path that
|
|
400
401
|
* records a failure already holds the instant it was observed as DATA —
|
|
401
|
-
* `
|
|
402
|
+
* `settle`'s `msg.at` (stamped at the interpret boundary) and `gate`'s `at`
|
|
402
403
|
* (the caller's `attempt` / the retry timer's `atMs`) — so the streak clock
|
|
403
404
|
* is fed from a Msg, never from a `Date.now()` inside a verb (invariant 2).
|
|
404
405
|
*/
|
|
@@ -441,7 +442,7 @@ interface CallBudget {
|
|
|
441
442
|
* `phase` so each phase carries only its own data (pattern 11):
|
|
442
443
|
*
|
|
443
444
|
* - `idle` — never attempted, or fully settled and forgotten.
|
|
444
|
-
* - `running` — the effect Cmd is out; awaiting `
|
|
445
|
+
* - `running` — the effect Cmd is out; awaiting `settle`.
|
|
445
446
|
* Carries the deadline budget ({@link CallBudget}) and the
|
|
446
447
|
* last `input` so a retry can re-issue it.
|
|
447
448
|
* - `waiting_retry` — a transient failure backed off; the retry timer is armed
|
|
@@ -497,11 +498,28 @@ interface ResilientState<I, R> {
|
|
|
497
498
|
readonly retry: Readonly<Record<string, RetryState>>;
|
|
498
499
|
readonly cache: TtlCache<R>;
|
|
499
500
|
readonly calls: Readonly<Record<string, CallPhase<I, R>>>;
|
|
501
|
+
/**
|
|
502
|
+
* The instant of the latest clocked transition this slice saw — the `at` of
|
|
503
|
+
* the last `attempt` / `resume` / `settleFailed`, settled Msg or timer fire.
|
|
504
|
+
* `timer` counts the soonest deadline down from it, so the built-in `timer`
|
|
505
|
+
* Sub gets a relative `ms` without anything reading a clock. `0` until the
|
|
506
|
+
* first clocked transition.
|
|
507
|
+
*/
|
|
508
|
+
readonly clockMs: number;
|
|
500
509
|
}
|
|
501
510
|
/**
|
|
502
|
-
* The
|
|
503
|
-
*
|
|
504
|
-
* is
|
|
511
|
+
* The failures a run handler may return (ADR 0021). `port_rejected` is the
|
|
512
|
+
* work failing — carry the cause beside the tag (`err({ _tag: "port_rejected",
|
|
513
|
+
* cause })`); `deadline_exceeded` is a handler that timed the work out itself.
|
|
514
|
+
* Either one settles as `<name>_run_err` and feeds the retry / breaker. Any
|
|
515
|
+
* other failure is a contract breach and goes to the error sink.
|
|
516
|
+
*/
|
|
517
|
+
type RunErr = TaggedError<"port_rejected" | "deadline_exceeded">;
|
|
518
|
+
/**
|
|
519
|
+
* The one effect this knob emits: "run the work for `key` with `input`". It is
|
|
520
|
+
* `Cmd.define`d, so the handler you write for it returns an outcome and the
|
|
521
|
+
* engine mints `<name>_run_ok` / `<name>_run_err` (ADR 0021). It carries no
|
|
522
|
+
* closure — `input` is plain data (invariant 3).
|
|
505
523
|
*/
|
|
506
524
|
declare function runCmdDef<I, R, N extends string = DefaultResilientName>(name?: N): CmdDef<`${N}_run`, {
|
|
507
525
|
readonly key: string;
|
|
@@ -512,37 +530,97 @@ declare function runCmdDef<I, R, N extends string = DefaultResilientName>(name?:
|
|
|
512
530
|
} | {
|
|
513
531
|
readonly [detail: string]: unknown;
|
|
514
532
|
readonly _tag: "port_rejected";
|
|
515
|
-
}
|
|
533
|
+
}>;
|
|
516
534
|
type RunCmdDef<I, R, N extends string = DefaultResilientName> = ReturnType<typeof runCmdDef<I, R, N>>;
|
|
517
|
-
type RunCmd<I, N extends string = DefaultResilientName> = CmdOf<RunCmdDef<I, unknown, N>>;
|
|
518
535
|
/**
|
|
519
|
-
*
|
|
520
|
-
*
|
|
521
|
-
*
|
|
522
|
-
* `key` switch a single shared cell forces is gone.
|
|
536
|
+
* The run Cmd value. `R` is its settle value — `unknown` reads any knob's run
|
|
537
|
+
* Cmd; the knob's own verbs emit it at their `R`, which is what lets a machine
|
|
538
|
+
* list `cmds: [rc.run]` and take the verbs' Cmds as its own.
|
|
523
539
|
*/
|
|
524
|
-
type
|
|
540
|
+
type RunCmd<I, N extends string = DefaultResilientName, R = unknown> = CmdOf<RunCmdDef<I, R, N>>;
|
|
541
|
+
/**
|
|
542
|
+
* The settle Msgs the engine mints from a run handler's outcome:
|
|
543
|
+
* `<name>_run_ok` carrying the handler's `value`, `<name>_run_err` carrying its
|
|
544
|
+
* declared `error`. Each carries the run Cmd it settles (`cmd.key` names the
|
|
545
|
+
* call) and the `at` the engine stamped. Both are generic in the knob's name
|
|
546
|
+
* family `N`, so two knobs named apart land in two `update` cells whose
|
|
547
|
+
* payloads are already narrowed.
|
|
548
|
+
*
|
|
549
|
+
* They are the `SettledOk` / `SettledErr` pair `Cmd.define` mints, spelled out
|
|
550
|
+
* so a helper that folds the error into a richer type of its own (llm-call's
|
|
551
|
+
* `LlmErr`, jev-ask's `JevAskErr`) can hand `settle` its Msg with `E` widened.
|
|
552
|
+
*/
|
|
553
|
+
type SucceedMsg<R, N extends string = DefaultResilientName, I = unknown> = {
|
|
525
554
|
readonly type: ResilientOkType<N>;
|
|
526
|
-
readonly
|
|
527
|
-
readonly
|
|
555
|
+
readonly cmd: RunCmd<I, N>;
|
|
556
|
+
readonly value: R;
|
|
528
557
|
readonly at: number;
|
|
529
558
|
};
|
|
530
|
-
type FailMsg<N extends string = DefaultResilientName> = {
|
|
559
|
+
type FailMsg<N extends string = DefaultResilientName, I = unknown, E = RunErr | MalformedResult> = {
|
|
531
560
|
readonly type: ResilientErrType<N>;
|
|
532
|
-
readonly
|
|
561
|
+
readonly cmd: RunCmd<I, N>;
|
|
562
|
+
readonly error: E;
|
|
563
|
+
readonly at: number;
|
|
564
|
+
};
|
|
565
|
+
/**
|
|
566
|
+
* What `settle` reads off a settled Msg: the call's `key` (on `cmd`), the
|
|
567
|
+
* engine's `at`, and the handler's `value` or `error`. {@link SucceedMsg} and
|
|
568
|
+
* {@link FailMsg} are both one of these, so an engine-minted Msg passes
|
|
569
|
+
* straight in; a helper that settles from its own data (a fallback answer, a
|
|
570
|
+
* compaction summary) builds the record without inventing a whole run Cmd.
|
|
571
|
+
*/
|
|
572
|
+
type SettleMsg<R, N extends string = DefaultResilientName> = {
|
|
573
|
+
readonly type?: ResilientOkType<N>;
|
|
574
|
+
readonly cmd: {
|
|
575
|
+
readonly key: string;
|
|
576
|
+
};
|
|
577
|
+
readonly value: R;
|
|
578
|
+
readonly at: number;
|
|
579
|
+
} | {
|
|
580
|
+
readonly type?: ResilientErrType<N>;
|
|
581
|
+
readonly cmd: {
|
|
582
|
+
readonly key: string;
|
|
583
|
+
};
|
|
533
584
|
readonly error: unknown;
|
|
534
585
|
readonly at: number;
|
|
535
586
|
};
|
|
587
|
+
/**
|
|
588
|
+
* How a settled call ended — the third thing `settle` hands back, and the only
|
|
589
|
+
* place the port's value can be read from.
|
|
590
|
+
*
|
|
591
|
+
* - `done` — the port answered; `value` is its result.
|
|
592
|
+
* - `failed` — no retry is left (or no retry brick); `error` is the last
|
|
593
|
+
* failure.
|
|
594
|
+
* - `retrying` — backed off; the retry timer is armed and the call is still
|
|
595
|
+
* live.
|
|
596
|
+
*/
|
|
597
|
+
type SettleOutcome<R> = {
|
|
598
|
+
readonly kind: "done";
|
|
599
|
+
readonly value: R;
|
|
600
|
+
} | {
|
|
601
|
+
readonly kind: "failed";
|
|
602
|
+
readonly error: unknown;
|
|
603
|
+
} | {
|
|
604
|
+
readonly kind: "retrying";
|
|
605
|
+
};
|
|
606
|
+
/**
|
|
607
|
+
* What `settle` returns: the settled slice, the Cmds it emitted, and the
|
|
608
|
+
* {@link SettleOutcome}. One record, so the slice update and the result read
|
|
609
|
+
* cannot be split apart in a hand-wired `update` cell.
|
|
610
|
+
*/
|
|
611
|
+
interface SettleResult<I, R, N extends string = DefaultResilientName> {
|
|
612
|
+
readonly call: ResilientState<I, R>;
|
|
613
|
+
readonly cmds: readonly RunCmd<I, N, R>[];
|
|
614
|
+
readonly outcome: SettleOutcome<R>;
|
|
615
|
+
}
|
|
536
616
|
/**
|
|
537
617
|
* The deadline Msg tag this knob's timers dispatch, derived from its name the
|
|
538
|
-
* same way
|
|
539
|
-
* `"deadline_exceeded"` literal
|
|
540
|
-
* the name existed already handles, and `mountResilientCall` still returns a
|
|
541
|
-
* `deadline_exceeded` cell for an unnamed knob.
|
|
618
|
+
* same way the settle Msgs are. The DEFAULT family keeps the bare
|
|
619
|
+
* `"deadline_exceeded"` literal.
|
|
542
620
|
*/
|
|
543
621
|
type ResilientDeadlineType<N extends string = DefaultResilientName> = N extends DefaultResilientName ? "deadline_exceeded" : `${N}_deadline`;
|
|
544
622
|
/**
|
|
545
|
-
* The name
|
|
623
|
+
* The name a deadline carries for the `N` family — `undefined` for the
|
|
546
624
|
* default family (no name at all, so the bare literal is dispatched), the name
|
|
547
625
|
* itself otherwise. One conditional, so the value and {@link
|
|
548
626
|
* ResilientDeadlineType} can never disagree about which family is unnamed.
|
|
@@ -567,20 +645,6 @@ type DeadlineExceededError = {
|
|
|
567
645
|
readonly id: string;
|
|
568
646
|
readonly atMs: number;
|
|
569
647
|
};
|
|
570
|
-
/**
|
|
571
|
-
* What `handlers(ports)` returns: the interpret cell for this knob's run Cmd,
|
|
572
|
-
* under that Cmd's own name. A named knob contributes `<name>_run`, so two
|
|
573
|
-
* knobs' handler records merge into one `interpret` without either shadowing
|
|
574
|
-
* the other.
|
|
575
|
-
*/
|
|
576
|
-
type ResilientHandlers<I, R, N extends string = DefaultResilientName> = {
|
|
577
|
-
readonly [K in ResilientRunType<N>]: (cmd: RunCmd<I, N>, ctx: NoCtx) => Promise<SucceedMsg<R, N> | FailMsg<N>>;
|
|
578
|
-
};
|
|
579
|
-
/** Ports the consumer supplies to `handlers`. */
|
|
580
|
-
interface ResilientPorts<I, R> {
|
|
581
|
-
/** The fallible work this knob wraps. Throws on failure → routed to `fail`. */
|
|
582
|
-
readonly run: (input: I, key: string) => Promise<R>;
|
|
583
|
-
}
|
|
584
648
|
/**
|
|
585
649
|
* Build a resilient-call knob from `config`. `rng` is injected for retry
|
|
586
650
|
* jitter — pass a fixed `() => 0.5` in tests to pin backoff; defaults to
|
|
@@ -588,30 +652,39 @@ interface ResilientPorts<I, R> {
|
|
|
588
652
|
* curried onto the factory rather than threaded through every verb so callers
|
|
589
653
|
* spell the determinism choice once.
|
|
590
654
|
*
|
|
591
|
-
* Returns
|
|
592
|
-
*
|
|
593
|
-
* `withResilience` (`../with-resilience`) — see the migration map at the top
|
|
594
|
-
* of this module.
|
|
655
|
+
* Returns plain functions and the run Cmd def (ADR 0022) — see the module doc
|
|
656
|
+
* for the wiring. `I` is the work's input type, `R` its result type.
|
|
595
657
|
*/
|
|
596
658
|
declare function createResilientCall<I, R, N extends string = DefaultResilientName>(config: ResilientConfig<N>, rng?: () => number): {
|
|
597
659
|
name: N;
|
|
660
|
+
/** The `Cmd.define`d run Cmd; list it in the machine's `cmds`. */
|
|
661
|
+
run: CmdDef<`${N}_run`, {
|
|
662
|
+
readonly key: string;
|
|
663
|
+
readonly input: I;
|
|
664
|
+
}, R, {
|
|
665
|
+
readonly [detail: string]: unknown;
|
|
666
|
+
readonly _tag: "deadline_exceeded";
|
|
667
|
+
} | {
|
|
668
|
+
readonly [detail: string]: unknown;
|
|
669
|
+
readonly _tag: "port_rejected";
|
|
670
|
+
}>;
|
|
598
671
|
init: () => ResilientState<I, R>;
|
|
599
|
-
attempt: (s: ResilientState<I, R>, key: string, input: I, at: number) => readonly [ResilientState<I, R>, readonly RunCmd<I, N>[]];
|
|
672
|
+
attempt: (s: ResilientState<I, R>, key: string, input: I, at: number) => readonly [ResilientState<I, R>, readonly RunCmd<I, N, R>[]];
|
|
600
673
|
resume: (s: ResilientState<I, R>, at: number) => ResilientState<I, R>;
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
674
|
+
settle: (s: ResilientState<I, R>, msg: SettleMsg<R, N>) => SettleResult<I, R, N>;
|
|
675
|
+
settleFailed: (s: ResilientState<I, R>, key: string, error: unknown, at: number) => readonly [ResilientState<I, R>, readonly RunCmd<I, N, R>[]];
|
|
676
|
+
onTimer: (slice: ResilientState<I, R>, msg: {
|
|
677
|
+
readonly id: string;
|
|
678
|
+
readonly atMs: number;
|
|
679
|
+
}) => readonly [ResilientState<I, R>, readonly RunCmd<I, N, R>[]];
|
|
680
|
+
deadlines: (s: ResilientState<I, R>) => readonly DeadlineSub<DeadlineNameOf<N>>[];
|
|
681
|
+
timer: (s: ResilientState<I, R>) => TimerDeps<ResilientTimerMsg<N>> | null;
|
|
607
682
|
};
|
|
608
683
|
/**
|
|
609
684
|
* Lift a knob result `[slice, cmds]` into a host `[State, cmds]` where the
|
|
610
685
|
* slice lives at `state.resilience`. A convenience for the common single-slice
|
|
611
686
|
* host; consumers with a differently-named field spread by hand. Pure — a thin
|
|
612
|
-
* record rebuild, no clock / RNG.
|
|
613
|
-
* `model.$resilience`, so there is nothing to lift; this is for the embedded
|
|
614
|
-
* slice consumers only.
|
|
687
|
+
* record rebuild, no clock / RNG.
|
|
615
688
|
*
|
|
616
689
|
* The record rebuild itself is `liftSlice` from the root door (#231) — this
|
|
617
690
|
* stays as the named, pre-keyed convenience for the `state.resilience` field,
|
|
@@ -620,187 +693,5 @@ declare function createResilientCall<I, R, N extends string = DefaultResilientNa
|
|
|
620
693
|
declare function liftResilience<S extends {
|
|
621
694
|
resilience: ResilientState<I, R>;
|
|
622
695
|
}, I, R, C extends Cmd>(state: S, result: readonly [ResilientState<I, R>, readonly C[]]): readonly [S, readonly C[]];
|
|
623
|
-
/** What every verb of a knob in this family hands back. */
|
|
624
|
-
type Settle<I, R> = readonly [
|
|
625
|
-
ResilientState<I, R>,
|
|
626
|
-
readonly RunCmd<I>[]
|
|
627
|
-
];
|
|
628
|
-
/**
|
|
629
|
-
* The part of a resilient-call knob {@link mountResilientCall} needs. This knob
|
|
630
|
-
* satisfies it, and so does every knob that delegates these verbs to it —
|
|
631
|
-
* `internal/jev/ask` and `internal/llm-call` both do, which is why the mount is
|
|
632
|
-
* written against the shape rather than against either door.
|
|
633
|
-
*
|
|
634
|
-
* `OkMsg` / `ErrMsg` are parameters rather than {@link SucceedMsg} /
|
|
635
|
-
* {@link FailMsg} because an inheriting knob narrows them: jev-ask's `fail`
|
|
636
|
-
* takes a `JevFailMsg` whose `error` is a typed `JevAskErr`, and a mount that
|
|
637
|
-
* fixed the supertype would hand that verb a widened Msg.
|
|
638
|
-
*/
|
|
639
|
-
interface MountableKnob<I, R, OkMsg, ErrMsg, Handlers, N extends string = DefaultResilientName> {
|
|
640
|
-
/**
|
|
641
|
-
* The Msg-name family this knob settles into — `<name>_ok` / `<name>_err`
|
|
642
|
-
* (#229). The mount reads it rather than assuming `resilient_*`, so a named
|
|
643
|
-
* knob mounts into the cells it actually emits; an unnamed one is
|
|
644
|
-
* `resilient`, so nothing a machine already spread changes.
|
|
645
|
-
*/
|
|
646
|
-
readonly name: N;
|
|
647
|
-
init(): ResilientState<I, R>;
|
|
648
|
-
succeed(s: ResilientState<I, R>, key: string, msg: OkMsg): Settle<I, R>;
|
|
649
|
-
fail(s: ResilientState<I, R>, key: string, msg: ErrMsg): Settle<I, R>;
|
|
650
|
-
onTimer(s: ResilientState<I, R>, msg: ResilientTimerMsg<N>): Settle<I, R>;
|
|
651
|
-
subs(s: ResilientState<I, R>): readonly DeadlineSub<DeadlineNameOf<N>>[];
|
|
652
|
-
handlers(): Handlers;
|
|
653
|
-
}
|
|
654
|
-
/**
|
|
655
|
-
* The consumer's half of a settle cell: fold the settled answer into the
|
|
656
|
-
* machine's own Model.
|
|
657
|
-
*
|
|
658
|
-
* It is handed the Model the inherited verb ALREADY settled — the slice at
|
|
659
|
-
* `slice` is the post-`succeed` / post-`fail` one — so the ordering that wedges
|
|
660
|
-
* a call at `running` is not something this callback can express. It returns
|
|
661
|
-
* the repo's universal cell shape so a fold that needs to chain an effect
|
|
662
|
-
* (book the answer, then write it somewhere) returns that Cmd like any other
|
|
663
|
-
* reducer cell would.
|
|
664
|
-
*/
|
|
665
|
-
type SettleFold<Model, M, C extends Cmd> = (model: Model, msg: M) => readonly [Model, readonly C[]];
|
|
666
|
-
/** One cell of the update fragment {@link mountResilientCall} returns. */
|
|
667
|
-
type MountedCell<Model, M, I, C extends Cmd> = (model: Model, msg: M) => readonly [Model, readonly (RunCmd<I> | C)[]];
|
|
668
|
-
/**
|
|
669
|
-
* What to mount, and where. `slice` names the Model field the knob's state
|
|
670
|
-
* lives on — a plain, readable field, per
|
|
671
|
-
* [ADR 0015](../../../../.decisions/0015-hide-the-wiring-never-the-state.md):
|
|
672
|
-
* the mount absorbs the assembly and hides none of the durable state.
|
|
673
|
-
*/
|
|
674
|
-
interface MountConfig<Model, Slice extends string, I, R, AttemptType extends string, AttemptMsg, OkMsg, ErrMsg, C extends Cmd, N extends string = DefaultResilientName> {
|
|
675
|
-
/** The Model field carrying the knob's slice. */
|
|
676
|
-
readonly slice: Slice;
|
|
677
|
-
/**
|
|
678
|
-
* The cell that starts a call. Its shape is the one wiring point the mount
|
|
679
|
-
* cannot supply: each door's `attempt` takes its own arguments (jev-ask reads
|
|
680
|
-
* a key, a state and an instant; llm-call reads a request), and only the
|
|
681
|
-
* consumer knows which Msg field carries each. `run` is that one line.
|
|
682
|
-
*/
|
|
683
|
-
readonly attempt: {
|
|
684
|
-
/** The Msg type that starts a call — the key the cell lands on. */
|
|
685
|
-
readonly on: AttemptType;
|
|
686
|
-
readonly run: (slice: ResilientState<I, R>, msg: AttemptMsg) => Settle<I, R>;
|
|
687
|
-
};
|
|
688
|
-
/** Fold a settled success into the Model. Omit and only the slice advances. */
|
|
689
|
-
readonly onOk?: SettleFold<Model, OkMsg, C>;
|
|
690
|
-
/** Fold a settled failure into the Model. Omit and only the slice advances. */
|
|
691
|
-
readonly onErr?: SettleFold<Model, ErrMsg, C>;
|
|
692
|
-
/**
|
|
693
|
-
* Fold a call the TIMER settled into the Model. This is the third failure
|
|
694
|
-
* class, and it never reaches {@link MountConfig.onErr}: a deadline fire
|
|
695
|
-
* settles `failed` inside the slice and emits no settle Msg, so without this
|
|
696
|
-
* callback a call that dies on its budget advances the slice and folds
|
|
697
|
-
* nothing — the shape that used to be a documented caveat.
|
|
698
|
-
*
|
|
699
|
-
* It runs once per call the knob's deadline cell moved INTO `failed`:
|
|
700
|
-
* the deadline fire itself, and the resumed retry whose gate found the
|
|
701
|
-
* budget spent. A plain backoff tick, a stale fire and an already-`failed`
|
|
702
|
-
* call fold nothing. `error` is the slice's own settled error — a
|
|
703
|
-
* {@link DeadlineExceededError} on the deadline path.
|
|
704
|
-
*
|
|
705
|
-
* Omit and only the slice advances, exactly as the other two do.
|
|
706
|
-
*/
|
|
707
|
-
readonly onDeadline?: SettleFold<Model, DeadlineSettled<N>, C>;
|
|
708
|
-
}
|
|
709
|
-
/**
|
|
710
|
-
* What {@link MountConfig.onDeadline} is handed: the one call the timer cell
|
|
711
|
-
* just settled `failed`, named by its `key`, carrying the error the slice
|
|
712
|
-
* settled with and the timer Msg that produced it. It is not a Msg the reducer
|
|
713
|
-
* ever sees — no settle Msg exists for this failure class, which is the whole
|
|
714
|
-
* reason the callback is here.
|
|
715
|
-
*/
|
|
716
|
-
interface DeadlineSettled<N extends string = DefaultResilientName> {
|
|
717
|
-
/** The call key that settled. */
|
|
718
|
-
readonly key: string;
|
|
719
|
-
/** The error now on the slice — a {@link DeadlineExceededError} on the deadline path. */
|
|
720
|
-
readonly error: unknown;
|
|
721
|
-
/**
|
|
722
|
-
* The timer Msg whose fire settled it — this knob's own tag, so a fold on a
|
|
723
|
-
* knob named `jev` is handed a `jev_deadline` and one on an unnamed knob a
|
|
724
|
-
* `deadline_exceeded`.
|
|
725
|
-
*/
|
|
726
|
-
readonly msg: ResilientTimerMsg<N>;
|
|
727
|
-
}
|
|
728
|
-
/**
|
|
729
|
-
* The four fragments a consumer spreads into `defineMachine`. Together with
|
|
730
|
-
* `init` they are the eight wiring points; none of them is optional at the type
|
|
731
|
-
* level, so a consumer that mounts cannot omit `subscribe` (a backed-off retry
|
|
732
|
-
* that never fires) or re-implement `interpret` as a dispatching handler.
|
|
733
|
-
*/
|
|
734
|
-
interface MountedResilientCall<Model, Slice extends string, I, R, AttemptType extends string, AttemptMsg, OkMsg, ErrMsg, C extends Cmd, Handlers, N extends string = DefaultResilientName> {
|
|
735
|
-
/** The starting slice under its field name — spread into the machine's `init`. */
|
|
736
|
-
init(): {
|
|
737
|
-
readonly [K in Slice]: ResilientState<I, R>;
|
|
738
|
-
};
|
|
739
|
-
/**
|
|
740
|
-
* The three settle cells plus the attempt cell, to spread into `update`.
|
|
741
|
-
*
|
|
742
|
-
* The two settle keys are the knob's OWN Msg names (#229), so a knob built as
|
|
743
|
-
* `name: "jev"` mounts into `jev_ok` / `jev_err` and two named knobs in one
|
|
744
|
-
* machine spread into four distinct cells instead of colliding on one. An
|
|
745
|
-
* unnamed knob is `resilient`, so the keys read `resilient_ok` /
|
|
746
|
-
* `resilient_err` exactly as they always have.
|
|
747
|
-
*
|
|
748
|
-
* The deadline cell is keyed the same way (#238). A knob's deadline Sub
|
|
749
|
-
* carries its name, so a knob built as `name: "jev"` dispatches
|
|
750
|
-
* `jev_deadline` and mounts into a `jev_deadline` cell; an unnamed knob still
|
|
751
|
-
* dispatches and mounts `deadline_exceeded`. Before that, both mounts wrote
|
|
752
|
-
* the one unqualified `deadline_exceeded` key and the last spread silently
|
|
753
|
-
* dropped the other knob's deadline fold. The cell folds through
|
|
754
|
-
* {@link MountConfig.onDeadline}, since a call the timer settles emits no
|
|
755
|
-
* settle Msg and so reaches no `onErr`.
|
|
756
|
-
*/
|
|
757
|
-
readonly update: Readonly<Record<AttemptType, MountedCell<Model, AttemptMsg, I, C>>> & {
|
|
758
|
-
readonly [K in ResilientOkType<N>]: MountedCell<Model, OkMsg, I, C>;
|
|
759
|
-
} & {
|
|
760
|
-
readonly [K in ResilientErrType<N>]: MountedCell<Model, ErrMsg, I, C>;
|
|
761
|
-
} & {
|
|
762
|
-
readonly [K in ResilientDeadlineType<N>]: MountedCell<Model, ResilientTimerMsg<N>, I, C>;
|
|
763
|
-
};
|
|
764
|
-
subscriptions(model: Model): readonly DeadlineSub<DeadlineNameOf<N>>[];
|
|
765
|
-
readonly subscribe: {
|
|
766
|
-
readonly deadline: typeof subscribeDeadline;
|
|
767
|
-
};
|
|
768
|
-
readonly interpret: Handlers;
|
|
769
|
-
}
|
|
770
|
-
/**
|
|
771
|
-
* Pre-assemble a resilient-call knob into the fragments a machine definition
|
|
772
|
-
* spreads, so mounting one is a spread instead of eight hand-spliced points.
|
|
773
|
-
*
|
|
774
|
-
* The three points that used to fail only at runtime are gone at the type
|
|
775
|
-
* level rather than documented:
|
|
776
|
-
*
|
|
777
|
-
* - The settle cells run the inherited `succeed` / `fail` verb and hand the
|
|
778
|
-
* already-settled Model to {@link SettleFold}. There is no cell for a
|
|
779
|
-
* consumer to write in the wrong order.
|
|
780
|
-
* - `interpret` is `knob.handlers()` — the form that RETURNS the settle Msg
|
|
781
|
-
* so it re-enters the reducer. A consumer that spreads the fragment cannot
|
|
782
|
-
* substitute a dispatching handler for it.
|
|
783
|
-
* - `subscribe` carries `subscribeDeadline`, so the retry timer is armed by
|
|
784
|
-
* construction rather than by remembering.
|
|
785
|
-
*
|
|
786
|
-
* A deadline-exceeded call settles inside the slice and emits no settle Msg, so
|
|
787
|
-
* it reaches no `onErr`. {@link MountConfig.onDeadline} is that failure class's
|
|
788
|
-
* fold — omit it and the slice still advances, exactly as omitting `onErr`
|
|
789
|
-
* does.
|
|
790
|
-
*
|
|
791
|
-
* Nothing is taken away. The slice stays a plain field at `slice` that the
|
|
792
|
-
* consumer reads, `replay` sees and the journal prints, and every verb the
|
|
793
|
-
* fragments call is still exported and callable by hand — a consumer that
|
|
794
|
-
* wants a settle cell this shape cannot express writes that one cell itself and
|
|
795
|
-
* spreads the rest. PURE: a record of closures over `knob` and `config`, no
|
|
796
|
-
* clock and no RNG.
|
|
797
|
-
*/
|
|
798
|
-
declare function mountResilientCall<Slice extends string, I, R, Model extends {
|
|
799
|
-
readonly [K in Slice]: ResilientState<I, R>;
|
|
800
|
-
}, AttemptType extends string, AttemptMsg, OkMsg extends {
|
|
801
|
-
readonly key: string;
|
|
802
|
-
}, ErrMsg extends {
|
|
803
|
-
readonly key: string;
|
|
804
|
-
}, Handlers, C extends Cmd = never, N extends string = DefaultResilientName>(knob: MountableKnob<I, R, OkMsg, ErrMsg, Handlers, N>, config: MountConfig<Model, Slice, I, R, AttemptType, AttemptMsg, OkMsg, ErrMsg, C, N>): MountedResilientCall<Model, Slice, I, R, AttemptType, AttemptMsg, OkMsg, ErrMsg, C, Handlers, N>;
|
|
805
696
|
|
|
806
|
-
export {
|
|
697
|
+
export { initBucket as A, initCircuit as B, type CacheConfig as C, DEFAULT_RESILIENT_NAME as D, initWindow as E, type FailMsg as F, liftResilience as G, onFailure as H, onSuccess as I, record as J, refill as K, remaining as L, runCmdDef as M, tryConsume as N, type RunCmd as R, type SucceedMsg as S, type TokenBucket as T, type ResilientState as a, type ResilientTimerMsg as b, type ResilientConfig as c, type CallBudget as d, type CallPhase as e, type CircuitConfig as f, type CircuitPolicy as g, type CircuitState as h, type DeadlineExceededError as i, type DeadlineNameOf as j, type DefaultResilientName as k, type RateLimitConfig as l, type DeadlineConfig as m, type ResilientDeadlineType as n, type ResilientErrType as o, type ResilientOkType as p, type ResilientRunType as q, type RunCmdDef as r, type RunErr as s, type SettleMsg as t, type SettleOutcome as u, type SettleResult as v, type SlidingWindow as w, canPass as x, createResilientCall as y, defaultCircuitPolicy as z };
|