canic_core/ops/ic/
timer.rs1#![allow(clippy::disallowed_methods)]
2
3pub use crate::cdk::timers::TimerId;
4
5use crate::{
6 cdk::timers::{
7 clear_timer as cdk_clear_timer, set_timer as cdk_set_timer,
8 set_timer_interval as cdk_set_timer_interval,
9 },
10 model::metrics::{
11 system::{SystemMetricKind, SystemMetrics},
12 timer::{TimerMetrics, TimerMode},
13 },
14 ops::perf::PerfOps,
15 perf::perf_counter,
16};
17use std::{cell::RefCell, future::Future, rc::Rc, time::Duration};
18
19pub struct TimerOps;
24
25impl TimerOps {
26 pub fn set(
29 delay: Duration,
30 label: impl Into<String>,
31 task: impl Future<Output = ()> + 'static,
32 ) -> TimerId {
33 let label = label.into();
34
35 SystemMetrics::increment(SystemMetricKind::TimerScheduled);
36 TimerMetrics::ensure(TimerMode::Once, delay, &label);
37
38 cdk_set_timer(delay, async move {
39 TimerMetrics::increment(TimerMode::Once, delay, &label);
40
41 let start = perf_counter();
42 task.await;
43 let end = perf_counter();
44
45 PerfOps::record(&label, end.saturating_sub(start));
46 })
47 }
48
49 pub fn set_interval<F, Fut>(interval: Duration, label: impl Into<String>, task: F) -> TimerId
52 where
53 F: FnMut() -> Fut + 'static,
54 Fut: Future<Output = ()> + 'static,
55 {
56 let label = label.into();
57
58 SystemMetrics::increment(SystemMetricKind::TimerScheduled);
59 TimerMetrics::ensure(TimerMode::Interval, interval, &label);
60
61 let task = Rc::new(RefCell::new(task));
62
63 cdk_set_timer_interval(interval, move || {
64 let label = label.clone();
65 let interval = interval;
66 let task = Rc::clone(&task);
67
68 async move {
69 TimerMetrics::increment(TimerMode::Interval, interval, &label);
70
71 let start = perf_counter();
72 let fut = { (task.borrow_mut())() };
73 fut.await;
74 let end = perf_counter();
75
76 PerfOps::record(&label, end.saturating_sub(start));
77 }
78 })
79 }
80
81 pub fn clear(id: TimerId) {
83 cdk_clear_timer(id);
84 }
85}