Every timer carries an action (a function) which cannot be persisted, so a setup is necessary.
@luc-blaeser came up with a neat way to do this using a transient let
:
import { setTimer } = "mo:base/Timer"
actor {
func computeExpiry() : Nat = 42;
func action() : async () {
// do whatever
/*timerId :=*/ ignore setTimer<system>(#seconds (computeExpiry()), action);
};
// on top-level
transient var timerId = setTimer<system>(#seconds (computeExpiry()), func() : async () { await action() });
};
transient
bindings always get reinitialised when the actor is upgraded, so there is a guarantee that action
will trigger sometime.
Hope this helps. (Edited the example, but I keep running into the circularity problem, and it is too late here. Will fix it tomorrow.)