Skip to content

Commit

Permalink
refactor(time-helper): optionally durable
Browse files Browse the repository at this point in the history
  • Loading branch information
0xpatrickdev committed Jun 21, 2024
1 parent 92292e7 commit ca5d087
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 40 deletions.
17 changes: 10 additions & 7 deletions packages/orchestration/src/examples/stakeBld.contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { prepareRecorderKitMakers } from '@agoric/zoe/src/contractSupport/record
import { withdrawFromSeat } from '@agoric/zoe/src/contractSupport/zoeHelpers.js';
import { InvitationShape } from '@agoric/zoe/src/typeGuards.js';
import { makeDurableZone } from '@agoric/zone/durable.js';
import { makeHeapZone } from '@agoric/zone';
import { prepareVowTools, V } from '@agoric/vow/vat.js';
import { E } from '@endo/far';
import { deeplyFulfilled } from '@endo/marshal';
Expand Down Expand Up @@ -36,21 +37,23 @@ const trace = makeTracer('StakeBld');
*/
export const start = async (zcf, privateArgs, baggage) => {
const zone = makeDurableZone(baggage);
const { agoricNames, marshaller, timerService } = privateArgs;

const { makeRecorderKit } = prepareRecorderKitMakers(
baggage,
privateArgs.marshaller,
);
const { makeRecorderKit } = prepareRecorderKitMakers(baggage, marshaller);
const vowTools = prepareVowTools(zone.subZone('vows'));
const timeHelper = makeTimeHelper(makeHeapZone(), {
timerService,
vowTools,
});

const makeLocalOrchestrationAccountKit = prepareLocalOrchestrationAccountKit(
zone,
makeRecorderKit,
zcf,
privateArgs.timerService,
timerService,
vowTools,
makeChainHub(privateArgs.agoricNames),
makeTimeHelper(privateArgs.timerService),
makeChainHub(agoricNames),
timeHelper,
);

// ----------------
Expand Down
63 changes: 38 additions & 25 deletions packages/orchestration/src/exos/time-helper.js
Original file line number Diff line number Diff line change
@@ -1,46 +1,54 @@
import { RelativeTimeRecordShape, TimeMath } from '@agoric/time';
import { VowShape } from '@agoric/vow';
import { watch, allVows } from '@agoric/vow/vat.js';
import { makeHeapZone } from '@agoric/zone';
import { E } from '@endo/far';
import { E, Far } from '@endo/far';
import { M } from '@endo/patterns';

/**
* @import {Remote} from '@agoric/internal';*
* @import {RelativeTimeRecord, TimerBrand, TimerService, TimestampRecord} from '@agoric/time';
* @import {Vow} from '@agoric/vow';
* @import {Vow, VowTools} from '@agoric/vow';
* @import {Zone} from '@agoric/zone';
*/

export const SECONDS_PER_MINUTE = 60n;
export const NANOSECONDS_PER_SECOND = 1_000_000_000n;

/**
* @param {Remote<TimerService>} timerService
* @param {Zone} [zone]
* @param {Zone} zone
* @param {{ timerService: Remote<TimerService>; vowTools: VowTools }} powers
*/

export const makeTimeHelper = (timerService, zone = makeHeapZone()) => {
/** @type {TimerBrand | undefined} */
let brandCache;
const getBrand = () => {
if (brandCache) return brandCache;
return watch(E(timerService).getTimerBrand(), {
onFulfilled: timerBrand => {
brandCache = timerBrand;
return timerBrand;
},
});
};

return zone.exo(
export const makeTimeHelper = (
zone,
{ timerService, vowTools: { watch, allVows } },
) => {
const timeHelper = zone.exoClass(
'Time Helper',
M.interface('TimeHelperI', {
getTimeoutTimestampNS: M.call()
.optional(RelativeTimeRecordShape)
.returns(VowShape),
getBrand: M.call().returns(VowShape),
}),
() =>
/** @type {{ brandCache: TimerBrand | undefined }} */ ({
brandCache: undefined,
}),
{
/** @returns {Vow<TimerBrand>} */
getBrand() {
// XXX this is a common use case that should have a helper like `provideSingleton`
if (this.state.brandCache) return watch(this.state.brandCache);
return watch(
E(timerService).getTimerBrand(),
Far('BrandWatcher', {
/** @param {TimerBrand} timerBrand */
onFulfilled: timerBrand => {
this.state.brandCache = timerBrand;
return timerBrand;
},
}),
);
},
/**
* Takes the current time from ChainTimerService and adds a relative time
* to determine a timeout timestamp in nanoseconds. Useful for
Expand All @@ -52,8 +60,11 @@ export const makeTimeHelper = (timerService, zone = makeHeapZone()) => {
*/
getTimeoutTimestampNS(relativeTime) {
return watch(
allVows([E(timerService).getCurrentTimestamp(), getBrand()]),
{
allVows([
E(timerService).getCurrentTimestamp(),
this.self.getBrand(),
]),
Far('TimestampWatcher', {
/** @param {[TimestampRecord, TimerBrand]} results */
onFulfilled([currentTime, timerBrand]) {
const timeout =
Expand All @@ -67,11 +78,13 @@ export const makeTimeHelper = (timerService, zone = makeHeapZone()) => {
NANOSECONDS_PER_SECOND
);
},
},
}),
);
},
},
);
return timeHelper();
};
harden(makeTimeHelper);

/** @typedef {Awaited<ReturnType<typeof makeTimeHelper>>} TimeHelper */
/** @typedef {ReturnType<typeof makeTimeHelper>} TimeHelper */
11 changes: 8 additions & 3 deletions packages/orchestration/src/utils/start-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { prepareAsyncFlowTools } from '@agoric/async-flow';
import { prepareVowTools } from '@agoric/vow';
import { prepareRecorderKitMakers } from '@agoric/zoe/src/contractSupport/recorder.js';
import { makeDurableZone } from '@agoric/zone/durable.js';
import { makeHeapZone } from '@agoric/zone';
import { prepareLocalOrchestrationAccountKit } from '../exos/local-orchestration-account.js';
import { makeOrchestrationFacade } from '../facade.js';
import { makeChainHub } from '../exos/chain-hub.js';
Expand Down Expand Up @@ -46,11 +47,15 @@ export const provideOrchestration = (
marshaller,
) => {
const zone = makeDurableZone(baggage);
const vowTools = prepareVowTools(zone.subZone('vows'));

const chainHub = makeChainHub(remotePowers.agoricNames);
const timeHelper = makeTimeHelper(remotePowers.timerService);
const { agoricNames, timerService } = remotePowers;

const vowTools = prepareVowTools(zone.subZone('vows'));
const chainHub = makeChainHub(agoricNames);
const timeHelper = makeTimeHelper(makeHeapZone(), {
timerService,
vowTools,
});

const { makeRecorderKit } = prepareRecorderKitMakers(baggage, marshaller);
const makeLocalOrchestrationAccountKit = prepareLocalOrchestrationAccountKit(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { AmountMath } from '@agoric/ertp';
import { eventLoopIteration } from '@agoric/internal/src/testing-utils.js';
import { V as E } from '@agoric/vow/vat.js';
import { prepareRecorderKitMakers } from '@agoric/zoe/src/contractSupport/recorder.js';
import { makeHeapZone } from '@agoric/zone';
import { Far } from '@endo/far';
import { prepareLocalOrchestrationAccountKit } from '../../src/exos/local-orchestration-account.js';
import { ChainAddress } from '../../src/orchestration-api.js';
Expand Down Expand Up @@ -37,7 +38,7 @@ test('deposit, withdraw', async t => {
timer,
vowTools,
makeChainHub(bootstrap.agoricNames),
makeTimeHelper(timer),
makeTimeHelper(makeHeapZone(), { timerService: timer, vowTools }),
);

t.log('request account from vat-localchain');
Expand Down Expand Up @@ -109,7 +110,7 @@ test('delegate, undelegate', async t => {
timer,
vowTools,
makeChainHub(bootstrap.agoricNames),
makeTimeHelper(timer),
makeTimeHelper(makeHeapZone(), { timerService: timer, vowTools }),
);

t.log('request account from vat-localchain');
Expand Down Expand Up @@ -162,7 +163,7 @@ test('transfer', async t => {
timer,
vowTools,
makeChainHub(bootstrap.agoricNames),
makeTimeHelper(timer),
makeTimeHelper(makeHeapZone(), { timerService: timer, vowTools }),
);

t.log('request account from vat-localchain');
Expand Down
14 changes: 12 additions & 2 deletions packages/orchestration/test/exos/time-helper.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/* eslint-disable @jessie.js/safe-await-separator */
import { test } from '@agoric/zoe/tools/prepare-test-env-ava.js';
import { V } from '@agoric/vow/vat.js';
import { prepareVowTools, V } from '@agoric/vow/vat.js';
import { buildZoeManualTimer } from '@agoric/zoe/tools/manualTimer.js';
import { TimeMath } from '@agoric/time';
import { makeHeapZone } from '@agoric/zone';
import {
makeTimeHelper,
NANOSECONDS_PER_SECOND,
Expand All @@ -11,15 +12,24 @@ import {

test('makeTimeHelper - getCurrentTimestamp', async t => {
const timer = buildZoeManualTimer(t.log);
const vowTools = prepareVowTools(makeHeapZone());
const timerBrand = timer.getTimerBrand();
t.is(timer.getCurrentTimestamp().absValue, 0n, 'current time is 0n');

const timeHelper = makeTimeHelper(timer);
const timeHelper = makeTimeHelper(makeHeapZone(), {
timerService: timer,
vowTools,
});
t.is(
await V.when(timeHelper.getTimeoutTimestampNS()),
5n * SECONDS_PER_MINUTE * NANOSECONDS_PER_SECOND,
'default timestamp is 5 minutes from current time, in nanoseconds',
);
t.is(
await V.when(timeHelper.getBrand()),
timerBrand,
'brand retrieved cache equals timerBrand',
);

t.is(
await V.when(
Expand Down

0 comments on commit ca5d087

Please sign in to comment.