# Timer Services
# TimerService objects
home has two timer service objects:
localTimerServiceis from the local vat with a resolution of 1ms.chainTimerServiceis from the chain (if present), with a resolution of 1s.
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.
With respect to using them, the only difference between the two timer
services is whether you preface their identical command set with
localTimerService or chainTimerService. However, note that
the local and chain versions of a method may use different time bases.
Before looking at the timer service methods, we need to cover four related objects.
# Timestamp object
An Integer, an absolute individual stamp returned by a TimerService. Note that different
timer services may have different interpretations of actual Timestamp values.
# RelativeTime object
An Integer, the difference between two Timestamps. Note that
different timer services may have different interpretations of actual RelativeTime values.
# TimerService methods
The following methods provide basic TimerService functionality.
# E(home.<chain or local>TimerService).getCurrentTimestamp()
- Returns: A monotonically increasing timestamp for the chain or local ag-solo.
The current block might be executed more than once in case of restart or replay.
But each time it will start from the same state and receive the same inputs.
Since this is repeatable computation, the same computation can be run in various
locations to cross-verify. So each time, the currentTimeStamp will be the same,
even if we're running the computation a minute or a month later. It's expressed
as a Unix epoch time in milliseconds or similar.
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
# 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
relative time has passed.
command[32] E(home.localTimerService).delay(3_000n)
history[32] unresolved Promise
history[32] 1632170321864n // about 3 seconds later, in milliseconds since epoch
# E(home.<chain or local>TimerService).makeNotifier(delay, interval)
delay{ RelativeTime }interval{ RelativeTime }- Returns:
{ Notifier<Timestamp> }
Creates and returns a Notifier object. It repeatedly delivers updates at times
that are a multiple of the passed-in interval value, with the first update happening
the value of delay after the notifier is created.
command[30] E(home.localTimerService).makeNotifier(5_000n,10_000n)
history[30] [Alleged: presence o-129]{}
command[31] E(history[30]).getUpdateSince()
history[31] {"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, which takes a Timestamp argument and returns void.
The passed timestamp is the time when the call to wake() is scheduled to occur.
# TimerRepeater object
A TimerRepeater has two methods, schedule() and disable:
schedule(waker)waker{ TimerWaker }- Returns
{ Timestamp } - The
wakerargument 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 - Disable this repeater, so
schedule()can't be called, and wakers already scheduled with this repeater won't be rescheduled again afterE(waker).wake()is next called on them.
- Returns
# Advanced TimerService methods
# E(home.<chain or local>TimerService).setWakeup(baseTime, handler)
baseTime{ Timestamp }handler{ Handler }- Returns:
{ Timestamp }
Calls the specified handler when the current timestamp is at least baseTime.
NOTE: baseTime is an absolute, not relative time.
Returns the time, in the same format as the parameter, 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(handler)
handler{ Handler }- Returns:
{ Promise<Array[Timestamp]>}
Remove the specified handler from all scheduled wakeups, whether
created by setWakeup() or repeater.schedule(), effectively
canceling the wakeups using that handler.
Returns a promise for an array of Timestamp times 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:{ Integer }interval:{ Integer }- Returns:
{ Repeater }
Creates and returns a Repeater object. It schedules wake() calls repeatedly at
times that are a multiple of the specified interval following baseTime. interval
is the delay between times when wake() is called. Since block times are coarse-grained,
the actual call may occur later, but this won't change when the
next event will be called.
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] makeHandler = () => { let calls = 0; const args = []; return { getCalls() {
return calls; }, getArgs() { return args; }, wake(arg) { args.push(arg); calls += 1; }, }; }
history[3] [Function makeHandler]
command[4] h1 = makeHandler()
history[4] {"getCalls":[Function getCalls],"getArgs":[Function getArgs],"wake":[Function wake]}
command[5] h2 = makeHandler()
history[5] {"getCalls":[Function getCalls],"getArgs":[Function getArgs],"wake":[Function wake]}
command[6] tl = home.localTimerService
history[6] [Presence o-59]
command[7] tc = home.chainTimerService
history[7] [Presence o-55]
command[8] rl = E(tl).makeRepeater(7, 1500)
history[8] [Presence o-64]
command[9] rc = E(tc).makeRepeater(7, 1)
history[9] [Presence o-65]
command[10] E(rl).schedule(h1)
history[10] 1571783040007n
command[11] E(rc).schedule(h2)
history[11] 1571783051n
command[12] h1.getCalls()
history[12] 3
command[13] h2.getCalls()
history[13] 1
...
command[22] h1.getCalls()
history[22] 50
command[23] h1.getCalls()
history[23] 53
command[24] h1.getCalls()
history[24] 54
command[25] E(tl).getCurrentTimestamp()
history[25] 1571783375000n
command[26] E(tc).getCurrentTimestamp()
history[26] 1571783384n