@axorum/client 0.0.0-stage → 1.0.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/LICENSE +202 -0
- package/README.md +530 -2
- package/dist/agent-uri.d.ts +30 -0
- package/dist/agent-uri.d.ts.map +1 -0
- package/dist/agent-uri.js +218 -0
- package/dist/agent-uri.js.map +1 -0
- package/dist/authorize.d.ts +671 -0
- package/dist/authorize.d.ts.map +1 -0
- package/dist/authorize.js +947 -0
- package/dist/authorize.js.map +1 -0
- package/dist/capabilities.d.ts +30 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +40 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/chart.d.ts +74 -0
- package/dist/chart.d.ts.map +1 -0
- package/dist/chart.js +107 -0
- package/dist/chart.js.map +1 -0
- package/dist/client.d.ts +644 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +1302 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +646 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +928 -0
- package/dist/errors.js.map +1 -0
- package/dist/failover.d.ts +197 -0
- package/dist/failover.d.ts.map +1 -0
- package/dist/failover.js +289 -0
- package/dist/failover.js.map +1 -0
- package/dist/freshness.d.ts +65 -0
- package/dist/freshness.d.ts.map +1 -0
- package/dist/freshness.js +148 -0
- package/dist/freshness.js.map +1 -0
- package/dist/generated/agent-plane.d.ts +1863 -0
- package/dist/generated/agent-plane.d.ts.map +1 -0
- package/dist/generated/agent-plane.js +19 -0
- package/dist/generated/agent-plane.js.map +1 -0
- package/dist/idempotency.d.ts +160 -0
- package/dist/idempotency.d.ts.map +1 -0
- package/dist/idempotency.js +208 -0
- package/dist/idempotency.js.map +1 -0
- package/dist/index.d.ts +89 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +87 -0
- package/dist/index.js.map +1 -0
- package/dist/intent.d.ts +163 -0
- package/dist/intent.d.ts.map +1 -0
- package/dist/intent.js +82 -0
- package/dist/intent.js.map +1 -0
- package/dist/json.d.ts +49 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +259 -0
- package/dist/json.js.map +1 -0
- package/dist/key.d.ts +64 -0
- package/dist/key.d.ts.map +1 -0
- package/dist/key.js +71 -0
- package/dist/key.js.map +1 -0
- package/dist/payment.d.ts +172 -0
- package/dist/payment.d.ts.map +1 -0
- package/dist/payment.js +178 -0
- package/dist/payment.js.map +1 -0
- package/dist/refusal.d.ts +121 -0
- package/dist/refusal.d.ts.map +1 -0
- package/dist/refusal.js +176 -0
- package/dist/refusal.js.map +1 -0
- package/dist/retry.d.ts +215 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +297 -0
- package/dist/retry.js.map +1 -0
- package/dist/typeid.d.ts +64 -0
- package/dist/typeid.d.ts.map +1 -0
- package/dist/typeid.js +119 -0
- package/dist/typeid.js.map +1 -0
- package/dist/types.d.ts +245 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -0
- package/package.json +58 -3
package/dist/refusal.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading why an intent was refused (contract 5.0.0).
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* The refusal codes this version of the contract documents.
|
|
8
|
+
*
|
|
9
|
+
* - `forbidden_by_rule`: a forbid rule in the judging policy won and no permit overrode
|
|
10
|
+
* it. `rule` names it.
|
|
11
|
+
* - `not_delegated`: a permit matched and its conditions held, but no delegation to the
|
|
12
|
+
* acting agent covers it. `rule` names the highest-priority such permit.
|
|
13
|
+
* - `denied_by_default`: no rule permitted the action for this actor, so the policy's
|
|
14
|
+
* default deny applied. No `rule`.
|
|
15
|
+
* - `reason_archived`: the refused record has been archived, so a replay cannot carry
|
|
16
|
+
* the reason. No `rule`.
|
|
17
|
+
*
|
|
18
|
+
* An **open vocabulary**: a newer service may send a code this client has never heard
|
|
19
|
+
* of. Test with {@link isKnownRefusalCode}, and fall back to `explanation`.
|
|
20
|
+
*/
|
|
21
|
+
export const REFUSAL_CODES = [
|
|
22
|
+
"forbidden_by_rule",
|
|
23
|
+
"not_delegated",
|
|
24
|
+
"denied_by_default",
|
|
25
|
+
"reason_archived",
|
|
26
|
+
];
|
|
27
|
+
/** Whether `code` is one this version of the contract documents. */
|
|
28
|
+
export function isKnownRefusalCode(code) {
|
|
29
|
+
return REFUSAL_CODES.includes(code);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* What a guard literal tested, named by `Condition.kind` (contract 5.0.0). An open
|
|
33
|
+
* vocabulary, like {@link REFUSAL_CODES}.
|
|
34
|
+
*/
|
|
35
|
+
export const CONDITION_KINDS = [
|
|
36
|
+
"register_cap",
|
|
37
|
+
"counterparty_limit",
|
|
38
|
+
"mandate_cap",
|
|
39
|
+
"counterparty_list",
|
|
40
|
+
"chart_of_accounts",
|
|
41
|
+
"posting_period",
|
|
42
|
+
"posted_balance",
|
|
43
|
+
"time_window",
|
|
44
|
+
"actor",
|
|
45
|
+
"param",
|
|
46
|
+
];
|
|
47
|
+
/** Whether `kind` is one this version of the contract documents. */
|
|
48
|
+
export function isKnownConditionKind(kind) {
|
|
49
|
+
return CONDITION_KINDS.includes(kind);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* What a figure read, named by `Figure.source`: `register` carries `register`, `window`
|
|
53
|
+
* and `scope`; `mandate` carries `mandate` and `quantity`. An open vocabulary.
|
|
54
|
+
*/
|
|
55
|
+
export const FIGURE_SOURCES = ["register", "mandate"];
|
|
56
|
+
/** The comparisons `Figure.op` can name, as the policy wrote them. An open vocabulary. */
|
|
57
|
+
export const COMPARISON_OPS = ["eq", "ne", "lt", "le", "gt", "ge", "in"];
|
|
58
|
+
/** The windows `Figure.window.kind` can name. An open vocabulary. */
|
|
59
|
+
export const WINDOW_KINDS = ["rolling", "calendar", "unbounded"];
|
|
60
|
+
/** The partitions `Figure.scope` can name. An open vocabulary. */
|
|
61
|
+
export const REGISTER_SCOPES = [
|
|
62
|
+
"per_party",
|
|
63
|
+
"per_role",
|
|
64
|
+
"per_counterparty",
|
|
65
|
+
"per_rail",
|
|
66
|
+
"global",
|
|
67
|
+
];
|
|
68
|
+
/** The mandate quantities `Figure.quantity` can name. An open vocabulary. */
|
|
69
|
+
export const MANDATE_QUANTITIES = ["spent", "ceiling", "remaining", "projected"];
|
|
70
|
+
/** The modalities `SetAside.modality` can name. An open vocabulary. */
|
|
71
|
+
export const MODALITIES = ["permitted", "obligated", "forbidden"];
|
|
72
|
+
/**
|
|
73
|
+
* The figure a condition compared, or `undefined` when the literal compared no figure
|
|
74
|
+
* (a list membership, an actor test) or the index is out of range.
|
|
75
|
+
*
|
|
76
|
+
* Every amount on a figure is a `bigint` in minor units of `currency`: exact at any
|
|
77
|
+
* magnitude, including above 2^64. `exponent` is the deployment's declared scale.
|
|
78
|
+
*
|
|
79
|
+
* ```ts
|
|
80
|
+
* const refusal = refusalOf(outcome);
|
|
81
|
+
* for (const condition of refusal?.conditions ?? []) {
|
|
82
|
+
* const figure = figureOf(refusal!, condition);
|
|
83
|
+
* if (figure?.headroom !== undefined && figure.headroom > 0n) {
|
|
84
|
+
* retryWith(figure.headroom); // the largest amount that clears this condition
|
|
85
|
+
* }
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export function figureOf(refusal, condition) {
|
|
90
|
+
if (condition.figure === undefined) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
const index = Number(condition.figure);
|
|
94
|
+
return Number.isSafeInteger(index) ? refusal.figures?.[index] : undefined;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* The substrate laws a `substrate_rejected` error body can name in `law` (contract
|
|
98
|
+
* 5.0.0). Present only on a genuine law violation, never on malformed input. An open
|
|
99
|
+
* vocabulary, like {@link REFUSAL_CODES}.
|
|
100
|
+
*/
|
|
101
|
+
export const SUBSTRATE_LAWS = [
|
|
102
|
+
"conservative",
|
|
103
|
+
"authorization_conservation",
|
|
104
|
+
"revenue_cost_matching",
|
|
105
|
+
"usage_balance_conservation",
|
|
106
|
+
"period_close_roll_forward",
|
|
107
|
+
];
|
|
108
|
+
/** Whether `law` is one this version of the contract documents. */
|
|
109
|
+
export function isKnownSubstrateLaw(law) {
|
|
110
|
+
return SUBSTRATE_LAWS.includes(law);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* What the caller must change, named by `cause` on a `substrate_rejected` error body
|
|
114
|
+
* (contract 5.0.0). Present only when the refusal broke no law but the intent was
|
|
115
|
+
* malformed in a way the caller can fix; a body carries `law` or `cause`, never both.
|
|
116
|
+
* An open vocabulary, like {@link REFUSAL_CODES}.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```ts
|
|
120
|
+
* if (error.body.cause === "unknown_account") {
|
|
121
|
+
* // provision the account, or post to one that exists
|
|
122
|
+
* }
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
export const SUBSTRATE_CAUSES = [
|
|
126
|
+
"unknown_account",
|
|
127
|
+
"account_revoked",
|
|
128
|
+
"currency_mismatch",
|
|
129
|
+
"non_positive_amount",
|
|
130
|
+
"entry_count",
|
|
131
|
+
"amount_overflow",
|
|
132
|
+
"unknown_mandate",
|
|
133
|
+
"mandate_revoked",
|
|
134
|
+
"unknown_usage",
|
|
135
|
+
"usage_not_owned",
|
|
136
|
+
"unknown_deferral",
|
|
137
|
+
"unknown_counterparty",
|
|
138
|
+
"counterparty_mandate_unresolved",
|
|
139
|
+
"undeclared_action",
|
|
140
|
+
"missing_param",
|
|
141
|
+
"unexpected_param",
|
|
142
|
+
"param_type_mismatch",
|
|
143
|
+
"period_closed",
|
|
144
|
+
"undeclared_currency",
|
|
145
|
+
];
|
|
146
|
+
/** Whether `cause` is one this version of the contract documents. */
|
|
147
|
+
export function isKnownSubstrateCause(cause) {
|
|
148
|
+
return SUBSTRATE_CAUSES.includes(cause);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Why `outcome` was refused, or `undefined` if it posted.
|
|
152
|
+
*
|
|
153
|
+
* Branch on `code`; for policy-specific reasons, branch on `rule.name`, which you
|
|
154
|
+
* declared. Show `explanation` to a human: it names the rule and says what to do next.
|
|
155
|
+
*
|
|
156
|
+
* `undefined` on a refused outcome means the service predates contract 5.0.0 and sent
|
|
157
|
+
* no reason; `posted: false` is still the refusal.
|
|
158
|
+
*
|
|
159
|
+
* The refusal is **not signed**. The receipt signs the provenance (whose `winning` is
|
|
160
|
+
* the rule id) and the policy hash; the refusal is derived from those, so a verifier
|
|
161
|
+
* recomputes it from signed facts rather than trusting these bytes.
|
|
162
|
+
*
|
|
163
|
+
* ```ts
|
|
164
|
+
* const outcome = await axorum.submitPinned(draft);
|
|
165
|
+
* const refusal = refusalOf(outcome);
|
|
166
|
+
* if (refusal?.code === "forbidden_by_rule" && refusal.rule?.name === "no_unapproved_vendors") {
|
|
167
|
+
* await askForVendorApproval();
|
|
168
|
+
* } else if (refusal) {
|
|
169
|
+
* console.log(refusal.explanation);
|
|
170
|
+
* }
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
export function refusalOf(outcome) {
|
|
174
|
+
return outcome.posted ? undefined : outcome.refusal;
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=refusal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refusal.js","sourceRoot":"","sources":["../src/refusal.ts"],"names":[],"mappings":"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"}
|
package/dist/retry.d.ts
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The transport retry policy: a mirror of `acton-service-client` 0.2's, which the Rust
|
|
3
|
+
* SDK uses, so both SDKs retry alike.
|
|
4
|
+
*
|
|
5
|
+
* Retries are **off** for a client's own calls unless it is built with a
|
|
6
|
+
* {@link RetryPolicy}. When one is, a request is sent again after a connection failure
|
|
7
|
+
* or a timeout, and after a `429`, `502` or `504` from something in front of the
|
|
8
|
+
* service (or a `423` that says when to come back), honouring `Retry-After`. A status
|
|
9
|
+
* the service documents as an answer (every `4xx` it sends, `421 not_primary`, `503
|
|
10
|
+
* commit_unavailable`) is not retried there: it reaches the caller after one send.
|
|
11
|
+
*
|
|
12
|
+
* `authorize` always retries, under its own policy ({@link AUTHORIZE_RETRY_POLICY}) and
|
|
13
|
+
* one deadline for the whole call ({@link AUTHORIZE_DEADLINE_MS}), and re-sends a `421`
|
|
14
|
+
* and a `503` too ({@link AUTHORIZE_RESENT_STATUSES}).
|
|
15
|
+
*
|
|
16
|
+
* Every function here is pure. `spec/fixtures/retry-v1.json` pins each one to the rows
|
|
17
|
+
* the Rust SDK pins `acton-service-client` itself to.
|
|
18
|
+
*
|
|
19
|
+
* @packageDocumentation
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* How a retry pause is spread below its exponential ceiling.
|
|
23
|
+
*
|
|
24
|
+
* - `"none"`: every pause is exactly the ceiling.
|
|
25
|
+
* - `"full"`: uniform over `[baseDelayMs, ceiling]`, floored at `baseDelayMs`, so a
|
|
26
|
+
* pause is never shorter than the base and a failing upstream is never hammered by a
|
|
27
|
+
* run of near-zero pauses.
|
|
28
|
+
*/
|
|
29
|
+
export type Jitter = "none" | "full";
|
|
30
|
+
/**
|
|
31
|
+
* Exponential backoff with a cap, optional jitter, and an optional total deadline.
|
|
32
|
+
* `maxAttempts` counts every send, the first included: `3` is one send and up to two
|
|
33
|
+
* retries. With a deadline, whichever of the two is reached first ends the loop.
|
|
34
|
+
*/
|
|
35
|
+
export interface RetryPolicy {
|
|
36
|
+
/** Sends in total, the first included. Below 1 behaves as 1. */
|
|
37
|
+
readonly maxAttempts: number;
|
|
38
|
+
/** The pause after the first send, in milliseconds, and the floor of every jittered one. */
|
|
39
|
+
readonly baseDelayMs: number;
|
|
40
|
+
/** The longest computed pause, in milliseconds. A `Retry-After` may exceed it. */
|
|
41
|
+
readonly maxDelayMs: number;
|
|
42
|
+
/**
|
|
43
|
+
* The whole call's budget, first send to last response, in milliseconds. Left out,
|
|
44
|
+
* the call is bounded by `maxAttempts` alone, and a `Retry-After` is honoured uncapped.
|
|
45
|
+
*/
|
|
46
|
+
readonly deadlineMs?: number;
|
|
47
|
+
/** How each pause is spread below its ceiling. Defaults to `"none"`. */
|
|
48
|
+
readonly jitter?: Jitter;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Three sends, 100 ms doubling, capped at 5 s, no jitter, no deadline:
|
|
52
|
+
* `acton-service-client`'s default.
|
|
53
|
+
*
|
|
54
|
+
* ```ts
|
|
55
|
+
* import { AxorumClient, DEFAULT_RETRY_POLICY } from "@axorum/client";
|
|
56
|
+
*
|
|
57
|
+
* const axorum = new AxorumClient({ baseUrl, retry: DEFAULT_RETRY_POLICY });
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare const DEFAULT_RETRY_POLICY: RetryPolicy;
|
|
61
|
+
/**
|
|
62
|
+
* The whole budget of one `authorize` call, in milliseconds: the window and pin reads,
|
|
63
|
+
* every submission, every attempt and every pause. The most `authorizeDeadlineMs`
|
|
64
|
+
* accepts, since the attestation minimum is sized for it.
|
|
65
|
+
*/
|
|
66
|
+
export declare const AUTHORIZE_DEADLINE_MS = 15000;
|
|
67
|
+
/**
|
|
68
|
+
* The response header on `GET /api/openapi.json` in which a clustered service advertises
|
|
69
|
+
* its commit wait (`[cluster] submit_timeout_ms`), in milliseconds: how long it holds a
|
|
70
|
+
* submission before answering `503 commit_unavailable`. A standalone service has no
|
|
71
|
+
* commit wait and sends none.
|
|
72
|
+
*/
|
|
73
|
+
export declare const SUBMIT_TIMEOUT_HEADER = "axorum-submit-timeout-ms";
|
|
74
|
+
/**
|
|
75
|
+
* How much longer than the advertised commit wait an attempt waits, in milliseconds, so
|
|
76
|
+
* the service's own `503 commit_unavailable` arrives before the client gives up.
|
|
77
|
+
*/
|
|
78
|
+
export declare const COMMIT_WAIT_MARGIN_MS = 1000;
|
|
79
|
+
/**
|
|
80
|
+
* The most one attempt waits, in milliseconds, when the service advertises no commit
|
|
81
|
+
* wait: a standalone service, one older than the header, or an advertisement that could
|
|
82
|
+
* not be read. Also the bound on each of `authorize`'s reads.
|
|
83
|
+
*/
|
|
84
|
+
export declare const SUBMIT_ATTEMPT_FALLBACK_MS = 6000;
|
|
85
|
+
/**
|
|
86
|
+
* The most one submission attempt waits against a service whose advertised commit wait
|
|
87
|
+
* is `commitWaitMs`: that wait plus {@link COMMIT_WAIT_MARGIN_MS}, or
|
|
88
|
+
* {@link SUBMIT_ATTEMPT_FALLBACK_MS} when none is advertised. Pure.
|
|
89
|
+
*
|
|
90
|
+
* Under `authorize`'s deadline the attempt is further clamped to what is left of it. When
|
|
91
|
+
* that clamp cuts an attempt below the commit wait plus the margin, the service may still
|
|
92
|
+
* be deciding when the client stops waiting, so an attempt that ends that way is honestly
|
|
93
|
+
* `indeterminate`: re-drive the same payment to learn its answer.
|
|
94
|
+
*
|
|
95
|
+
* ```ts
|
|
96
|
+
* submitAttemptTimeout(undefined); // 6000
|
|
97
|
+
* submitAttemptTimeout(9_000); // 10000
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export declare function submitAttemptTimeout(commitWaitMs: number | undefined): number;
|
|
101
|
+
/**
|
|
102
|
+
* The timeout a plain submission needs in place of the SDK's default `defaultMs` to
|
|
103
|
+
* outlast an advertised `commitWaitMs`: {@link submitAttemptTimeout} of it, when that is
|
|
104
|
+
* longer. Never shorter, and `undefined` when no wait is advertised. Pure.
|
|
105
|
+
*/
|
|
106
|
+
export declare function liftedSubmitTimeout(defaultMs: number, commitWaitMs: number | undefined): number | undefined;
|
|
107
|
+
/**
|
|
108
|
+
* The commit wait, in milliseconds, a {@link SUBMIT_TIMEOUT_HEADER} value states, or
|
|
109
|
+
* `undefined` when it states none: only 1 to 9 ASCII digits, not all zero, state a wait.
|
|
110
|
+
* Anything else (a sign, a space, an exponent, a tenth digit) is treated as no
|
|
111
|
+
* advertisement rather than guessed at, so this client reads the header as the Rust
|
|
112
|
+
* client does (`spec/fixtures/attempt-timeout-v1.json` pins both). Pure.
|
|
113
|
+
*/
|
|
114
|
+
export declare function advertisedCommitWait(value: string | null | undefined): number | undefined;
|
|
115
|
+
/**
|
|
116
|
+
* The policy every `authorize` request is sent under: as many attempts as the deadline
|
|
117
|
+
* allows, full jitter floored at 100 ms, capped at 1.6 s. The deadline is not in it: it is
|
|
118
|
+
* an instant, set once per call and shared by all of its requests.
|
|
119
|
+
*/
|
|
120
|
+
export declare const AUTHORIZE_RETRY_POLICY: RetryPolicy;
|
|
121
|
+
/**
|
|
122
|
+
* The status an `authorize` submission is re-sent on beyond the defaults: `421
|
|
123
|
+
* not_primary`, safe to re-send under the same transaction id. A `503` is not here: the
|
|
124
|
+
* transport re-sends on the status alone and reads no body, and only its body tells a
|
|
125
|
+
* `503 idempotency_unseeded`, which wrote nothing, from a `503 commit_unavailable`,
|
|
126
|
+
* which may have committed. So the call sends a `503` again itself, its body read.
|
|
127
|
+
*/
|
|
128
|
+
export declare const AUTHORIZE_RESENT_STATUSES: readonly number[];
|
|
129
|
+
/**
|
|
130
|
+
* The exponential ceiling for the pause after send number `attempt` (1-based):
|
|
131
|
+
* `baseDelayMs × 2^(attempt − 1)`, capped at `maxDelayMs`. An attempt below 1 is
|
|
132
|
+
* treated as 1; a huge one saturates to the cap. With no jitter it is the pause. Pure.
|
|
133
|
+
*/
|
|
134
|
+
export declare function backoffDelay(policy: RetryPolicy, attempt: number): number;
|
|
135
|
+
/**
|
|
136
|
+
* The pause after send number `attempt` (1-based), or `undefined` when it would reach the
|
|
137
|
+
* deadline. Pure.
|
|
138
|
+
*
|
|
139
|
+
* - `draw` is a uniform sample, clamped to `[0, 1)`; a `NaN` counts as 0. Ignored
|
|
140
|
+
* without jitter.
|
|
141
|
+
* - `remainingMs` is the time left before the deadline, or `undefined` for none.
|
|
142
|
+
*
|
|
143
|
+
* With `ceiling = backoffDelay(policy, attempt)` and `floor = min(baseDelayMs, ceiling)`:
|
|
144
|
+
* no jitter pauses `ceiling`; full jitter pauses `floor + ⌊(ceiling − floor) × draw⌋`.
|
|
145
|
+
* Either is refused when `remainingMs` is set and the pause is at least it.
|
|
146
|
+
*/
|
|
147
|
+
export declare function pause(policy: RetryPolicy, attempt: number, draw: number, remainingMs: number | undefined): number | undefined;
|
|
148
|
+
/** Whether another send is allowed after send number `attempt` (1-based). Pure. */
|
|
149
|
+
export declare function shouldRetry(policy: RetryPolicy, attempt: number): boolean;
|
|
150
|
+
/**
|
|
151
|
+
* The pause before the send after `attempt`, or `undefined` to stop: when `maxAttempts`
|
|
152
|
+
* is spent, or when the pause would reach the deadline. A server's `Retry-After`
|
|
153
|
+
* replaces the computed pause (unjittered, not capped by `maxDelayMs`) but is still
|
|
154
|
+
* refused if it would reach the deadline. Pure.
|
|
155
|
+
*/
|
|
156
|
+
export declare function nextPause(policy: RetryPolicy, attempt: number, draw: number, retryAfterMs: number | undefined, remainingMs: number | undefined): number | undefined;
|
|
157
|
+
/**
|
|
158
|
+
* The timeout for one send, or `undefined` to leave the client's own. Pure.
|
|
159
|
+
*
|
|
160
|
+
* In order: the request's own, the client-wide attempt timeout, then (under a deadline
|
|
161
|
+
* only) the client's timeout, then the time remaining; under a deadline, whichever
|
|
162
|
+
* applies is clamped to what remains.
|
|
163
|
+
*/
|
|
164
|
+
export declare function attemptTimeout(requestMs: number | undefined, clientAttemptMs: number | undefined, clientMs: number | undefined, remainingMs: number | undefined): number | undefined;
|
|
165
|
+
/**
|
|
166
|
+
* Whether a failing `status` asks for another send. A status listed in `retryOn` always
|
|
167
|
+
* does, checked first; otherwise an accepted (documented) status never does, and any
|
|
168
|
+
* other does when {@link isRetriableStatus} says so. Pure.
|
|
169
|
+
*/
|
|
170
|
+
export declare function wantsRetry(status: number, hasRetryAfter: boolean, accepted: boolean, retryOn: readonly number[]): boolean;
|
|
171
|
+
/**
|
|
172
|
+
* Whether a failing status is worth another send: `429`, `502`, `503`, `504`, and `423`
|
|
173
|
+
* only when the server said when to come back. Pure.
|
|
174
|
+
*/
|
|
175
|
+
export declare function isRetriableStatus(status: number, hasRetryAfter: boolean): boolean;
|
|
176
|
+
/**
|
|
177
|
+
* How an attempt that is about to be sent again ended: the counterpart of
|
|
178
|
+
* `acton-service-client`'s `RetryReason`.
|
|
179
|
+
*/
|
|
180
|
+
export type RetryReason = {
|
|
181
|
+
readonly kind: "connect";
|
|
182
|
+
} | {
|
|
183
|
+
readonly kind: "timeout";
|
|
184
|
+
} | {
|
|
185
|
+
readonly kind: "status";
|
|
186
|
+
readonly status: number;
|
|
187
|
+
};
|
|
188
|
+
/** A reason's label, as the Rust SDK's `RetryReason::label` spells it: `"503"`, `"timeout"`. Pure. */
|
|
189
|
+
export declare function retryLabel(reason: RetryReason): string;
|
|
190
|
+
/**
|
|
191
|
+
* The pause, if it ends strictly before the deadline `remainingMs` away, or `undefined`
|
|
192
|
+
* when it would reach it: `acton-service-client`'s rule, the boundary included. With no
|
|
193
|
+
* deadline every pause fits. Pure.
|
|
194
|
+
*/
|
|
195
|
+
export declare function fitsBefore(pauseMs: number, remainingMs: number | undefined): number | undefined;
|
|
196
|
+
/**
|
|
197
|
+
* A `Retry-After` header's delay in milliseconds, or `undefined`. Only the
|
|
198
|
+
* delta-seconds form is read, as Rust parses a `u64`: an optional `+`, then digits. An
|
|
199
|
+
* HTTP date, a fraction, a minus sign or an overflow is ignored. Pure.
|
|
200
|
+
*/
|
|
201
|
+
export declare function parseRetryAfter(header: string | null): number | undefined;
|
|
202
|
+
/**
|
|
203
|
+
* Rejects a policy whose counts and delays are not non-negative whole numbers, whose
|
|
204
|
+
* deadline is not a positive whole number, or whose jitter is not one this SDK knows.
|
|
205
|
+
*
|
|
206
|
+
* @throws {RangeError} Naming the bad field.
|
|
207
|
+
*/
|
|
208
|
+
export declare function checkRetryPolicy(policy: RetryPolicy): void;
|
|
209
|
+
/**
|
|
210
|
+
* Whether a `fetch` rejection is a connection that never opened: the counterpart of
|
|
211
|
+
* reqwest's `is_connect`, which is what `acton-service-client` retries (with timeouts).
|
|
212
|
+
* A connection that broke after the request went out is not one. Pure.
|
|
213
|
+
*/
|
|
214
|
+
export declare function isConnectFailure(error: unknown): boolean;
|
|
215
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"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"}
|