1#[macro_export]
2macro_rules! implement_cron {
3 () => {
4 pub static mut _CRON_STATE: Option<ic_cron::task_scheduler::TaskScheduler> = None;
5
6 pub fn get_cron_state() -> &'static mut ic_cron::task_scheduler::TaskScheduler {
7 unsafe {
8 match _CRON_STATE.as_mut() {
9 Some(cron) => cron,
10 None => {
11 _put_cron_state(Some(ic_cron::task_scheduler::TaskScheduler::default()));
12 get_cron_state()
13 }
14 }
15 }
16 }
17
18 pub fn _take_cron_state() -> Option<ic_cron::task_scheduler::TaskScheduler> {
19 unsafe { _CRON_STATE.take() }
20 }
21
22 pub fn _put_cron_state(state: Option<ic_cron::task_scheduler::TaskScheduler>) {
23 unsafe {
24 _CRON_STATE = state;
25 }
26 }
27
28 pub fn cron_enqueue<Payload: ic_cdk::export::candid::CandidType>(
29 payload: Payload,
30 scheduling_options: ic_cron::types::SchedulingOptions,
31 ) -> ic_cdk::export::candid::Result<ic_cron::types::TaskId> {
32 let cron = get_cron_state();
33
34 let id = cron.enqueue(payload, scheduling_options, ic_cdk::api::time())?;
35
36 Ok(id)
37 }
38
39 pub fn cron_dequeue(
40 task_id: ic_cron::types::TaskId,
41 ) -> Option<ic_cron::types::ScheduledTask> {
42 get_cron_state().dequeue(task_id)
43 }
44
45 pub fn cron_ready_tasks() -> Vec<ic_cron::types::ScheduledTask> {
46 get_cron_state().iterate(ic_cdk::api::time())
47 }
48 };
49}
50
51#[cfg(test)]
52mod tests {
53 use crate as ic_cron;
54 use crate::implement_cron;
55 use crate::task_scheduler::TaskScheduler;
56 use ic_cdk::storage::{stable_restore, stable_save};
57 use ic_cdk_macros::{heartbeat, post_upgrade, pre_upgrade};
58
59 implement_cron!();
60
61 #[pre_upgrade]
62 fn pre_upgrade_hook() {
63 let cron_state = _take_cron_state();
64
65 stable_save((cron_state,)).expect("Unable to save the state to stable memory");
66 }
67
68 #[post_upgrade]
69 fn post_upgrade_hook() {
70 let (cron_state,): (Option<TaskScheduler>,) =
71 stable_restore().expect("Unable to restore the state from stable memory");
72
73 _put_cron_state(cron_state);
74 }
75
76 #[heartbeat]
77 fn tick() {
78 let tasks = cron_ready_tasks();
79 }
80
81 #[test]
82 fn no_op() {
83 assert!(true);
84 }
85}