@openzeppelin/miden-multisig-client 0.16.1 → 0.16.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/README.md +48 -4
- package/dist/client.d.ts +4 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +5 -2
- package/dist/client.js.map +1 -1
- package/dist/client.test.js +7 -2
- package/dist/client.test.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/multisig.d.ts +3 -1
- package/dist/multisig.d.ts.map +1 -1
- package/dist/multisig.js +18 -9
- package/dist/multisig.js.map +1 -1
- package/dist/multisig.test.js +1 -0
- package/dist/multisig.test.js.map +1 -1
- package/dist/prover/errors.d.ts +5 -0
- package/dist/prover/errors.d.ts.map +1 -1
- package/dist/prover/errors.js +7 -155
- package/dist/prover/errors.js.map +1 -1
- package/dist/prover/errors.test.js +5 -0
- package/dist/prover/errors.test.js.map +1 -1
- package/dist/prover/retry.d.ts +1 -6
- package/dist/prover/retry.d.ts.map +1 -1
- package/dist/prover/retry.js +5 -28
- package/dist/prover/retry.js.map +1 -1
- package/dist/prover/retry.test.js +1 -1
- package/dist/prover/retry.test.js.map +1 -1
- package/dist/prover/workflow.d.ts +1 -1
- package/dist/prover/workflow.d.ts.map +1 -1
- package/dist/prover/workflow.test.js +23 -0
- package/dist/prover/workflow.test.js.map +1 -1
- package/dist/retry/classify.d.ts +16 -0
- package/dist/retry/classify.d.ts.map +1 -0
- package/dist/retry/classify.js +187 -0
- package/dist/retry/classify.js.map +1 -0
- package/dist/retry/runtime.d.ts +13 -0
- package/dist/retry/runtime.d.ts.map +1 -0
- package/dist/retry/runtime.js +33 -0
- package/dist/retry/runtime.js.map +1 -0
- package/dist/rpc/config.d.ts +11 -0
- package/dist/rpc/config.d.ts.map +1 -0
- package/dist/rpc/config.js +17 -0
- package/dist/rpc/config.js.map +1 -0
- package/dist/rpc/config.test.d.ts +2 -0
- package/dist/rpc/config.test.d.ts.map +1 -0
- package/dist/rpc/config.test.js +24 -0
- package/dist/rpc/config.test.js.map +1 -0
- package/dist/rpc/errors.d.ts +2 -0
- package/dist/rpc/errors.d.ts.map +1 -0
- package/dist/rpc/errors.js +11 -0
- package/dist/rpc/errors.js.map +1 -0
- package/dist/rpc/errors.test.d.ts +2 -0
- package/dist/rpc/errors.test.d.ts.map +1 -0
- package/dist/rpc/errors.test.js +34 -0
- package/dist/rpc/errors.test.js.map +1 -0
- package/dist/rpc/retry.d.ts +4 -0
- package/dist/rpc/retry.d.ts.map +1 -0
- package/dist/rpc/retry.js +6 -0
- package/dist/rpc/retry.js.map +1 -0
- package/dist/rpc/retry.test.d.ts +2 -0
- package/dist/rpc/retry.test.d.ts.map +1 -0
- package/dist/rpc/retry.test.js +98 -0
- package/dist/rpc/retry.test.js.map +1 -0
- package/package.json +2 -2
- package/src/client.test.ts +8 -2
- package/src/client.ts +11 -0
- package/src/index.ts +1 -0
- package/src/multisig.test.ts +1 -0
- package/src/multisig.ts +39 -8
- package/src/prover/errors.test.ts +8 -0
- package/src/prover/errors.ts +7 -175
- package/src/prover/retry.test.ts +1 -1
- package/src/prover/retry.ts +10 -35
- package/src/prover/workflow.test.ts +32 -1
- package/src/prover/workflow.ts +1 -1
- package/src/retry/classify.ts +220 -0
- package/src/retry/runtime.ts +45 -0
- package/src/rpc/config.test.ts +45 -0
- package/src/rpc/config.ts +30 -0
- package/src/rpc/errors.test.ts +69 -0
- package/src/rpc/errors.ts +12 -0
- package/src/rpc/retry.test.ts +144 -0
- package/src/rpc/retry.ts +12 -0
package/dist/prover/errors.d.ts
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prover-policy classification: the shared classifier with no transport-text
|
|
3
|
+
* extras — a bare "connection error" from a prover is treated as its
|
|
4
|
+
* considered answer.
|
|
5
|
+
*/
|
|
1
6
|
export declare function isTransientProverError(error: unknown): boolean;
|
|
2
7
|
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/prover/errors.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/prover/errors.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE9D"}
|
package/dist/prover/errors.js
CHANGED
|
@@ -1,158 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
]);
|
|
8
|
-
const PERMANENT_GRPC = new Set([
|
|
9
|
-
'invalidargument',
|
|
10
|
-
'failedprecondition',
|
|
11
|
-
'permissiondenied',
|
|
12
|
-
'unauthenticated',
|
|
13
|
-
'notfound',
|
|
14
|
-
'alreadyexists',
|
|
15
|
-
'outofrange',
|
|
16
|
-
'unimplemented',
|
|
17
|
-
'aborted',
|
|
18
|
-
'internal',
|
|
19
|
-
'dataloss',
|
|
20
|
-
]);
|
|
21
|
-
const TRANSIENT_HTTP = new Set([408, 429, 502, 503, 504]);
|
|
22
|
-
const NUMERIC_GRPC_CODES = new Map([
|
|
23
|
-
[0, 'ok'],
|
|
24
|
-
[1, 'cancelled'],
|
|
25
|
-
[2, 'unknown'],
|
|
26
|
-
[3, 'invalidargument'],
|
|
27
|
-
[4, 'deadlineexceeded'],
|
|
28
|
-
[5, 'notfound'],
|
|
29
|
-
[6, 'alreadyexists'],
|
|
30
|
-
[7, 'permissiondenied'],
|
|
31
|
-
[8, 'resourceexhausted'],
|
|
32
|
-
[9, 'failedprecondition'],
|
|
33
|
-
[10, 'aborted'],
|
|
34
|
-
[11, 'outofrange'],
|
|
35
|
-
[12, 'unimplemented'],
|
|
36
|
-
[13, 'internal'],
|
|
37
|
-
[14, 'unavailable'],
|
|
38
|
-
[15, 'dataloss'],
|
|
39
|
-
[16, 'unauthenticated'],
|
|
40
|
-
]);
|
|
41
|
-
function normalizeCode(value) {
|
|
42
|
-
if (typeof value === 'number') {
|
|
43
|
-
return NUMERIC_GRPC_CODES.get(value);
|
|
44
|
-
}
|
|
45
|
-
return typeof value === 'string' ? value.replaceAll(/[\s_-]/g, '').toLowerCase() : undefined;
|
|
46
|
-
}
|
|
47
|
-
function grpcEvidence(value) {
|
|
48
|
-
const code = normalizeCode(value);
|
|
49
|
-
if (code === undefined) {
|
|
50
|
-
return undefined;
|
|
51
|
-
}
|
|
52
|
-
if (TRANSIENT_GRPC.has(code)) {
|
|
53
|
-
return 'transient';
|
|
54
|
-
}
|
|
55
|
-
if (PERMANENT_GRPC.has(code)) {
|
|
56
|
-
return 'permanent';
|
|
57
|
-
}
|
|
58
|
-
if (code === 'unknown' || code === 'ok') {
|
|
59
|
-
return 'indeterminate';
|
|
60
|
-
}
|
|
61
|
-
return undefined;
|
|
62
|
-
}
|
|
63
|
-
function httpEvidence(value) {
|
|
64
|
-
if (typeof value !== 'number' || !Number.isInteger(value) || value < 400 || value > 599) {
|
|
65
|
-
return undefined;
|
|
66
|
-
}
|
|
67
|
-
return TRANSIENT_HTTP.has(value) ? 'transient' : 'permanent';
|
|
68
|
-
}
|
|
69
|
-
function httpMessageEvidence(message) {
|
|
70
|
-
let hasTransient = false;
|
|
71
|
-
for (const match of message.matchAll(/(?:\bhttp(?:\s+status)?|\bstatus\s*:?)\s*(\d{3})\b/g)) {
|
|
72
|
-
const evidence = httpEvidence(Number(match[1]));
|
|
73
|
-
if (evidence === 'permanent') {
|
|
74
|
-
return 'permanent';
|
|
75
|
-
}
|
|
76
|
-
hasTransient ||= evidence === 'transient';
|
|
77
|
-
}
|
|
78
|
-
return hasTransient ? 'transient' : undefined;
|
|
79
|
-
}
|
|
80
|
-
function flattenedTransient(message) {
|
|
81
|
-
return [
|
|
82
|
-
'cancelled',
|
|
83
|
-
'canceled',
|
|
84
|
-
'deadline exceeded',
|
|
85
|
-
'timeout',
|
|
86
|
-
'unavailable',
|
|
87
|
-
'resource exhausted',
|
|
88
|
-
'request timeout',
|
|
89
|
-
'too many requests',
|
|
90
|
-
'rate limited',
|
|
91
|
-
'rate limit',
|
|
92
|
-
'bad gateway',
|
|
93
|
-
'service unavailable',
|
|
94
|
-
'gateway timeout',
|
|
95
|
-
'i/o timeout',
|
|
96
|
-
'io timeout',
|
|
97
|
-
'connection reset',
|
|
98
|
-
'broken pipe',
|
|
99
|
-
].some((signal) => message.includes(signal));
|
|
100
|
-
}
|
|
101
|
-
function asRecord(value) {
|
|
102
|
-
return typeof value === 'object' && value !== null ? value : undefined;
|
|
103
|
-
}
|
|
1
|
+
import { isTransientError } from '../retry/classify.js';
|
|
2
|
+
/**
|
|
3
|
+
* Prover-policy classification: the shared classifier with no transport-text
|
|
4
|
+
* extras — a bare "connection error" from a prover is treated as its
|
|
5
|
+
* considered answer.
|
|
6
|
+
*/
|
|
104
7
|
export function isTransientProverError(error) {
|
|
105
|
-
|
|
106
|
-
const messages = [];
|
|
107
|
-
let hasTransient = false;
|
|
108
|
-
let hasPermanent = false;
|
|
109
|
-
let current = error;
|
|
110
|
-
while (current !== undefined && current !== null) {
|
|
111
|
-
const record = asRecord(current);
|
|
112
|
-
if (record !== undefined) {
|
|
113
|
-
if (seen.has(record)) {
|
|
114
|
-
break;
|
|
115
|
-
}
|
|
116
|
-
seen.add(record);
|
|
117
|
-
for (const evidence of [
|
|
118
|
-
grpcEvidence(record.code),
|
|
119
|
-
httpEvidence(record.status),
|
|
120
|
-
httpEvidence(record.statusCode),
|
|
121
|
-
]) {
|
|
122
|
-
hasTransient ||= evidence === 'transient';
|
|
123
|
-
hasPermanent ||= evidence === 'permanent';
|
|
124
|
-
}
|
|
125
|
-
if (typeof record.message === 'string') {
|
|
126
|
-
const message = record.message.toLowerCase();
|
|
127
|
-
messages.push(message);
|
|
128
|
-
const evidence = httpMessageEvidence(message);
|
|
129
|
-
hasTransient ||= evidence === 'transient';
|
|
130
|
-
hasPermanent ||= evidence === 'permanent';
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
const message = String(current).toLowerCase();
|
|
134
|
-
messages.push(message);
|
|
135
|
-
const evidence = httpMessageEvidence(message);
|
|
136
|
-
hasTransient ||= evidence === 'transient';
|
|
137
|
-
hasPermanent ||= evidence === 'permanent';
|
|
138
|
-
}
|
|
139
|
-
current = record.cause;
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
const message = String(current).toLowerCase();
|
|
143
|
-
messages.push(message);
|
|
144
|
-
const evidence = httpMessageEvidence(message);
|
|
145
|
-
hasTransient ||= evidence === 'transient';
|
|
146
|
-
hasPermanent ||= evidence === 'permanent';
|
|
147
|
-
break;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
if (hasPermanent) {
|
|
151
|
-
return false;
|
|
152
|
-
}
|
|
153
|
-
if (hasTransient) {
|
|
154
|
-
return true;
|
|
155
|
-
}
|
|
156
|
-
return messages.some(flattenedTransient);
|
|
8
|
+
return isTransientError(error);
|
|
157
9
|
}
|
|
158
10
|
//# sourceMappingURL=errors.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/prover/errors.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/prover/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAc;IACnD,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -20,5 +20,10 @@ describe('isTransientProverError', () => {
|
|
|
20
20
|
expect(isTransientProverError({ code: 14, message: 'unavailable' })).toBe(true);
|
|
21
21
|
expect(isTransientProverError({ code: 3, message: 'timeout text' })).toBe(false);
|
|
22
22
|
});
|
|
23
|
+
it('reads grpc code wording out of plain message text', () => {
|
|
24
|
+
expect(isTransientProverError(new Error('grpc code: NotFound'))).toBe(false);
|
|
25
|
+
expect(isTransientProverError(new Error('grpc code: Internal; nested timeout'))).toBe(false);
|
|
26
|
+
expect(isTransientProverError(new Error('grpc code: Unavailable'))).toBe(true);
|
|
27
|
+
});
|
|
23
28
|
});
|
|
24
29
|
//# sourceMappingURL=errors.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.test.js","sourceRoot":"","sources":["../../src/prover/errors.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAiBrD,SAAS,QAAQ;IACf,OAAO,IAAI,CAAC,KAAK,CACf,YAAY,CACV,IAAI,GAAG,CACL,wEAAwE,EACxE,MAAM,CAAC,IAAI,CAAC,GAAG,CAChB,EACD,MAAM,CACP,CACU,CAAC;AAChB,CAAC;AAED,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC,eAAe,EAAE,CAAC;YACjD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,CACrC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,CAAC,EACrC,SAAS,CACV,CAAC;YACF,MAAM,CAAC,sBAAsB,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,KAAK,GAAiB,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;QAC1E,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;QACpB,MAAM,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,sBAAsB,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChF,MAAM,CAAC,sBAAsB,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"errors.test.js","sourceRoot":"","sources":["../../src/prover/errors.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAiBrD,SAAS,QAAQ;IACf,OAAO,IAAI,CAAC,KAAK,CACf,YAAY,CACV,IAAI,GAAG,CACL,wEAAwE,EACxE,MAAM,CAAC,IAAI,CAAC,GAAG,CAChB,EACD,MAAM,CACP,CACU,CAAC;AAChB,CAAC;AAED,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC,eAAe,EAAE,CAAC;YACjD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,CACrC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,CAAC,EACrC,SAAS,CACV,CAAC;YACF,MAAM,CAAC,sBAAsB,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,KAAK,GAAiB,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;QAC1E,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;QACpB,MAAM,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,sBAAsB,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChF,MAAM,CAAC,sBAAsB,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,CAAC,sBAAsB,CAAC,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7E,MAAM,CACJ,sBAAsB,CAAC,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC,CACzE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACd,MAAM,CAAC,sBAAsB,CAAC,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/prover/retry.d.ts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import type { TransactionExecution, TransactionProof } from '@miden-sdk/miden-sdk';
|
|
2
2
|
import type { ResolvedProverConfig } from './config.js';
|
|
3
|
-
|
|
4
|
-
sleep(delayMs: number): Promise<void>;
|
|
5
|
-
unitRandom(): number;
|
|
6
|
-
}
|
|
7
|
-
export declare const productionRetryRuntime: RetryRuntime;
|
|
8
|
-
export declare function retryDelay(retryIndex: number, unitRandom: number): number;
|
|
3
|
+
import type { RetryRuntime } from '../retry/runtime.js';
|
|
9
4
|
export declare function proveWithRetry(execution: TransactionExecution, config: ResolvedProverConfig, runtime?: RetryRuntime): Promise<TransactionProof>;
|
|
10
5
|
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/prover/retry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/prover/retry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,wBAAsB,cAAc,CAClC,SAAS,EAAE,oBAAoB,EAC/B,MAAM,EAAE,oBAAoB,EAC5B,OAAO,GAAE,YAAqC,GAC7C,OAAO,CAAC,gBAAgB,CAAC,CAU3B"}
|
package/dist/prover/retry.js
CHANGED
|
@@ -1,32 +1,9 @@
|
|
|
1
1
|
import { isTransientProverError } from './errors.js';
|
|
2
|
-
|
|
3
|
-
const MAX_DELAY_MS = 8_000;
|
|
4
|
-
export const productionRetryRuntime = {
|
|
5
|
-
sleep: (delayMs) => new Promise((resolve) => setTimeout(resolve, delayMs)),
|
|
6
|
-
unitRandom: () => Math.random(),
|
|
7
|
-
};
|
|
8
|
-
export function retryDelay(retryIndex, unitRandom) {
|
|
9
|
-
const exponent = Math.min(retryIndex, 1023);
|
|
10
|
-
const raw = BASE_DELAY_MS * 2 ** exponent;
|
|
11
|
-
const finiteRandom = Number.isFinite(unitRandom) ? unitRandom : 0.5;
|
|
12
|
-
const boundedRandom = Math.min(Math.max(finiteRandom, 0), 1 - Number.EPSILON);
|
|
13
|
-
return Math.min(Math.floor(raw * (0.75 + boundedRandom * 0.5)), MAX_DELAY_MS);
|
|
14
|
-
}
|
|
2
|
+
import { productionRetryRuntime, retryTransient } from '../retry/runtime.js';
|
|
15
3
|
export async function proveWithRetry(execution, config, runtime = productionRetryRuntime) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
? await execution.prove()
|
|
21
|
-
: await execution.prove({ prover });
|
|
22
|
-
}
|
|
23
|
-
catch (error) {
|
|
24
|
-
if (!isTransientProverError(error) || attempt + 1 >= config.maxAttempts) {
|
|
25
|
-
throw error;
|
|
26
|
-
}
|
|
27
|
-
await runtime.sleep(retryDelay(attempt, runtime.unitRandom()));
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
throw new Error('unreachable prover retry state');
|
|
4
|
+
return retryTransient(async () => {
|
|
5
|
+
const prover = config.createProver();
|
|
6
|
+
return prover === undefined ? await execution.prove() : await execution.prove({ prover });
|
|
7
|
+
}, config.maxAttempts, isTransientProverError, runtime);
|
|
31
8
|
}
|
|
32
9
|
//# sourceMappingURL=retry.js.map
|
package/dist/prover/retry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/prover/retry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/prover/retry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE7E,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,SAA+B,EAC/B,MAA4B,EAC5B,UAAwB,sBAAsB;IAE9C,OAAO,cAAc,CACnB,KAAK,IAAI,EAAE;QACT,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;QACrC,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5F,CAAC,EACD,MAAM,CAAC,WAAW,EAClB,sBAAsB,EACtB,OAAO,CACR,CAAC;AACJ,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { describe, expect, it } from 'vitest';
|
|
3
|
-
import { retryDelay } from '
|
|
3
|
+
import { retryDelay } from '../retry/runtime.js';
|
|
4
4
|
function fixtures() {
|
|
5
5
|
return JSON.parse(readFileSync(new URL('../../../../fixtures/miden-multisig-client/prover-policy-fixtures.json', import.meta.url), 'utf8'));
|
|
6
6
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.test.js","sourceRoot":"","sources":["../../src/prover/retry.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"retry.test.js","sourceRoot":"","sources":["../../src/prover/retry.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAMjD,SAAS,QAAQ;IACf,OAAO,IAAI,CAAC,KAAK,CACf,YAAY,CACV,IAAI,GAAG,CACL,wEAAwE,EACxE,MAAM,CAAC,IAAI,CAAC,GAAG,CAChB,EACD,MAAM,CACP,CACU,CAAC;AAChB,CAAC;AAED,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC;YACxC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACnF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,CAAC,CAAC,CACvE,+CAA+C,EAC/C,CAAC,UAAU,EAAE,EAAE;QACb,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9C,CAAC,CACF,CAAC;AACJ,CAAC,CAAC,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AccountId, MidenClient, TransactionRequest } from '@miden-sdk/miden-sdk';
|
|
2
2
|
import type { ResolvedProverConfig } from './config.js';
|
|
3
|
-
import type { RetryRuntime } from '
|
|
3
|
+
import type { RetryRuntime } from '../retry/runtime.js';
|
|
4
4
|
export declare class ProverWorkflow {
|
|
5
5
|
private readonly client;
|
|
6
6
|
private readonly config;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/prover/workflow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACvF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/prover/workflow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACvF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAFR,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,oBAAoB,EAC5B,OAAO,CAAC,EAAE,YAAY,YAAA;IAGnC,MAAM,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;CAM/E"}
|
|
@@ -61,6 +61,29 @@ describe('ProverWorkflow', () => {
|
|
|
61
61
|
expect(prove).toHaveBeenCalledTimes(2);
|
|
62
62
|
expect(runtime.sleep).toHaveBeenCalledTimes(1);
|
|
63
63
|
});
|
|
64
|
+
it('never re-submits when submission fails with transient-looking wording', async () => {
|
|
65
|
+
const rateLimited = Object.assign(new Error('Too Many Requests!'), {
|
|
66
|
+
code: 'ResourceExhausted',
|
|
67
|
+
});
|
|
68
|
+
const submit = vi.fn().mockRejectedValue(rateLimited);
|
|
69
|
+
const prove = vi.fn().mockResolvedValue({ submit });
|
|
70
|
+
const client = {
|
|
71
|
+
transactions: { executeRequest: vi.fn().mockResolvedValue({ prove }) },
|
|
72
|
+
};
|
|
73
|
+
const runtime = {
|
|
74
|
+
sleep: vi.fn().mockResolvedValue(undefined),
|
|
75
|
+
unitRandom: () => 0.5,
|
|
76
|
+
};
|
|
77
|
+
const workflow = new ProverWorkflow(asType(client), {
|
|
78
|
+
kind: 'remote',
|
|
79
|
+
maxAttempts: 5,
|
|
80
|
+
createProver: () => asType({}),
|
|
81
|
+
}, runtime);
|
|
82
|
+
await expect(workflow.submit(asType({}), asType({}))).rejects.toBe(rateLimited);
|
|
83
|
+
expect(prove).toHaveBeenCalledTimes(1);
|
|
84
|
+
expect(submit).toHaveBeenCalledTimes(1);
|
|
85
|
+
expect(runtime.sleep).not.toHaveBeenCalled();
|
|
86
|
+
});
|
|
64
87
|
it('uses the injected prover directly when no cloneable remote override exists', async () => {
|
|
65
88
|
const apply = vi.fn().mockResolvedValue({});
|
|
66
89
|
const submit = vi.fn().mockResolvedValue({ apply });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow.test.js","sourceRoot":"","sources":["../../src/prover/workflow.test.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAGlD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,SAAS,MAAM,CAAI,KAAc;IAC/B,OAAO,KAAU,CAAC;AACpB,CAAC;AAED,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,iFAAiF,EAAE,KAAK,IAAI,EAAE;QAC/F,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,yBAAyB,CAAC,EAAE;YACpE,IAAI,EAAE,aAAa;SACpB,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACzF,MAAM,SAAS,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;QACjD,MAAM,cAAc,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAG;YACb,YAAY,EAAE,EAAE,cAAc,EAAE;SACjC,CAAC;QACF,MAAM,OAAO,GAAwB,EAAE,CAAC;QACxC,MAAM,MAAM,GAAyB;YACnC,IAAI,EAAE,QAAQ;YACd,GAAG,EAAE,yBAAyB;YAC9B,WAAW,EAAE,CAAC;YACd,YAAY,EAAE,GAAG,EAAE;gBACjB,MAAM,MAAM,GAAG,MAAM,CAAoB,EAAE,CAAC,CAAC;gBAC7C,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACrB,OAAO,MAAM,CAAC;YAChB,CAAC;SACF,CAAC;QACF,MAAM,OAAO,GAAiB;YAC5B,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;YAC3C,UAAU,EAAE,GAAG,EAAE,CAAC,GAAG;SACtB,CAAC;QACF,MAAM,QAAQ,GAAG,IAAI,cAAc,CACjC,MAAM,CAAc,MAAM,CAAC,EAC3B,MAAM,EACN,OAAO,CACR,CAAC;QAEF,MAAM,QAAQ,CAAC,MAAM,CACnB,MAAM,CAAY,EAAE,CAAC,EACrB,MAAM,CAAqB,EAAE,CAAC,CAC/B,CAAC;QAEF,MAAM,CAAC,cAAc,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,KAAK,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,KAAK,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QAClF,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,aAAa,CAAC,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;QAC/E,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,CAAC,EAAE;YAC1D,IAAI,EAAE,kBAAkB;SACzB,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;QAChF,MAAM,MAAM,GAAG,EAAE,YAAY,EAAE,EAAE,cAAc,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1F,MAAM,OAAO,GAAiB;YAC5B,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;YAC3C,UAAU,EAAE,GAAG,EAAE,CAAC,GAAG;SACtB,CAAC;QACF,MAAM,QAAQ,GAAG,IAAI,cAAc,CACjC,MAAM,CAAc,MAAM,CAAC,EAC3B;YACE,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,CAAC;YACd,YAAY,EAAE,GAAG,EAAE,CAAC,MAAM,CAAoB,EAAE,CAAC;SAClD,EACD,OAAO,CACR,CAAC;QAEF,MAAM,MAAM,CACV,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAY,EAAE,CAAC,EAAE,MAAM,CAAqB,EAAE,CAAC,CAAC,CACvE,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtB,MAAM,CAAC,KAAK,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;QAC1F,MAAM,KAAK,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG;YACb,YAAY,EAAE,EAAE,cAAc,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;SACvE,CAAC;QACF,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,MAAM,CAAc,MAAM,CAAC,EAAE;YAC/D,IAAI,EAAE,UAAU;YAChB,WAAW,EAAE,CAAC;YACd,YAAY,EAAE,GAAG,EAAE,CAAC,SAAS;SAC9B,CAAC,CAAC;QAEH,MAAM,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAY,EAAE,CAAC,EAAE,MAAM,CAAqB,EAAE,CAAC,CAAC,CAAC;QAE7E,MAAM,CAAC,KAAK,CAAC,CAAC,oBAAoB,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"workflow.test.js","sourceRoot":"","sources":["../../src/prover/workflow.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transient/permanent error classification shared by the prover and node-RPC
|
|
3
|
+
* retry policies, mirroring `is_transient_error_with` in the Rust
|
|
4
|
+
* `guardian-shared` crate: the whole cause chain is walked accumulating
|
|
5
|
+
* evidence, permanent evidence anywhere vetoes transient anywhere, and the
|
|
6
|
+
* transient-wording fallback fires only when no status-level evidence exists
|
|
7
|
+
* in any link. Behavior is pinned by the cross-SDK fixture corpus.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Walks the error's cause chain and reports whether every piece of evidence
|
|
11
|
+
* points at a transient failure. `extraTransientSignals` extends the
|
|
12
|
+
* transient-wording fallback for one policy without leaking into others,
|
|
13
|
+
* under the same permanent-wins rule.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isTransientError(error: unknown, extraTransientSignals?: readonly string[]): boolean;
|
|
16
|
+
//# sourceMappingURL=classify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/retry/classify.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAsJH;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,OAAO,EACd,qBAAqB,GAAE,SAAS,MAAM,EAAO,GAC5C,OAAO,CAqDT"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transient/permanent error classification shared by the prover and node-RPC
|
|
3
|
+
* retry policies, mirroring `is_transient_error_with` in the Rust
|
|
4
|
+
* `guardian-shared` crate: the whole cause chain is walked accumulating
|
|
5
|
+
* evidence, permanent evidence anywhere vetoes transient anywhere, and the
|
|
6
|
+
* transient-wording fallback fires only when no status-level evidence exists
|
|
7
|
+
* in any link. Behavior is pinned by the cross-SDK fixture corpus.
|
|
8
|
+
*/
|
|
9
|
+
const TRANSIENT_GRPC = new Set([
|
|
10
|
+
'cancelled',
|
|
11
|
+
'canceled',
|
|
12
|
+
'deadlineexceeded',
|
|
13
|
+
'unavailable',
|
|
14
|
+
'resourceexhausted',
|
|
15
|
+
]);
|
|
16
|
+
const PERMANENT_GRPC = new Set([
|
|
17
|
+
'invalidargument',
|
|
18
|
+
'failedprecondition',
|
|
19
|
+
'permissiondenied',
|
|
20
|
+
'unauthenticated',
|
|
21
|
+
'notfound',
|
|
22
|
+
'alreadyexists',
|
|
23
|
+
'outofrange',
|
|
24
|
+
'unimplemented',
|
|
25
|
+
'aborted',
|
|
26
|
+
'internal',
|
|
27
|
+
'dataloss',
|
|
28
|
+
]);
|
|
29
|
+
const TRANSIENT_HTTP = new Set([408, 429, 502, 503, 504]);
|
|
30
|
+
const NUMERIC_GRPC_CODES = new Map([
|
|
31
|
+
[0, 'ok'],
|
|
32
|
+
[1, 'cancelled'],
|
|
33
|
+
[2, 'unknown'],
|
|
34
|
+
[3, 'invalidargument'],
|
|
35
|
+
[4, 'deadlineexceeded'],
|
|
36
|
+
[5, 'notfound'],
|
|
37
|
+
[6, 'alreadyexists'],
|
|
38
|
+
[7, 'permissiondenied'],
|
|
39
|
+
[8, 'resourceexhausted'],
|
|
40
|
+
[9, 'failedprecondition'],
|
|
41
|
+
[10, 'aborted'],
|
|
42
|
+
[11, 'outofrange'],
|
|
43
|
+
[12, 'unimplemented'],
|
|
44
|
+
[13, 'internal'],
|
|
45
|
+
[14, 'unavailable'],
|
|
46
|
+
[15, 'dataloss'],
|
|
47
|
+
[16, 'unauthenticated'],
|
|
48
|
+
]);
|
|
49
|
+
const GRPC_MESSAGE_TOKENS = [
|
|
50
|
+
...[...TRANSIENT_GRPC].map((code) => ({ token: `grpccode${code}`, evidence: 'transient' })),
|
|
51
|
+
...[...PERMANENT_GRPC].map((code) => ({ token: `grpccode${code}`, evidence: 'permanent' })),
|
|
52
|
+
];
|
|
53
|
+
function normalizeCode(value) {
|
|
54
|
+
if (typeof value === 'number') {
|
|
55
|
+
return NUMERIC_GRPC_CODES.get(value);
|
|
56
|
+
}
|
|
57
|
+
return typeof value === 'string' ? value.replaceAll(/[\s_-]/g, '').toLowerCase() : undefined;
|
|
58
|
+
}
|
|
59
|
+
function grpcEvidence(value) {
|
|
60
|
+
const code = normalizeCode(value);
|
|
61
|
+
if (code === undefined) {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
if (TRANSIENT_GRPC.has(code)) {
|
|
65
|
+
return 'transient';
|
|
66
|
+
}
|
|
67
|
+
if (PERMANENT_GRPC.has(code)) {
|
|
68
|
+
return 'permanent';
|
|
69
|
+
}
|
|
70
|
+
if (code === 'unknown' || code === 'ok') {
|
|
71
|
+
return 'indeterminate';
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
function httpEvidence(value) {
|
|
76
|
+
if (typeof value !== 'number' || !Number.isInteger(value) || value < 400 || value > 599) {
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
return TRANSIENT_HTTP.has(value) ? 'transient' : 'permanent';
|
|
80
|
+
}
|
|
81
|
+
function httpMessageEvidence(message) {
|
|
82
|
+
let hasTransient = false;
|
|
83
|
+
for (const match of message.matchAll(/(?:\bhttp(?:\s+status)?|\bstatus)(?:\s+code)?\s*:?\s*(\d{3})\b/g)) {
|
|
84
|
+
const evidence = httpEvidence(Number(match[1]));
|
|
85
|
+
if (evidence === 'permanent') {
|
|
86
|
+
return 'permanent';
|
|
87
|
+
}
|
|
88
|
+
hasTransient ||= evidence === 'transient';
|
|
89
|
+
}
|
|
90
|
+
return hasTransient ? 'transient' : undefined;
|
|
91
|
+
}
|
|
92
|
+
function grpcMessageEvidence(message) {
|
|
93
|
+
const normalized = message.replaceAll(/[^a-z0-9]/g, '');
|
|
94
|
+
let hasTransient = false;
|
|
95
|
+
for (const { token, evidence } of GRPC_MESSAGE_TOKENS) {
|
|
96
|
+
if (normalized.includes(token)) {
|
|
97
|
+
if (evidence === 'permanent') {
|
|
98
|
+
return 'permanent';
|
|
99
|
+
}
|
|
100
|
+
hasTransient ||= evidence === 'transient';
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return hasTransient ? 'transient' : undefined;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Last-resort transient wording, consulted only when the whole chain carried
|
|
107
|
+
* no status-level evidence. Guarded by the negative classification fixtures
|
|
108
|
+
* (server rejections must never match) — extend with care.
|
|
109
|
+
*/
|
|
110
|
+
function flattenedTransient(message) {
|
|
111
|
+
return [
|
|
112
|
+
'cancelled',
|
|
113
|
+
'canceled',
|
|
114
|
+
'deadline exceeded',
|
|
115
|
+
'timeout',
|
|
116
|
+
'unavailable',
|
|
117
|
+
'resource exhausted',
|
|
118
|
+
'request timeout',
|
|
119
|
+
'too many requests',
|
|
120
|
+
'rate limited',
|
|
121
|
+
'rate limit',
|
|
122
|
+
'bad gateway',
|
|
123
|
+
'service unavailable',
|
|
124
|
+
'gateway timeout',
|
|
125
|
+
'i/o timeout',
|
|
126
|
+
'io timeout',
|
|
127
|
+
'connection reset',
|
|
128
|
+
'broken pipe',
|
|
129
|
+
].some((signal) => message.includes(signal));
|
|
130
|
+
}
|
|
131
|
+
function asRecord(value) {
|
|
132
|
+
return typeof value === 'object' && value !== null ? value : undefined;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Walks the error's cause chain and reports whether every piece of evidence
|
|
136
|
+
* points at a transient failure. `extraTransientSignals` extends the
|
|
137
|
+
* transient-wording fallback for one policy without leaking into others,
|
|
138
|
+
* under the same permanent-wins rule.
|
|
139
|
+
*/
|
|
140
|
+
export function isTransientError(error, extraTransientSignals = []) {
|
|
141
|
+
const seen = new Set();
|
|
142
|
+
const messages = [];
|
|
143
|
+
let hasTransient = false;
|
|
144
|
+
let hasPermanent = false;
|
|
145
|
+
let current = error;
|
|
146
|
+
const recordMessage = (message) => {
|
|
147
|
+
messages.push(message);
|
|
148
|
+
for (const evidence of [httpMessageEvidence(message), grpcMessageEvidence(message)]) {
|
|
149
|
+
hasTransient ||= evidence === 'transient';
|
|
150
|
+
hasPermanent ||= evidence === 'permanent';
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
while (current !== undefined && current !== null) {
|
|
154
|
+
const record = asRecord(current);
|
|
155
|
+
if (record !== undefined) {
|
|
156
|
+
if (seen.has(record)) {
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
seen.add(record);
|
|
160
|
+
for (const evidence of [
|
|
161
|
+
grpcEvidence(record.code),
|
|
162
|
+
httpEvidence(record.status),
|
|
163
|
+
httpEvidence(record.statusCode),
|
|
164
|
+
]) {
|
|
165
|
+
hasTransient ||= evidence === 'transient';
|
|
166
|
+
hasPermanent ||= evidence === 'permanent';
|
|
167
|
+
}
|
|
168
|
+
recordMessage(typeof record.message === 'string'
|
|
169
|
+
? record.message.toLowerCase()
|
|
170
|
+
: String(current).toLowerCase());
|
|
171
|
+
current = record.cause;
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
recordMessage(String(current).toLowerCase());
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (hasPermanent) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
if (hasTransient) {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
return messages.some((message) => flattenedTransient(message) ||
|
|
185
|
+
extraTransientSignals.some((signal) => message.includes(signal)));
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=classify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/retry/classify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface RetryRuntime {
|
|
2
|
+
sleep(delayMs: number): Promise<void>;
|
|
3
|
+
unitRandom(): number;
|
|
4
|
+
}
|
|
5
|
+
export declare const productionRetryRuntime: RetryRuntime;
|
|
6
|
+
export declare function retryDelay(retryIndex: number, unitRandom: number): number;
|
|
7
|
+
/**
|
|
8
|
+
* Runs `operation` under an attempt budget: the budget is consulted before
|
|
9
|
+
* the error is classified, transient failures back off with `retryDelay`,
|
|
10
|
+
* and permanent failures or the final attempt rethrow the error unchanged.
|
|
11
|
+
*/
|
|
12
|
+
export declare function retryTransient<T>(operation: () => Promise<T>, maxAttempts: number, isTransient: (error: unknown) => boolean, runtime: RetryRuntime): Promise<T>;
|
|
13
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/retry/runtime.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,UAAU,IAAI,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,sBAAsB,EAAE,YAGpC,CAAC;AAEF,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAMzE;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,CAAC,EACpC,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,EACxC,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,CAAC,CAAC,CAaZ"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const BASE_DELAY_MS = 500;
|
|
2
|
+
const MAX_DELAY_MS = 8_000;
|
|
3
|
+
export const productionRetryRuntime = {
|
|
4
|
+
sleep: (delayMs) => new Promise((resolve) => setTimeout(resolve, delayMs)),
|
|
5
|
+
unitRandom: () => Math.random(),
|
|
6
|
+
};
|
|
7
|
+
export function retryDelay(retryIndex, unitRandom) {
|
|
8
|
+
const exponent = Math.min(retryIndex, 1023);
|
|
9
|
+
const raw = BASE_DELAY_MS * 2 ** exponent;
|
|
10
|
+
const finiteRandom = Number.isFinite(unitRandom) ? unitRandom : 0.5;
|
|
11
|
+
const boundedRandom = Math.min(Math.max(finiteRandom, 0), 1 - Number.EPSILON);
|
|
12
|
+
return Math.min(Math.floor(raw * (0.75 + boundedRandom * 0.5)), MAX_DELAY_MS);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Runs `operation` under an attempt budget: the budget is consulted before
|
|
16
|
+
* the error is classified, transient failures back off with `retryDelay`,
|
|
17
|
+
* and permanent failures or the final attempt rethrow the error unchanged.
|
|
18
|
+
*/
|
|
19
|
+
export async function retryTransient(operation, maxAttempts, isTransient, runtime) {
|
|
20
|
+
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
21
|
+
try {
|
|
22
|
+
return await operation();
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (attempt + 1 >= maxAttempts || !isTransient(error)) {
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
await runtime.sleep(retryDelay(attempt, runtime.unitRandom()));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
throw new Error('unreachable retry state');
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=runtime.js.map
|