Skip to content

Commit

Permalink
feat(watchUtils): add asPromise helper
Browse files Browse the repository at this point in the history
Co-authored-by: Michael FIG <mfig@agoric.com>
  • Loading branch information
0xpatrickdev and michaelfig committed Jul 1, 2024
1 parent caaec05 commit bf430a1
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 4 deletions.
7 changes: 6 additions & 1 deletion packages/vow/src/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ export const prepareVowTools = (zone, powers = {}) => {
const makeVowKit = prepareVowKit(zone);
const when = makeWhen(isRetryableReason);
const watch = prepareWatch(zone, makeVowKit, isRetryableReason);
const makeWatchUtils = prepareWatchUtils(zone, watch, makeVowKit);
const makeWatchUtils = prepareWatchUtils(zone, {
watch,
when,
makeVowKit,
isRetryableReason,
});
const watchUtils = makeWatchUtils();
const asVow = makeAsVow(makeVowKit);

Expand Down
38 changes: 35 additions & 3 deletions packages/vow/src/watch-utils.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
// @ts-check

import { M } from '@endo/patterns';
import { PromiseWatcherI } from '@agoric/base-zone';

const { Fail, bare } = assert;

/**
* @import {MapStore} from '@agoric/store/src/types.js'
* @import { Zone } from '@agoric/base-zone'
* @import { Watch } from './watch.js'
* @import { When } from './when.js'
* @import {VowKit} from './types.js'
* @import {IsRetryableReason} from './types.js'
*/

const VowShape = M.tagged(
Expand All @@ -18,21 +23,29 @@ const VowShape = M.tagged(

/**
* @param {Zone} zone
* @param {Watch} watch
* @param {() => VowKit<any>} makeVowKit
* @param {object} powers
* @param {Watch} powers.watch
* @param {When} powers.when
* @param {() => VowKit<any>} powers.makeVowKit
* @param {IsRetryableReason} powers.isRetryableReason
*/
export const prepareWatchUtils = (zone, watch, makeVowKit) => {
export const prepareWatchUtils = (
zone,
{ watch, when, makeVowKit, isRetryableReason },
) => {
const detached = zone.detached();
const makeWatchUtilsKit = zone.exoClassKit(
'WatchUtils',
{
utils: M.interface('Utils', {
all: M.call(M.arrayOf(M.any())).returns(VowShape),
asPromise: M.call(M.raw()).rest(M.raw()).returns(M.promise()),
}),
watcher: M.interface('Watcher', {
onFulfilled: M.call(M.any()).rest(M.any()).returns(M.any()),
onRejected: M.call(M.any()).rest(M.any()).returns(M.any()),
}),
retryRejectionPromiseWatcher: PromiseWatcherI,
},
() => {
/**
Expand Down Expand Up @@ -83,6 +96,17 @@ export const prepareWatchUtils = (zone, watch, makeVowKit) => {
}
return kit.vow;
},
asPromise(specimenP, ...watcherArgs) {
// Watch the specimen in case it is an ephemeral promise.
const vow = watch(specimenP, ...watcherArgs);
const promise = when(vow);
// Watch the ephemeral result promise to ensure that if its settlement is
// lost due to upgrade of this incarnation, we will at least cause an
// unhandled rejection in the new incarnation.
zone.watchPromise(promise, this.facets.retryRejectionPromiseWatcher);

return promise;
},
},
watcher: {
onFulfilled(value, { id, index }) {
Expand Down Expand Up @@ -122,6 +146,14 @@ export const prepareWatchUtils = (zone, watch, makeVowKit) => {
resolver.reject(value);
},
},
retryRejectionPromiseWatcher: {
onFulfilled(_result) {},
onRejected(reason, failedOp) {
if (isRetryableReason(reason, undefined)) {
Fail`Pending ${bare(failedOp)} could not retry; {reason}`;
}
},
},
},
);

Expand Down

0 comments on commit bf430a1

Please sign in to comment.