Skip to main content

reifydb_runtime/actor/timers/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4//! Timer utilities for actors.
5//!
6//! This module provides timer functionality for scheduling messages:
7//! - [`TimerHandle`]: A handle to cancel a scheduled timer
8//! - [`Context::schedule_once`]: Schedule a message to be sent after a delay
9//! - [`Context::schedule_repeat`]: Schedule a message to be sent repeatedly
10//!
11//! # Platform Differences
12//!
13//! - **Native**: Uses a centralized scheduler with a BinaryHeap min-heap
14//! - **WASM**: Uses `setTimeout` and `setInterval` via `web-sys`
15//!
16//! [`Context::schedule_once`]: crate::actor::context::Context::schedule_once
17//! [`Context::schedule_repeat`]: crate::actor::context::Context::schedule_repeat
18
19use std::{
20	fmt,
21	fmt::Debug,
22	sync::{
23		Arc,
24		atomic::{AtomicBool, AtomicU64, Ordering},
25	},
26};
27
28#[cfg(reifydb_target = "dst")]
29pub(crate) mod dst;
30#[cfg(reifydb_target = "native")]
31pub mod scheduler;
32#[cfg(reifydb_target = "wasi")]
33pub(crate) mod wasi;
34#[cfg(reifydb_target = "wasm")]
35pub(crate) mod wasm;
36
37#[cfg(reifydb_target = "wasi")]
38use wasi::drain_expired_timers as wasi_drain;
39
40/// Handle to a scheduled timer.
41///
42/// Can be used to cancel the timer before it fires.
43#[derive(Clone)]
44pub struct TimerHandle {
45	id: u64,
46	cancelled: Arc<AtomicBool>,
47}
48
49impl TimerHandle {
50	pub(crate) fn new(id: u64) -> Self {
51		Self {
52			id,
53			cancelled: Arc::new(AtomicBool::new(false)),
54		}
55	}
56
57	/// Cancel this timer.
58	///
59	/// If the timer hasn't fired yet, it will be cancelled.
60	/// Returns `true` if the timer was successfully cancelled.
61	pub fn cancel(&self) -> bool {
62		self.cancelled.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst).is_ok()
63	}
64
65	/// Check if this timer has been cancelled.
66	pub fn is_cancelled(&self) -> bool {
67		self.cancelled.load(Ordering::SeqCst)
68	}
69
70	/// Get the timer ID.
71	pub fn id(&self) -> u64 {
72		self.id
73	}
74
75	/// Get a clone of the cancelled flag.
76	pub(crate) fn cancelled_flag(&self) -> Arc<AtomicBool> {
77		self.cancelled.clone()
78	}
79}
80
81impl Debug for TimerHandle {
82	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83		f.debug_struct("TimerHandle").field("id", &self.id).field("cancelled", &self.is_cancelled()).finish()
84	}
85}
86
87/// Counter for generating unique timer IDs.
88static TIMER_ID_COUNTER: AtomicU64 = AtomicU64::new(0);
89
90pub(crate) fn next_timer_id() -> u64 {
91	TIMER_ID_COUNTER.fetch_add(1, Ordering::Relaxed)
92}
93
94/// Drain expired timers, firing their callbacks synchronously.
95///
96/// Only meaningful on WASI where timers are queue-based. No-op on native
97/// (thread-based timers) and WASM (JavaScript event loop handles timers).
98#[cfg(reifydb_target = "wasi")]
99pub fn drain_expired_timers() {
100	wasi_drain();
101}
102
103/// Drain expired timers (no-op on this platform).
104#[cfg(not(reifydb_target = "wasi"))]
105pub fn drain_expired_timers() {}