@agoric/vow 0.1.1-dev-442f07c.0 → 0.1.1-dev-69f8e4b.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 +2 -2
- package/package.json +7 -7
- package/src/retryable.d.ts +75 -0
- package/src/retryable.d.ts.map +1 -0
- package/src/retryable.js +224 -0
- package/src/tools.d.ts.map +1 -1
- package/src/tools.js +7 -20
- package/src/types.d.ts +19 -1
- package/src/types.d.ts.map +1 -1
- package/src/types.ts +26 -7
- package/src/vow-utils.js +1 -1
- package/vat.js +10 -2
package/README.md
CHANGED
|
@@ -150,8 +150,8 @@ Here is an (oversimplified) algorithm that `watch` and `when` use to obtain a
|
|
|
150
150
|
final result:
|
|
151
151
|
|
|
152
152
|
```js
|
|
153
|
-
// Directly await the non-
|
|
154
|
-
// This is non-
|
|
153
|
+
// Directly await the non-retryable original specimen.
|
|
154
|
+
// This is non-retryable because we don't know how our caller obtained
|
|
155
155
|
// it in the first place, since it is an application-specific detail
|
|
156
156
|
// that may not be side-effect free.
|
|
157
157
|
let result = await specimenP;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/vow",
|
|
3
|
-
"version": "0.1.1-dev-
|
|
3
|
+
"version": "0.1.1-dev-69f8e4b.0+69f8e4b",
|
|
4
4
|
"description": "Remote (shortening and disconnection-tolerant) Promise-likes",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"lint:types": "tsc"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@agoric/base-zone": "0.1.1-dev-
|
|
23
|
-
"@agoric/internal": "0.3.3-dev-
|
|
22
|
+
"@agoric/base-zone": "0.1.1-dev-69f8e4b.0+69f8e4b",
|
|
23
|
+
"@agoric/internal": "0.3.3-dev-69f8e4b.0+69f8e4b",
|
|
24
24
|
"@endo/env-options": "^1.1.6",
|
|
25
25
|
"@endo/errors": "^1.2.5",
|
|
26
26
|
"@endo/eventual-send": "^1.2.5",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@agoric/internal": "^0.3.2",
|
|
33
|
-
"@agoric/swingset-vat": "0.32.3-dev-
|
|
34
|
-
"@agoric/zone": "0.2.3-dev-
|
|
33
|
+
"@agoric/swingset-vat": "0.32.3-dev-69f8e4b.0+69f8e4b",
|
|
34
|
+
"@agoric/zone": "0.2.3-dev-69f8e4b.0+69f8e4b",
|
|
35
35
|
"@endo/far": "^1.1.5",
|
|
36
36
|
"@endo/init": "^1.1.4",
|
|
37
37
|
"ava": "^5.3.0",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"access": "public"
|
|
56
56
|
},
|
|
57
57
|
"typeCoverage": {
|
|
58
|
-
"atLeast":
|
|
58
|
+
"atLeast": 91.85
|
|
59
59
|
},
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "69f8e4b5e04b66df5400716251e66fbce468c86e"
|
|
61
61
|
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
export function prepareRetryableTools(outerZone: Zone, outerOptions: PreparationOptions): {
|
|
2
|
+
prepareRetryableFlowKit: (zone: Zone, tag: string, retryableFunc: RetryableFunc) => (activationArgs: any) => import("@endo/exo").GuardedKit<{
|
|
3
|
+
flow: {
|
|
4
|
+
/**
|
|
5
|
+
* Calls the retryable function, either for the initial run or when
|
|
6
|
+
* the result of the previous run fails with a retryable reason.
|
|
7
|
+
*/
|
|
8
|
+
restart(): void;
|
|
9
|
+
getOutcome(): Vow<any>;
|
|
10
|
+
};
|
|
11
|
+
resultWatcher: {
|
|
12
|
+
onFulfilled(value: any, runId: any): void;
|
|
13
|
+
onRejected(reason: any, runId: any): void;
|
|
14
|
+
};
|
|
15
|
+
}>;
|
|
16
|
+
adminRetryableFlow: import("@endo/exo").Guarded<{
|
|
17
|
+
/**
|
|
18
|
+
* @param {Vow} outcomeVow
|
|
19
|
+
*/
|
|
20
|
+
getFlowForOutcomeVow(outcomeVow: Vow): import("@endo/exo").Guarded<{
|
|
21
|
+
/**
|
|
22
|
+
* Calls the retryable function, either for the initial run or when
|
|
23
|
+
* the result of the previous run fails with a retryable reason.
|
|
24
|
+
*/
|
|
25
|
+
restart(): void;
|
|
26
|
+
getOutcome(): Vow<any>;
|
|
27
|
+
}>;
|
|
28
|
+
}>;
|
|
29
|
+
retryable: import("./types.js").RetryableTool;
|
|
30
|
+
};
|
|
31
|
+
export type PreparationOptions = {
|
|
32
|
+
makeVowKit: () => VowKit<any>;
|
|
33
|
+
isRetryableReason: IsRetryableReason;
|
|
34
|
+
};
|
|
35
|
+
export type RetryableFunc = (...args: Passable[]) => Promise<any>;
|
|
36
|
+
export type RetryableTools = ReturnType<(outerZone: Zone, outerOptions: PreparationOptions) => {
|
|
37
|
+
prepareRetryableFlowKit: (zone: Zone, tag: string, retryableFunc: RetryableFunc) => (activationArgs: any) => import("@endo/exo").GuardedKit<{
|
|
38
|
+
flow: {
|
|
39
|
+
/**
|
|
40
|
+
* Calls the retryable function, either for the initial run or when
|
|
41
|
+
* the result of the previous run fails with a retryable reason.
|
|
42
|
+
*/
|
|
43
|
+
restart(): void;
|
|
44
|
+
getOutcome(): Vow<any>;
|
|
45
|
+
};
|
|
46
|
+
resultWatcher: {
|
|
47
|
+
onFulfilled(value: any, runId: any): void;
|
|
48
|
+
onRejected(reason: any, runId: any): void;
|
|
49
|
+
};
|
|
50
|
+
}>;
|
|
51
|
+
adminRetryableFlow: import("@endo/exo").Guarded<{
|
|
52
|
+
/**
|
|
53
|
+
* @param {Vow} outcomeVow
|
|
54
|
+
*/
|
|
55
|
+
getFlowForOutcomeVow(outcomeVow: Vow): import("@endo/exo").Guarded<{
|
|
56
|
+
/**
|
|
57
|
+
* Calls the retryable function, either for the initial run or when
|
|
58
|
+
* the result of the previous run fails with a retryable reason.
|
|
59
|
+
*/
|
|
60
|
+
restart(): void;
|
|
61
|
+
getOutcome(): Vow<any>;
|
|
62
|
+
}>;
|
|
63
|
+
}>;
|
|
64
|
+
retryable: import("./types.js").RetryableTool;
|
|
65
|
+
}>;
|
|
66
|
+
export type AdminRetryableFlow = RetryableTools["adminRetryableFlow"];
|
|
67
|
+
export type MakeRetryableFlowKit = ReturnType<RetryableTools["prepareRetryableFlowKit"]>;
|
|
68
|
+
export type RetryableFlowKit = ReturnType<MakeRetryableFlowKit>;
|
|
69
|
+
export type RetryableFlow = RetryableFlowKit["flow"];
|
|
70
|
+
import type { Zone } from '@agoric/base-zone';
|
|
71
|
+
import type { Vow } from './types.js';
|
|
72
|
+
import type { VowKit } from './types.js';
|
|
73
|
+
import type { IsRetryableReason } from './types.js';
|
|
74
|
+
import type { Passable } from '@endo/pass-style';
|
|
75
|
+
//# sourceMappingURL=retryable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retryable.d.ts","sourceRoot":"","sources":["retryable.js"],"names":[],"mappings":"AAwCO,iDAHI,IAAI,gBACJ,kBAAkB;oCAoBhB,IAAI,OACJ,MAAM,iBACN,aAAa;;YAsBhB;;;eAGG;;;;;;;;;;QAuGP;;WAEG;yCADQ,GAAG;YA3GV;;;eAGG;;;;;;EAqHZ;;gBA5La,MAAM,OAAO,GAAG,CAAC;uBACjB,iBAAiB;;4BAIlB,CAAC,GAAG,IAAI,EAAE,QAAQ,EAAE,KAAK,OAAO,CAAC,GAAG,CAAC;6BA2LrC,UAAU,aAzKZ,IAAI,gBACJ,kBAAkB;oCAoBhB,IAAI,OACJ,MAAM,iBACN,aAAa;;YAsBhB;;;eAGG;;;;;;;;;;QAuGP;;WAEG;yCADQ,GAAG;YA3GV;;;eAGG;;;;;;EAyHiC;iCAIjC,cAAc,CAAC,oBAAoB,CAAC;mCAIpC,UAAU,CAAC,cAAc,CAAC,yBAAyB,CAAC,CAAC;+BAIrD,UAAU,CAAC,oBAAoB,CAAC;4BAIhC,gBAAgB,CAAC,MAAM,CAAC;0BAvNd,mBAAmB;yBACiB,YAAY;4BAAZ,YAAY;uCAAZ,YAAY;8BAC/B,kBAAkB"}
|
package/src/retryable.js
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { Fail } from '@endo/errors';
|
|
2
|
+
import { M } from '@endo/patterns';
|
|
3
|
+
import { PromiseWatcherI } from '@agoric/base-zone';
|
|
4
|
+
import { makeAsVow, toPassableCap, VowShape } from './vow-utils.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @import {MapStore, WeakMapStore} from '@agoric/store'
|
|
8
|
+
* @import {Zone} from '@agoric/base-zone'
|
|
9
|
+
* @import {Vow, VowKit, IsRetryableReason, VowTools} from './types.js'
|
|
10
|
+
* @import {Passable, PassableCap} from '@endo/pass-style'
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {object} PreparationOptions
|
|
15
|
+
* @property {() => VowKit<any>} makeVowKit
|
|
16
|
+
* @property {IsRetryableReason} isRetryableReason
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @typedef {(...args: Passable[]) => Promise<any>} RetryableFunc
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
const { defineProperties } = Object;
|
|
24
|
+
|
|
25
|
+
const RetryableFlowIKit = harden({
|
|
26
|
+
flow: M.interface('Flow', {
|
|
27
|
+
restart: M.call().returns(),
|
|
28
|
+
getOutcome: M.call().returns(VowShape),
|
|
29
|
+
}),
|
|
30
|
+
resultWatcher: PromiseWatcherI,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const AdminRetryableFlowI = M.interface('RetryableFlowAdmin', {
|
|
34
|
+
getFlowForOutcomeVow: M.call(VowShape).returns(M.opt(M.remotable('flow'))),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {Zone} outerZone
|
|
39
|
+
* @param {PreparationOptions} outerOptions
|
|
40
|
+
*/
|
|
41
|
+
export const prepareRetryableTools = (outerZone, outerOptions) => {
|
|
42
|
+
const { makeVowKit, isRetryableReason } = outerOptions;
|
|
43
|
+
|
|
44
|
+
const asVow = makeAsVow(makeVowKit);
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* So we can give out wrapper functions easily and recover flow objects
|
|
48
|
+
* for their activations later.
|
|
49
|
+
*/
|
|
50
|
+
const flowForOutcomeVowKey =
|
|
51
|
+
/** @type {MapStore<PassableCap, RetryableFlow>} */ (
|
|
52
|
+
outerZone.mapStore('retryableFlowForOutcomeVow', {
|
|
53
|
+
keyShape: M.remotable('toPassableCap'),
|
|
54
|
+
valueShape: M.remotable('flow'), // isDone === false
|
|
55
|
+
})
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @param {Zone} zone
|
|
60
|
+
* @param {string} tag
|
|
61
|
+
* @param {RetryableFunc} retryableFunc
|
|
62
|
+
*/
|
|
63
|
+
const prepareRetryableFlowKit = (zone, tag, retryableFunc) => {
|
|
64
|
+
typeof retryableFunc === 'function' ||
|
|
65
|
+
Fail`retryableFunc must be a callable function ${retryableFunc}`;
|
|
66
|
+
|
|
67
|
+
const internalMakeRetryableFlowKit = zone.exoClassKit(
|
|
68
|
+
tag,
|
|
69
|
+
RetryableFlowIKit,
|
|
70
|
+
activationArgs => {
|
|
71
|
+
harden(activationArgs);
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
activationArgs, // restarting the retryable function uses the original args
|
|
75
|
+
outcomeKit: makeVowKit(), // outcome of activation as vow
|
|
76
|
+
lastRetryReason: undefined,
|
|
77
|
+
runs: 0n,
|
|
78
|
+
isDone: false, // persistently done
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
flow: {
|
|
83
|
+
/**
|
|
84
|
+
* Calls the retryable function, either for the initial run or when
|
|
85
|
+
* the result of the previous run fails with a retryable reason.
|
|
86
|
+
*/
|
|
87
|
+
restart() {
|
|
88
|
+
const { state, facets } = this;
|
|
89
|
+
const { activationArgs, isDone } = state;
|
|
90
|
+
const { flow, resultWatcher } = facets;
|
|
91
|
+
|
|
92
|
+
!isDone ||
|
|
93
|
+
// separate line so I can set a breakpoint
|
|
94
|
+
Fail`Cannot restart a done retryable flow ${flow}`;
|
|
95
|
+
|
|
96
|
+
const runId = state.runs + 1n;
|
|
97
|
+
state.runs = runId;
|
|
98
|
+
|
|
99
|
+
let resultP;
|
|
100
|
+
try {
|
|
101
|
+
resultP = Promise.resolve(retryableFunc(...activationArgs));
|
|
102
|
+
} catch (err) {
|
|
103
|
+
resultP = Promise.reject(err);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
outerZone.watchPromise(harden(resultP), resultWatcher, runId);
|
|
107
|
+
},
|
|
108
|
+
getOutcome() {
|
|
109
|
+
const { state } = this;
|
|
110
|
+
const { outcomeKit } = state;
|
|
111
|
+
return outcomeKit.vow;
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
resultWatcher: {
|
|
115
|
+
onFulfilled(value, runId) {
|
|
116
|
+
const { state } = this;
|
|
117
|
+
const { runs, outcomeKit } = state;
|
|
118
|
+
if (runId !== runs) return;
|
|
119
|
+
!state.isDone ||
|
|
120
|
+
Fail`Cannot resolve a done retryable flow ${this.facets.flow}`;
|
|
121
|
+
outcomeKit.resolver.resolve(value);
|
|
122
|
+
flowForOutcomeVowKey.delete(toPassableCap(outcomeKit.vow));
|
|
123
|
+
state.isDone = true;
|
|
124
|
+
},
|
|
125
|
+
onRejected(reason, runId) {
|
|
126
|
+
const { state } = this;
|
|
127
|
+
const { runs, outcomeKit } = state;
|
|
128
|
+
if (runId !== runs) return;
|
|
129
|
+
!state.isDone ||
|
|
130
|
+
Fail`Cannot reject a done retryable flow ${this.facets.flow}`;
|
|
131
|
+
const retryReason = isRetryableReason(
|
|
132
|
+
reason,
|
|
133
|
+
state.lastRetryReason,
|
|
134
|
+
);
|
|
135
|
+
if (retryReason) {
|
|
136
|
+
state.lastRetryReason = retryReason;
|
|
137
|
+
this.facets.flow.restart();
|
|
138
|
+
} else {
|
|
139
|
+
outcomeKit.resolver.reject(reason);
|
|
140
|
+
flowForOutcomeVowKey.delete(toPassableCap(outcomeKit.vow));
|
|
141
|
+
state.isDone = true;
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
);
|
|
147
|
+
const makeRetryableFlowKit = activationArgs => {
|
|
148
|
+
const retryableKit = internalMakeRetryableFlowKit(activationArgs);
|
|
149
|
+
const { flow } = retryableKit;
|
|
150
|
+
|
|
151
|
+
const vow = flow.getOutcome();
|
|
152
|
+
flowForOutcomeVowKey.init(toPassableCap(vow), flow);
|
|
153
|
+
flow.restart();
|
|
154
|
+
return retryableKit;
|
|
155
|
+
};
|
|
156
|
+
return harden(makeRetryableFlowKit);
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* @type {VowTools['retryable']}
|
|
161
|
+
*/
|
|
162
|
+
const retryable = (zone, tag, retryableFunc) => {
|
|
163
|
+
const makeRetryableKit = prepareRetryableFlowKit(zone, tag, retryableFunc);
|
|
164
|
+
const wrapperFuncName = `${tag}_retryable`;
|
|
165
|
+
|
|
166
|
+
const wrapperFunc = {
|
|
167
|
+
/** @param {any[]} args */
|
|
168
|
+
[wrapperFuncName](...args) {
|
|
169
|
+
// Make sure any error results in a rejected vow
|
|
170
|
+
return asVow(() => {
|
|
171
|
+
zone.isStorable(harden(args)) ||
|
|
172
|
+
Fail`retryable arguments must be storable ${args}`;
|
|
173
|
+
const { flow } = makeRetryableKit(args);
|
|
174
|
+
return flow.getOutcome();
|
|
175
|
+
});
|
|
176
|
+
},
|
|
177
|
+
}[wrapperFuncName];
|
|
178
|
+
defineProperties(wrapperFunc, {
|
|
179
|
+
length: { value: retryableFunc.length },
|
|
180
|
+
});
|
|
181
|
+
// @ts-expect-error inferred generic func
|
|
182
|
+
return harden(wrapperFunc);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const adminRetryableFlow = outerZone.exo(
|
|
186
|
+
'AdminRetryableFlow',
|
|
187
|
+
AdminRetryableFlowI,
|
|
188
|
+
{
|
|
189
|
+
/**
|
|
190
|
+
* @param {Vow} outcomeVow
|
|
191
|
+
*/
|
|
192
|
+
getFlowForOutcomeVow(outcomeVow) {
|
|
193
|
+
return flowForOutcomeVowKey.get(toPassableCap(outcomeVow));
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
return harden({
|
|
199
|
+
prepareRetryableFlowKit,
|
|
200
|
+
adminRetryableFlow,
|
|
201
|
+
retryable,
|
|
202
|
+
});
|
|
203
|
+
};
|
|
204
|
+
harden(prepareRetryableTools);
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* @typedef {ReturnType<prepareRetryableTools>} RetryableTools
|
|
208
|
+
*/
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @typedef {RetryableTools['adminRetryableFlow']} AdminRetryableFlow
|
|
212
|
+
*/
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* @typedef {ReturnType<RetryableTools['prepareRetryableFlowKit']>} MakeRetryableFlowKit
|
|
216
|
+
*/
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* @typedef {ReturnType<MakeRetryableFlowKit>} RetryableFlowKit
|
|
220
|
+
*/
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* @typedef {RetryableFlowKit['flow']} RetryableFlow
|
|
224
|
+
*/
|
package/src/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["tools.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["tools.js"],"names":[],"mappings":"AAuBO,2CALI,IAAI;;gBAGF,QAAQ,CAiEpB;0BA7EsB,mBAAmB;uCAE4B,YAAY;8BAAZ,YAAY"}
|
package/src/tools.js
CHANGED
|
@@ -3,6 +3,7 @@ import { makeAsVow } from './vow-utils.js';
|
|
|
3
3
|
import { prepareVowKit } from './vow.js';
|
|
4
4
|
import { prepareWatchUtils } from './watch-utils.js';
|
|
5
5
|
import { prepareWatch } from './watch.js';
|
|
6
|
+
import { prepareRetryableTools } from './retryable.js';
|
|
6
7
|
import { makeWhen } from './when.js';
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -35,25 +36,10 @@ export const prepareBasicVowTools = (zone, powers = {}) => {
|
|
|
35
36
|
const watchUtils = makeWatchUtils();
|
|
36
37
|
const asVow = makeAsVow(makeVowKit);
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
* Create a function that retries the given function if the underlying
|
|
43
|
-
* functions rejects due to upgrade disconnection.
|
|
44
|
-
*
|
|
45
|
-
* @template {(...args: any[]) => Promise<any>} F
|
|
46
|
-
* @param {Zone} fnZone - the zone for the named function
|
|
47
|
-
* @param {string} name
|
|
48
|
-
* @param {F} fn
|
|
49
|
-
* @returns {F extends (...args: infer Args) => Promise<infer R> ? (...args: Args) => Vow<R> : never}
|
|
50
|
-
*/
|
|
51
|
-
const retriable =
|
|
52
|
-
(fnZone, name, fn) =>
|
|
53
|
-
// @ts-expect-error cast
|
|
54
|
-
(...args) => {
|
|
55
|
-
return watch(fn(...args));
|
|
56
|
-
};
|
|
39
|
+
const { retryable } = prepareRetryableTools(zone, {
|
|
40
|
+
makeVowKit,
|
|
41
|
+
isRetryableReason,
|
|
42
|
+
});
|
|
57
43
|
|
|
58
44
|
/**
|
|
59
45
|
* Vow-tolerant implementation of Promise.all that takes an iterable of vows
|
|
@@ -95,7 +81,8 @@ export const prepareBasicVowTools = (zone, powers = {}) => {
|
|
|
95
81
|
allSettled,
|
|
96
82
|
asVow,
|
|
97
83
|
asPromise,
|
|
98
|
-
|
|
84
|
+
retryable,
|
|
85
|
+
retriable: retryable, // For temporary backwards compat with alpha implementation
|
|
99
86
|
});
|
|
100
87
|
};
|
|
101
88
|
harden(prepareBasicVowTools);
|
package/src/types.d.ts
CHANGED
|
@@ -58,6 +58,20 @@ export type Watcher<T = any, TResult1 = T, TResult2 = never, C extends any[] = a
|
|
|
58
58
|
* Converts a vow or promise to a promise, ensuring proper handling of ephemeral promises.
|
|
59
59
|
*/
|
|
60
60
|
export type AsPromiseFunction<T = any, TResult1 = T, TResult2 = never, C extends any[] = any[]> = (specimenP: ERef<T | Vow<T>>, watcher?: Watcher<T, TResult1, TResult2, C> | undefined, watcherArgs?: C | undefined) => Promise<TResult1 | TResult2>;
|
|
61
|
+
export interface RetryableTool {
|
|
62
|
+
/**
|
|
63
|
+
* Create a function that retries the given function if the underlying
|
|
64
|
+
* async function rejects due to an upgrade disconnection. The return value
|
|
65
|
+
* of the created function is a vow that settles to the final retry result.
|
|
66
|
+
*
|
|
67
|
+
* The retried function should be idempotent.
|
|
68
|
+
*
|
|
69
|
+
* @param fnZone the zone for the named function
|
|
70
|
+
* @param name base name to use in the zone
|
|
71
|
+
* @param fn the retried function
|
|
72
|
+
*/
|
|
73
|
+
<F extends (...args: any[]) => Promise<any>>(fnZone: Zone, name: string, fn: F): F extends (...args: infer Args) => Promise<infer R> ? (...args: Args) => Vow<R> : never;
|
|
74
|
+
}
|
|
61
75
|
export type VowTools = {
|
|
62
76
|
/**
|
|
63
77
|
* Vow-tolerant implementation of Promise.all that takes an iterable of vows
|
|
@@ -93,7 +107,11 @@ export type VowTools = {
|
|
|
93
107
|
*/
|
|
94
108
|
asVow: <T extends unknown>(fn: (...args: any[]) => Vow<Awaited<T>> | Awaited<T> | PromiseVow<T>) => Vow<Awaited<T>>;
|
|
95
109
|
makeVowKit: <T>() => VowKit<T>;
|
|
96
|
-
|
|
110
|
+
retryable: RetryableTool;
|
|
111
|
+
/**
|
|
112
|
+
* @deprecated use `retryable`
|
|
113
|
+
*/
|
|
114
|
+
retriable: RetryableTool;
|
|
97
115
|
watch: <T = any, TResult1 = T, TResult2 = never, C extends any[] = any[]>(specimenP: EVow<T>, watcher?: Watcher<T, TResult1, TResult2, C> | undefined, ...watcherArgs: C) => Vow<Exclude<TResult1, void> | Exclude<TResult2, void> extends never ? TResult1 : Exclude<TResult1, void> | Exclude<TResult2, void>>;
|
|
98
116
|
/**
|
|
99
117
|
* Shorten `specimenP` until we achieve a final result.
|
package/src/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"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"}
|
package/src/types.ts
CHANGED
|
@@ -100,6 +100,27 @@ export type AsPromiseFunction<
|
|
|
100
100
|
watcherArgs?: C | undefined,
|
|
101
101
|
) => Promise<TResult1 | TResult2>;
|
|
102
102
|
|
|
103
|
+
export interface RetryableTool {
|
|
104
|
+
/**
|
|
105
|
+
* Create a function that retries the given function if the underlying
|
|
106
|
+
* async function rejects due to an upgrade disconnection. The return value
|
|
107
|
+
* of the created function is a vow that settles to the final retry result.
|
|
108
|
+
*
|
|
109
|
+
* The retried function should be idempotent.
|
|
110
|
+
*
|
|
111
|
+
* @param fnZone the zone for the named function
|
|
112
|
+
* @param name base name to use in the zone
|
|
113
|
+
* @param fn the retried function
|
|
114
|
+
*/
|
|
115
|
+
<F extends (...args: any[]) => Promise<any>>(
|
|
116
|
+
fnZone: Zone,
|
|
117
|
+
name: string,
|
|
118
|
+
fn: F,
|
|
119
|
+
): F extends (...args: infer Args) => Promise<infer R>
|
|
120
|
+
? (...args: Args) => Vow<R>
|
|
121
|
+
: never;
|
|
122
|
+
}
|
|
123
|
+
|
|
103
124
|
export type VowTools = {
|
|
104
125
|
/**
|
|
105
126
|
* Vow-tolerant implementation of Promise.all that takes an iterable of vows
|
|
@@ -142,13 +163,11 @@ export type VowTools = {
|
|
|
142
163
|
fn: (...args: any[]) => Vow<Awaited<T>> | Awaited<T> | PromiseVow<T>,
|
|
143
164
|
) => Vow<Awaited<T>>;
|
|
144
165
|
makeVowKit: <T>() => VowKit<T>;
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
? (...args: Args) => Vow<R>
|
|
151
|
-
: never;
|
|
166
|
+
retryable: RetryableTool;
|
|
167
|
+
/**
|
|
168
|
+
* @deprecated use `retryable`
|
|
169
|
+
*/
|
|
170
|
+
retriable: RetryableTool;
|
|
152
171
|
watch: <T = any, TResult1 = T, TResult2 = never, C extends any[] = any[]>(
|
|
153
172
|
specimenP: EVow<T>,
|
|
154
173
|
watcher?: Watcher<T, TResult1, TResult2, C> | undefined,
|
package/src/vow-utils.js
CHANGED
|
@@ -29,7 +29,7 @@ harden(isVow);
|
|
|
29
29
|
/**
|
|
30
30
|
* A vow is a passable tagged as 'Vow'. Its payload is a record with
|
|
31
31
|
* API-versioned remotables. payload.vowV0 is the API for the `watch` and
|
|
32
|
-
* `when` operators to use for
|
|
32
|
+
* `when` operators to use for retryable shortening of the vow chain.
|
|
33
33
|
*
|
|
34
34
|
* If the specimen is a Vow, return its payload, otherwise undefined.
|
|
35
35
|
*
|
package/vat.js
CHANGED
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
/* global globalThis */
|
|
7
7
|
// @ts-check
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
isUpgradeDisconnection,
|
|
10
|
+
isAbandonedError,
|
|
11
|
+
} from '@agoric/internal/src/upgrade-api.js';
|
|
9
12
|
import { makeHeapZone } from '@agoric/base-zone/heap.js';
|
|
10
13
|
|
|
11
14
|
import { prepareBasicVowTools } from './src/tools.js';
|
|
@@ -15,11 +18,16 @@ import makeE from './src/E.js';
|
|
|
15
18
|
const isRetryableReason = (reason, priorRetryValue) => {
|
|
16
19
|
if (
|
|
17
20
|
isUpgradeDisconnection(reason) &&
|
|
18
|
-
(!priorRetryValue ||
|
|
21
|
+
(!isUpgradeDisconnection(priorRetryValue) ||
|
|
19
22
|
reason.incarnationNumber > priorRetryValue.incarnationNumber)
|
|
20
23
|
) {
|
|
21
24
|
return reason;
|
|
22
25
|
}
|
|
26
|
+
// For abandoned errors there is no way to differentiate errors from
|
|
27
|
+
// consecutive upgrades
|
|
28
|
+
if (isAbandonedError(reason) && !isAbandonedError(priorRetryValue)) {
|
|
29
|
+
return reason;
|
|
30
|
+
}
|
|
23
31
|
return undefined;
|
|
24
32
|
};
|
|
25
33
|
|