Timer Services
TimerService objects
home
has two timer service objects:
localTimerService
is from the local vat with units of 1 millisecond.chainTimerService
is from the chain (if present) with units of 1 second.
In general, you should use the chain timer for contracts. But it's more efficient to use the local timer for objects that don't need consensus or consistency. For example, people might want it for testing.
Both timer services let you:
- Schedule
wake()
calls. - Remove scheduled
wake()
calls. - Create a repeater for scheduling of events at regular intervals.
The local service lets you get a monotonically increasing timestamp for each instance of the local chain. The chain service lets you get the start time of the current block.
Both timer services present an identical API, but apply a different interpretation to the following data types.
Timestamp
A BigInt
representing an absolute instant in time in a TimerService
, using units and a basis dependent upon the service.
RelativeTime
A BigInt
representing the difference between two Timestamp
s of the same TimerService
.
TimerService methods
The following methods provide basic TimerService functionality.
E(home.<chain or local>TimerService).getCurrentTimestamp()
- Returns:
{ Promise<Timestamp> }
Returns a promise that resolves with the current timestamp.
command[1] E(home.chainTimerService).getCurrentTimestamp()
history[1] 1632170301n // in seconds since epoch
command[2] E(home.localTimerService).getCurrentTimestamp()
history[2] 1632170301546n // in milliseconds since epoch
A chain block might be executed more than once in case of restart or replay or cross-verification, but each such execution will receive the same input state and observe the same response, even if running a minute or a month later.
E(home.<chain or local>TimerService).delay(delay)
delay
{ RelativeTime }
- Returns:
{ Promise<Timestamp> }
Returns a promise that resolves with the current timestamp after the delay
has elapsed.
command[3] E(home.localTimerService).delay(3_000n)
history[3] unresolved Promise
history[3] 1632170321864n // about 3 seconds later, in milliseconds since epoch
E(home.<chain or local>TimerService).makeNotifier(delay, interval)
delay
{ RelativeTime }
interval
{ RelativeTime }
- Returns:
{ Promise<Notifier<Timestamp>> }
Creates a Notifier
object and returns a promise that resolves with it. The notifier repeatedly delivers updates at times that are a multiple of the specified interval
, with the first update happening after the specified delay
has elapsed.
command[4] E(home.localTimerService).makeNotifier(5_000n, 10_000n)
history[4] [Alleged: presence o-129]{}
command[5] E(history[4]).getUpdateSince()
history[5] {"updateCount":1,"value":1632163863000n}
Advanced TimerService objects
These are more complex objects that are only used for the following advanced methods.
TimerWaker
object
A TimerWaker
has one method, wake()
wake(timestamp)
timestamp
{ Timestamp }
- Returns
{ void }
- The provided
timestamp
is the time for which the call towake()
was scheduled.
TimerRepeater
object
A TimerRepeater
has an associated interval and two methods, schedule()
and disable()
:
schedule(waker)
waker
{ TimerWaker }
- Returns
{ Timestamp }
- The
waker
argument is any object with awake()
method. Returns the time indicating the time the waker is next scheduled to be called. The waker continues to be scheduled every interval until the repeater is disabled.
disable()
- Returns
{ void }
- Disables this repeater, so
schedule()
can't be called again and wakers already scheduled with this repeater won't be rescheduled after they are called.
- Returns
Advanced TimerService methods
E(home.<chain or local>TimerService).setWakeup(baseTime, waker)
baseTime
{ Timestamp }
waker
{ TimerWaker }
- Returns:
{ Promise<Timestamp> }
Calls the specified waker
when the current timestamp is at least baseTime
. NOTE: baseTime
is an absolute, not relative time.
Returns a promise that resolves with the time at which the call is scheduled to happen.
command[3] handler = harden({ wake: now => { console.log(`woke up ${now}`); }})
history[3] {"wake":[Function wake]}
command[4] willWakeAt = E(home.localTimerService).setWakeup(1632170399207n + 3_000n, handler)
history[4] 1632170402207n
// Written to console a few seconds later
woke up 1632170402207n
E(home.<chain or local>TimerService).removeWakeup(waker)
waker
{ TimerWaker }
- Returns:
{ Promise<Array[Timestamp]> }
Cancels all scheduled wakeups of the specified waker
, whether created by setWakeup()
or repeater.schedule()
.
Returns a promise for an array of Timestamps representing when the cancelled wakeup calls were scheduled to happen.
command[5] timeList = E(home.localTimerService).removeWakeup(handler)
history[5] unresolved Promise
E(home.<chain or local>TimerService).makeRepeater(delay, interval)
delay
:{ RelativeTime }
interval
:{ RelativeTime }
- Returns:
{ Promise<Repeater> }
Creates a Repeater
object and returns a promise that resolves with it. The repeater schedules wake()
calls repeatedly at times that are a multiple of the specified interval
, with the first update happening after the specified delay
has elapsed. Since block times are coarse-grained, the actual calls when using chainTimerService
may occur less frequently than the specified interval
.
command[6] E(home.localTimerService).makeRepeater(5_000n, 10_000n)
history[6] [Alleged: presence o-124]{}
A longer example of creating and using Repeaters:
command[3] makeWakeCounter = () => {
let count = 0;
return Far('counter', { getCount() { return count; }, wake(_t) { count += 1; }, });
}
history[3] [Function makeWakeCounter]
command[4] c1 = makeWakeCounter()
history[4] [Object Alleged: counter]{"getCount":[Function getCount],"wake":[Function wake]}
command[5] c2 = makeWakeCounter()
history[5] [Object Alleged: counter]{"getCount":[Function getCount],"wake":[Function wake]}
command[6] tl = home.localTimerService
history[6] [Object Alleged: timerService]{}
command[7] tc = home.chainTimerService
history[7] [Object Alleged: timerService]{}
command[8] rl = E(tl).makeRepeater(7n, 1500n)
history[8] [Object Alleged: vatRepeater]{}
command[9] rc = E(tc).makeRepeater(7n, 15n)
history[9] [Object Alleged: vatRepeater]{}
command[10] E(rl).schedule(c1)
history[10] 1571783040007n
command[11] E(rc).schedule(c2)
history[11] 1571783051n
...
command[22] E(tl).getCurrentTimestamp().then(t => [t, c1.getCount()])
history[22] [1571783069041n,20]
command[23] E(tc).getCurrentTimestamp().then(t => [t, c2.getCount()])
history[23] [1571783070n,2]