Skip to main content

canic_core/api/
timer.rs

1//! Module: api::timer
2//!
3//! Responsibility: expose hidden lifecycle adapters for macro-generated entrypoints.
4//! Does not own: timer state, recurrence, arbitration, or domain scheduling policy.
5//! Boundary: framework lifecycle and the exact Root owner delegate to timer authority.
6
7use crate::workflow::runtime::timer::{
8    TimerAuthorityWorkflow, recovery_watchdog_identity, require_active,
9};
10use ic_timers::TimerRunResult;
11use std::{future::Future, time::Duration};
12
13pub use crate::workflow::runtime::timer::TimerError;
14
15/// Hidden timer adapter used by Canic's macro-expanded lifecycle entrypoints.
16#[doc(hidden)]
17pub struct TimerApi;
18
19impl TimerApi {
20    /// Initialize the shared runtime and fixed non-root declarations during lifecycle restore.
21    #[doc(hidden)]
22    pub fn initialize_nonroot_runtime_required() {
23        TimerAuthorityWorkflow::initialize_nonroot_runtime()
24            .unwrap_or_else(|error| ic_cdk::trap(format!("timer runtime init failed: {error}")));
25    }
26
27    /// Initialize the shared runtime and fixed root declarations during lifecycle restore.
28    #[doc(hidden)]
29    pub fn initialize_root_runtime_required() {
30        TimerAuthorityWorkflow::initialize_root_runtime()
31            .unwrap_or_else(|error| ic_cdk::trap(format!("timer runtime init failed: {error}")));
32    }
33
34    /// Initialize the shared runtime for a canister with no Canic runtime jobs.
35    #[doc(hidden)]
36    pub fn initialize_shared_runtime_required() {
37        TimerAuthorityWorkflow::initialize_shared_runtime()
38            .unwrap_or_else(|error| ic_cdk::trap(format!("timer runtime init failed: {error}")));
39    }
40
41    /// Restore volatile suspension from the durable authority fence.
42    #[doc(hidden)]
43    pub fn restore_snapshot_suspension(sealed: bool) {
44        TimerAuthorityWorkflow::restore_snapshot_suspension(sealed);
45    }
46
47    /// Prove exact Root-native claims and business attempts are safe to suspend.
48    #[doc(hidden)]
49    pub fn require_root_authority_snapshot_resumable() -> Result<(), TimerError> {
50        TimerAuthorityWorkflow::require_root_resumable()
51    }
52
53    /// Reject Root-owned scheduling while the durable snapshot fence is sealed.
54    #[doc(hidden)]
55    pub fn require_active() -> Result<(), TimerError> {
56        require_active()
57    }
58
59    /// Return the exact identity shared by each role's sole recovery watchdog.
60    #[doc(hidden)]
61    pub fn recovery_watchdog_identity() -> Result<ic_timers::TimerIdentity, TimerError> {
62        recovery_watchdog_identity()
63    }
64
65    /// Recover expired core business attempts for the Root-owned watchdog.
66    #[doc(hidden)]
67    #[must_use]
68    pub fn recover_expired_async_jobs(now_ns: u64) -> u64 {
69        TimerAuthorityWorkflow::recover_expired_async_jobs(now_ns)
70    }
71
72    /// Recover the base Root jobs plus its core-owned automatic cycle top-up attempt.
73    #[doc(hidden)]
74    #[must_use]
75    pub fn recover_expired_root_async_jobs(now_ns: u64) -> u64 {
76        TimerAuthorityWorkflow::recover_expired_async_jobs_with_automatic_topup(now_ns)
77    }
78
79    /// Schedule framework-owned lifecycle work and trap if runtime invariants reject it.
80    #[doc(hidden)]
81    pub fn defer_lifecycle_required(
82        delay: Duration,
83        label: impl Into<String>,
84        task: impl Future<Output = ()> + 'static,
85    ) {
86        TimerAuthorityWorkflow::defer_lifecycle_once(delay, label, task)
87            .unwrap_or_else(|error| ic_cdk::trap(format!("lifecycle timer rejected: {error}")));
88    }
89
90    /// Schedule framework lifecycle work with a truthful typed completion.
91    #[doc(hidden)]
92    pub fn defer_lifecycle_result_required(
93        delay: Duration,
94        label: impl Into<String>,
95        task: impl Future<Output = TimerRunResult> + 'static,
96    ) {
97        TimerAuthorityWorkflow::defer_lifecycle_result_once(delay, label, task)
98            .unwrap_or_else(|error| ic_cdk::trap(format!("lifecycle timer rejected: {error}")));
99    }
100}