1pub use crate::cdk::timers::TimerId;
2
3use crate::{
4 interface::ic::timer::Timer,
5 model::metrics::{SystemMetricKind, SystemMetrics, TimerMetrics, TimerMode},
6 ops::perf::PerfOps,
7 perf::perf_counter,
8};
9use std::{cell::RefCell, future::Future, rc::Rc, time::Duration};
10
11pub struct TimerOps;
16
17impl TimerOps {
18 pub fn set(
21 delay: Duration,
22 label: impl Into<String>,
23 task: impl Future<Output = ()> + 'static,
24 ) -> TimerId {
25 let label = label.into();
26
27 SystemMetrics::increment(SystemMetricKind::TimerScheduled);
28 TimerMetrics::ensure(TimerMode::Once, delay, &label);
29
30 Timer::set(delay, async move {
31 TimerMetrics::increment(TimerMode::Once, delay, &label);
32
33 let start = perf_counter();
34 task.await;
35 let end = perf_counter();
36
37 PerfOps::record(&label, end.saturating_sub(start));
38 })
39 }
40
41 pub fn set_interval<F, Fut>(interval: Duration, label: impl Into<String>, task: F) -> TimerId
44 where
45 F: FnMut() -> Fut + 'static,
46 Fut: Future<Output = ()> + 'static,
47 {
48 let label = label.into();
49
50 SystemMetrics::increment(SystemMetricKind::TimerScheduled);
51 TimerMetrics::ensure(TimerMode::Interval, interval, &label);
52
53 let task = Rc::new(RefCell::new(task));
54
55 Timer::set_interval(interval, move || {
56 let label = label.clone();
57 let interval = interval;
58 let task = Rc::clone(&task);
59
60 async move {
61 TimerMetrics::increment(TimerMode::Interval, interval, &label);
62
63 let start = perf_counter();
64 let fut = { (task.borrow_mut())() };
65 fut.await;
66 let end = perf_counter();
67
68 PerfOps::record(&label, end.saturating_sub(start));
69 }
70 })
71 }
72}