From cdc251f40228c89af973b2d19547c8004cf9baf5 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Mon, 20 Jan 2025 21:42:54 +0100 Subject: [PATCH 1/6] doc: add notes to `Timer.mo` --- src/Timer.mo | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Timer.mo b/src/Timer.mo index 27b4dd48..57cc1cb3 100644 --- a/src/Timer.mo +++ b/src/Timer.mo @@ -1,9 +1,26 @@ -/// Timers for one-off or periodic tasks. +/// Timers for one-off or periodic tasks. Applicable as part of the default mechanism. /// /// Note: If `moc` is invoked with `-no-timer`, the importing will fail. +/// /// Note: The resolution of the timers is in the order of the block rate, /// so durations should be chosen well above that. For frequent /// canister wake-ups the heatbeat mechanism should be considered. +/// +/// Note: The functionality described below is enabled only when the actor does not override it by declaring an explicit `system func timer`. +/// +/// Note: Timers are _not_ persisted across upgrades. One possible strategy +/// to re-establish timers after an upgrade is to walk stable variables +/// in the `post_upgrade` hook and distill necessary timer information +/// from there. +/// +/// Note: Basing security (e.g. access control) on timers is almost always +/// the wrong choice. Be sure to inform yourself about state-of-the art +/// dApp security. If you _must use_ timers for security controls, be sure +/// to consider reentrancy issues, and the vanishing of timers on upgrades +/// and reinstalls. +/// +/// Note: For further usage information for timers on the IC please consult +/// https://internetcomputer.org/docs/current/developer-docs/backend/periodic-tasks#timers-library-limitations import { setTimer = setTimerNano; cancelTimer = cancel } = "mo:⛔"; import { fromIntWrap } = "Nat64"; From c23ea985617bfcb7cc674f0890006b214ff8f02e Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Mon, 20 Jan 2025 21:44:48 +0100 Subject: [PATCH 2/6] be more precise --- src/Timer.mo | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Timer.mo b/src/Timer.mo index 57cc1cb3..974d8c98 100644 --- a/src/Timer.mo +++ b/src/Timer.mo @@ -21,7 +21,7 @@ /// /// Note: For further usage information for timers on the IC please consult /// https://internetcomputer.org/docs/current/developer-docs/backend/periodic-tasks#timers-library-limitations - +q import { setTimer = setTimerNano; cancelTimer = cancel } = "mo:⛔"; import { fromIntWrap } = "Nat64"; @@ -57,7 +57,7 @@ module { /// executes the future `job()` and reinserts itself for another expiration. /// /// Note: A duration of 0 will only expire once. - /// Note: Since `job` can be called more than once (under rare circumstances), + /// Note: Since `job` can be called more than once per expiration (under rare circumstances), /// it should not possess side-effects. /// /// ```motoko no-repl From 635c65619b0d661b10b6bf001f7488c2fc70e354 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Mon, 20 Jan 2025 21:54:06 +0100 Subject: [PATCH 3/6] Update src/Timer.mo --- src/Timer.mo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Timer.mo b/src/Timer.mo index 974d8c98..c65eacd3 100644 --- a/src/Timer.mo +++ b/src/Timer.mo @@ -4,7 +4,7 @@ /// /// Note: The resolution of the timers is in the order of the block rate, /// so durations should be chosen well above that. For frequent -/// canister wake-ups the heatbeat mechanism should be considered. +/// canister wake-ups the heartbeat mechanism should be considered. /// /// Note: The functionality described below is enabled only when the actor does not override it by declaring an explicit `system func timer`. /// From bd64161bab44bd7fe7594fe1f064408b7b435b35 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 21 Jan 2025 08:18:03 +0100 Subject: [PATCH 4/6] tweaks --- src/Debug.mo | 2 +- src/ExperimentalInternetComputer.mo | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Debug.mo b/src/Debug.mo index c379d99e..80003332 100644 --- a/src/Debug.mo +++ b/src/Debug.mo @@ -11,7 +11,7 @@ module { /// /// NOTE: When running on an ICP network, all output is written to the [canister log](https://internetcomputer.org/docs/current/developer-docs/smart-contracts/maintain/logs) with the exclusion of any output /// produced during the execution of non-replicated queries and composite queries. - /// In other environments, like the interpreter and stand-alone wasm engines, the output is written to standard out. + /// In other environments, like the interpreter and stand-alone wasm engines, the output is written to standard out. /// /// ```motoko include=import /// Debug.print "Hello New World!"; diff --git a/src/ExperimentalInternetComputer.mo b/src/ExperimentalInternetComputer.mo index 3a3d4c2d..9ccbc622 100644 --- a/src/ExperimentalInternetComputer.mo +++ b/src/ExperimentalInternetComputer.mo @@ -85,7 +85,6 @@ module { /// Returns the time (in nanoseconds from the epoch start) by when the update message should /// reply to the best effort message so that it can be received by the requesting canister. /// Queries and non-best-effort update messages return zero. - /// public func replyDeadline() : Nat = Prim.nat64ToNat(Prim.replyDeadline()); } From 138e92a296d9c622d68bc796fb6a8233702c59f4 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 21 Jan 2025 08:40:55 +0100 Subject: [PATCH 5/6] Update src/Timer.mo --- src/Timer.mo | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Timer.mo b/src/Timer.mo index c65eacd3..497ce8c1 100644 --- a/src/Timer.mo +++ b/src/Timer.mo @@ -21,7 +21,6 @@ /// /// Note: For further usage information for timers on the IC please consult /// https://internetcomputer.org/docs/current/developer-docs/backend/periodic-tasks#timers-library-limitations -q import { setTimer = setTimerNano; cancelTimer = cancel } = "mo:⛔"; import { fromIntWrap } = "Nat64"; From 6e1dc2f4d80459cba79c4ea82c1013b6ba69c907 Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Tue, 21 Jan 2025 13:15:55 +0100 Subject: [PATCH 6/6] remove scary notes as Timo remarked, these may be misinterpreted by users, and constructing a case where `job` would have undesired side-effects proved very difficult in our experiments: see the thread around https://dfinity.slack.com/archives/CPL67E7MX/p1737461532661639?thread_ts=1736347600.078339&cid=CPL67E7MX --- src/Timer.mo | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Timer.mo b/src/Timer.mo index 497ce8c1..c9b7be16 100644 --- a/src/Timer.mo +++ b/src/Timer.mo @@ -37,9 +37,6 @@ module { /// Installs a one-off timer that upon expiration after given duration `d` /// executes the future `job()`. /// - /// Note: Since `job` can be called more than once (under rare circumstances), - /// it should not possess side-effects. - /// /// ```motoko no-repl /// let now = Time.now(); /// let thirtyMinutes = 1_000_000_000 * 60 * 30; @@ -56,8 +53,6 @@ module { /// executes the future `job()` and reinserts itself for another expiration. /// /// Note: A duration of 0 will only expire once. - /// Note: Since `job` can be called more than once per expiration (under rare circumstances), - /// it should not possess side-effects. /// /// ```motoko no-repl /// func checkAndWaterPlants() : async () {