@agoric/vow 0.1.1-dev-d492653.0 → 0.1.1-dev-4fca040.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/package.json +4 -4
- package/src/tools.d.ts +2 -1
- package/src/tools.d.ts.map +1 -1
- package/src/tools.js +4 -2
- package/src/types.d.ts +4 -0
- package/src/types.d.ts.map +1 -1
- package/src/types.js +10 -0
- package/src/vow.d.ts.map +1 -1
- package/src/vow.js +21 -3
- package/src/watch.d.ts +1 -1
- package/src/watch.d.ts.map +1 -1
- package/src/watch.js +17 -8
- package/src/when.d.ts +2 -1
- package/src/when.d.ts.map +1 -1
- package/src/when.js +21 -10
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-4fca040.0+4fca040",
|
|
4
4
|
"description": "Remote (shortening and disconnection-tolerant) Promise-likes",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"lint:types": "tsc"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@agoric/base-zone": "0.1.1-dev-
|
|
24
|
-
"@agoric/internal": "0.3.3-dev-
|
|
23
|
+
"@agoric/base-zone": "0.1.1-dev-4fca040.0+4fca040",
|
|
24
|
+
"@agoric/internal": "0.3.3-dev-4fca040.0+4fca040",
|
|
25
25
|
"@endo/env-options": "^1.1.4",
|
|
26
26
|
"@endo/eventual-send": "^1.2.2",
|
|
27
27
|
"@endo/pass-style": "^1.4.0",
|
|
@@ -53,5 +53,5 @@
|
|
|
53
53
|
"typeCoverage": {
|
|
54
54
|
"atLeast": 89.6
|
|
55
55
|
},
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "4fca040204f3d45fc85c51b67e84d3ecb02728c8"
|
|
57
57
|
}
|
package/src/tools.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export function prepareVowTools(zone: Zone, powers?: {
|
|
2
|
-
isRetryableReason?:
|
|
2
|
+
isRetryableReason?: IsRetryableReason | undefined;
|
|
3
3
|
} | undefined): {
|
|
4
4
|
when: <T, TResult1 = import("./types.js").Unwrap<T>, TResult2 = never>(specimenP: T, onFulfilled?: ((value: import("./types.js").Unwrap<T>) => TResult1 | PromiseLike<TResult1>) | undefined, onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined) => Promise<TResult1 | TResult2>;
|
|
5
5
|
watch: <T_1 = any, TResult1_1 = T_1, TResult2_1 = never, C = any>(specimenP: import("./types.js").ERef<T_1 | import("./types.js").Vow<T_1>>, watcher?: import("./types.js").Watcher<T_1, TResult1_1, TResult2_1> | undefined, watcherContext?: C | undefined) => import("./types.js").Vow<Exclude<TResult1_1, void> | Exclude<TResult2_1, void> extends never ? TResult1_1 : Exclude<TResult1_1, void> | Exclude<TResult2_1, void>>;
|
|
@@ -7,4 +7,5 @@ export function prepareVowTools(zone: Zone, powers?: {
|
|
|
7
7
|
allVows: (vows: unknown[]) => import("./types.js").Vow<any[]>;
|
|
8
8
|
};
|
|
9
9
|
import type { Zone } from '@agoric/base-zone';
|
|
10
|
+
import type { IsRetryableReason } from './types.js';
|
|
10
11
|
//# sourceMappingURL=tools.d.ts.map
|
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":"AAcO;;;sFACL,CAAF;;;oBAWa,OAAO,EAAE;EAKrB;0BAzBuB,mBAAmB;uCACN,YAAY"}
|
package/src/tools.js
CHANGED
|
@@ -5,14 +5,16 @@ import { prepareWatch } from './watch.js';
|
|
|
5
5
|
import { prepareWatchUtils } from './watch-utils.js';
|
|
6
6
|
|
|
7
7
|
/** @import {Zone} from '@agoric/base-zone' */
|
|
8
|
+
/** @import {IsRetryableReason} from './types.js' */
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* @param {Zone} zone
|
|
11
12
|
* @param {object} [powers]
|
|
12
|
-
* @param {
|
|
13
|
+
* @param {IsRetryableReason} [powers.isRetryableReason]
|
|
13
14
|
*/
|
|
14
15
|
export const prepareVowTools = (zone, powers = {}) => {
|
|
15
|
-
const { isRetryableReason = () => false } =
|
|
16
|
+
const { isRetryableReason = /** @type {IsRetryableReason} */ (() => false) } =
|
|
17
|
+
powers;
|
|
16
18
|
const makeVowKit = prepareVowKit(zone);
|
|
17
19
|
const when = makeWhen(isRetryableReason);
|
|
18
20
|
const watch = prepareWatch(zone, makeVowKit, isRetryableReason);
|
package/src/types.d.ts
CHANGED
package/src/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.js"],"names":[],"mappings":";;;yCAeW,GAAG,mBACH,GAAG,KAED,GAAG;;;;;uBAMa,CAAC,IAAjB,OAAO,CAAS,CAAC,AAAR,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;iBAMH,CAAC,IAAD,CAAC,AAAhB,GAAG,WAAW,CAAC,CAAC,CAAC;;;;;mBAY9B,CAAK;;;;;;;kBAWsB,CAAC;;;;;;;aAAf,MAAM,OAAO,CAAC,CAAC,CAAC;;uBASe,CAAC;;;gBAKJ,CAAC;;;mBAOhB,CAAC,UAFf;IACZ,GAAO,EAAE,GAAG,CACc,CAAC,AADb,CAAC,CAAC;IAChB,QAAY,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;CAC1B;wBAK0C,CAAC;oDAAI,IAAI;oBAAkB,GAAG,GAAG,IAAI;;oBAS7D,CAAC,QAAyD,QAAQ,MAClB,QAAQ,UAD3C,CAAC;2BAAd,CAAC,YAAY,CAAC;2BACb,GAAG;;;iEA1EzB,CAAD;;;oBAcsB,SAAS;;iCAvBO,kBAAkB;oCAHvB,qBAAqB;qCAEpB,kBAAkB;4BACd,kBAAkB"}
|
package/src/types.js
CHANGED
|
@@ -10,6 +10,16 @@ export {};
|
|
|
10
10
|
* @import {prepareVowTools} from './tools.js'
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* @callback IsRetryableReason
|
|
15
|
+
* Return truthy if a rejection reason should result in a retry.
|
|
16
|
+
* @param {any} reason
|
|
17
|
+
* @param {any} priorRetryValue the previous value returned by this function
|
|
18
|
+
* when deciding whether to retry the same logical operation
|
|
19
|
+
* @returns {any} If falsy, the reason is not retryable. If truthy, the
|
|
20
|
+
* priorRetryValue for the next call.
|
|
21
|
+
*/
|
|
22
|
+
|
|
13
23
|
/**
|
|
14
24
|
* @template T
|
|
15
25
|
* @typedef {Promise<T | Vow<T>>} PromiseVow Return type of a function that may
|
package/src/vow.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vow.d.ts","sourceRoot":"","sources":["vow.js"],"names":[],"mappings":"AAuBO,
|
|
1
|
+
{"version":3,"file":"vow.d.ts","sourceRoot":"","sources":["vow.js"],"names":[],"mappings":"AAuBO,4CA8He,CAAC,iBAStB;;0BAtJsB,mBAAmB;4BACJ,YAAY;gCAFrB,mBAAmB"}
|
package/src/vow.js
CHANGED
|
@@ -69,7 +69,9 @@ export const prepareVowKit = zone => {
|
|
|
69
69
|
() => ({
|
|
70
70
|
value: undefined,
|
|
71
71
|
// The stepStatus is null if the promise step hasn't settled yet.
|
|
72
|
-
stepStatus: /** @type {null | 'fulfilled' | 'rejected'} */ (
|
|
72
|
+
stepStatus: /** @type {null | 'pending' | 'fulfilled' | 'rejected'} */ (
|
|
73
|
+
null
|
|
74
|
+
),
|
|
73
75
|
}),
|
|
74
76
|
{
|
|
75
77
|
vowV0: {
|
|
@@ -84,6 +86,7 @@ export const prepareVowKit = zone => {
|
|
|
84
86
|
case 'rejected':
|
|
85
87
|
throw value;
|
|
86
88
|
case null:
|
|
89
|
+
case 'pending':
|
|
87
90
|
return provideCurrentKit(this.facets.resolver).promise;
|
|
88
91
|
default:
|
|
89
92
|
throw new TypeError(`unexpected stepStatus ${stepStatus}`);
|
|
@@ -96,10 +99,17 @@ export const prepareVowKit = zone => {
|
|
|
96
99
|
*/
|
|
97
100
|
resolve(value) {
|
|
98
101
|
const { resolver } = this.facets;
|
|
99
|
-
const {
|
|
102
|
+
const { stepStatus } = this.state;
|
|
103
|
+
const { resolve } = getPromiseKitForResolution(resolver);
|
|
100
104
|
if (resolve) {
|
|
101
105
|
resolve(value);
|
|
102
|
-
|
|
106
|
+
}
|
|
107
|
+
if (stepStatus === null) {
|
|
108
|
+
this.state.stepStatus = 'pending';
|
|
109
|
+
zone.watchPromise(
|
|
110
|
+
HandledPromise.resolve(value),
|
|
111
|
+
this.facets.watchNextStep,
|
|
112
|
+
);
|
|
103
113
|
}
|
|
104
114
|
},
|
|
105
115
|
/**
|
|
@@ -107,15 +117,23 @@ export const prepareVowKit = zone => {
|
|
|
107
117
|
*/
|
|
108
118
|
reject(reason) {
|
|
109
119
|
const { resolver, watchNextStep } = this.facets;
|
|
120
|
+
const { stepStatus } = this.state;
|
|
110
121
|
const { reject } = getPromiseKitForResolution(resolver);
|
|
111
122
|
if (reject) {
|
|
112
123
|
reject(reason);
|
|
124
|
+
}
|
|
125
|
+
if (stepStatus === null) {
|
|
113
126
|
watchNextStep.onRejected(reason);
|
|
114
127
|
}
|
|
115
128
|
},
|
|
116
129
|
},
|
|
117
130
|
watchNextStep: {
|
|
118
131
|
onFulfilled(value) {
|
|
132
|
+
const { resolver } = this.facets;
|
|
133
|
+
const { resolve } = getPromiseKitForResolution(resolver);
|
|
134
|
+
if (resolve) {
|
|
135
|
+
resolve(value);
|
|
136
|
+
}
|
|
119
137
|
this.state.stepStatus = 'fulfilled';
|
|
120
138
|
this.state.value = value;
|
|
121
139
|
},
|
package/src/watch.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export function prepareWatch(zone: Zone, makeVowKit: () => VowKit<any>, isRetryableReason?: ((reason: any) =>
|
|
1
|
+
export function prepareWatch(zone: Zone, makeVowKit: () => VowKit<any>, isRetryableReason?: ((reason: any, lastValue: any) => any) | undefined): <T = any, TResult1 = T, TResult2 = never, C = any>(specimenP: ERef<T | Vow<T>>, watcher?: Watcher<T, TResult1, TResult2> | undefined, watcherContext?: C | undefined) => Vow<Exclude<TResult1, void> | Exclude<TResult2, void> extends never ? TResult1 : Exclude<TResult1, void> | Exclude<TResult2, void>>;
|
|
2
2
|
export type Watch = ReturnType<typeof prepareWatch>;
|
|
3
3
|
import type { Zone } from '@agoric/base-zone';
|
|
4
4
|
import type { VowKit } from './types.js';
|
package/src/watch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["watch.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["watch.js"],"names":[],"mappings":"AAkIO,sGAFa,GAAG,aAAa,GAAG,KAAK,GAAG,iBAmBrB,CAAC,2SA0B1B;oBAIa,UAAU,CAAC,OAAO,YAAY,CAAC;0BA1KJ,mBAAmB;4BACmB,YAAY;yBAAZ,YAAY;0BAAZ,YAAY;6BAAZ,YAAY"}
|
package/src/watch.js
CHANGED
|
@@ -6,7 +6,7 @@ const { apply } = Reflect;
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @import { PromiseWatcher, Zone } from '@agoric/base-zone';
|
|
9
|
-
* @import { ERef, Vow, VowKit, VowResolver, Watcher } from './types.js';
|
|
9
|
+
* @import { ERef, IsRetryableReason, Vow, VowKit, VowResolver, Watcher } from './types.js';
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -62,7 +62,7 @@ const settle = (resolver, watcher, wcb, value, watcherContext) => {
|
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
64
|
* @param {Zone} zone
|
|
65
|
-
* @param {
|
|
65
|
+
* @param {IsRetryableReason} isRetryableReason
|
|
66
66
|
* @param {ReturnType<typeof makeWatchNextStep>} watchNextStep
|
|
67
67
|
*/
|
|
68
68
|
const preparePromiseWatcher = (zone, isRetryableReason, watchNextStep) =>
|
|
@@ -80,6 +80,7 @@ const preparePromiseWatcher = (zone, isRetryableReason, watchNextStep) =>
|
|
|
80
80
|
(resolver, watcher, watcherContext) => {
|
|
81
81
|
const state = {
|
|
82
82
|
vow: /** @type {unknown} */ (undefined),
|
|
83
|
+
priorRetryValue: /** @type {any} */ (undefined),
|
|
83
84
|
resolver,
|
|
84
85
|
watcher,
|
|
85
86
|
watcherContext: harden(watcherContext),
|
|
@@ -96,17 +97,25 @@ const preparePromiseWatcher = (zone, isRetryableReason, watchNextStep) =>
|
|
|
96
97
|
watchNextStep(value, this.self);
|
|
97
98
|
return;
|
|
98
99
|
}
|
|
100
|
+
this.state.priorRetryValue = undefined;
|
|
99
101
|
this.state.watcher = undefined;
|
|
100
102
|
this.state.resolver = undefined;
|
|
101
103
|
settle(resolver, watcher, 'onFulfilled', value, watcherContext);
|
|
102
104
|
},
|
|
103
105
|
/** @type {Required<PromiseWatcher>['onRejected']} */
|
|
104
106
|
onRejected(reason) {
|
|
105
|
-
const { vow, watcher, watcherContext, resolver } =
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
const { vow, watcher, watcherContext, resolver, priorRetryValue } =
|
|
108
|
+
this.state;
|
|
109
|
+
if (vow) {
|
|
110
|
+
const retryValue = isRetryableReason(reason, priorRetryValue);
|
|
111
|
+
if (retryValue) {
|
|
112
|
+
// Retry the same specimen.
|
|
113
|
+
this.state.priorRetryValue = retryValue;
|
|
114
|
+
watchNextStep(vow, this.self);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
109
117
|
}
|
|
118
|
+
this.state.priorRetryValue = undefined;
|
|
110
119
|
this.state.resolver = undefined;
|
|
111
120
|
this.state.watcher = undefined;
|
|
112
121
|
settle(resolver, watcher, 'onRejected', reason, watcherContext);
|
|
@@ -117,12 +126,12 @@ const preparePromiseWatcher = (zone, isRetryableReason, watchNextStep) =>
|
|
|
117
126
|
/**
|
|
118
127
|
* @param {Zone} zone
|
|
119
128
|
* @param {() => VowKit<any>} makeVowKit
|
|
120
|
-
* @param {(reason: any) =>
|
|
129
|
+
* @param {(reason: any, lastValue: any) => any} [isRetryableReason]
|
|
121
130
|
*/
|
|
122
131
|
export const prepareWatch = (
|
|
123
132
|
zone,
|
|
124
133
|
makeVowKit,
|
|
125
|
-
isRetryableReason = _reason =>
|
|
134
|
+
isRetryableReason = (_reason, _lastValue) => undefined,
|
|
126
135
|
) => {
|
|
127
136
|
const watchNextStep = makeWatchNextStep(zone);
|
|
128
137
|
const makePromiseWatcher = preparePromiseWatcher(
|
package/src/when.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export function makeWhen(isRetryableReason?:
|
|
1
|
+
export function makeWhen(isRetryableReason?: IsRetryableReason | undefined): <T, TResult1 = Unwrap<T>, TResult2 = never>(specimenP: T, onFulfilled?: ((value: Unwrap<T>) => TResult1 | PromiseLike<TResult1>) | undefined, onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined) => Promise<TResult1 | TResult2>;
|
|
2
2
|
export type When = ReturnType<typeof makeWhen>;
|
|
3
|
+
import type { IsRetryableReason } from './types.js';
|
|
3
4
|
import type { Unwrap } from './types.js';
|
|
4
5
|
//# sourceMappingURL=when.d.ts.map
|
package/src/when.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"when.d.ts","sourceRoot":"","sources":["when.js"],"names":[],"mappings":"AAQO,
|
|
1
|
+
{"version":3,"file":"when.d.ts","sourceRoot":"","sources":["when.js"],"names":[],"mappings":"AAQO,8EAUqB,CAAC,EAEN,QAAQ,cAAG,QAAQ,qBAFd,CAAC,AADf,uCAGS,QAAQ,AAFY,GAAG,WAAW,CAElC,QAAQ,AAFmC,CAAC,sCAC7C,GAAG,KACS,QAAQ,AADJ,GAAG,WAAW,CAClB,QAAQ,AADmB,CAAC,kBAC/C,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC,CA2C1C;mBAIa,UAAU,CAAC,OAAO,QAAQ,CAAC;uCAhEM,YAAY;4BAAZ,YAAY"}
|
package/src/when.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import { getVowPayload, basicE } from './vow-utils.js';
|
|
3
3
|
|
|
4
|
-
/** @import { Unwrap } from './types.js' */
|
|
4
|
+
/** @import { IsRetryableReason, Unwrap } from './types.js' */
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* @param {
|
|
7
|
+
* @param {IsRetryableReason} [isRetryableReason]
|
|
8
8
|
*/
|
|
9
|
-
export const makeWhen = (
|
|
9
|
+
export const makeWhen = (
|
|
10
|
+
isRetryableReason = /** @type {IsRetryableReason} */ (() => false),
|
|
11
|
+
) => {
|
|
10
12
|
/**
|
|
11
13
|
* Shorten `specimenP` until we achieve a final result.
|
|
12
14
|
*
|
|
@@ -25,16 +27,25 @@ export const makeWhen = (isRetryableReason = () => false) => {
|
|
|
25
27
|
// Ensure we have a presence that won't be disconnected later.
|
|
26
28
|
let result = await specimenP;
|
|
27
29
|
let payload = getVowPayload(result);
|
|
30
|
+
let priorRetryValue;
|
|
28
31
|
while (payload) {
|
|
29
32
|
result = await basicE(payload.vowV0)
|
|
30
33
|
.shorten()
|
|
31
|
-
.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
.then(
|
|
35
|
+
res => {
|
|
36
|
+
priorRetryValue = undefined;
|
|
37
|
+
return res;
|
|
38
|
+
},
|
|
39
|
+
e => {
|
|
40
|
+
const nextValue = isRetryableReason(e, priorRetryValue);
|
|
41
|
+
if (nextValue) {
|
|
42
|
+
// Shorten the same specimen to try again.
|
|
43
|
+
priorRetryValue = nextValue;
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
throw e;
|
|
47
|
+
},
|
|
48
|
+
);
|
|
38
49
|
// Advance to the next vow.
|
|
39
50
|
payload = getVowPayload(result);
|
|
40
51
|
}
|