Skip to main content

reifydb_runtime/actor/
context.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4//! Actor execution context.
5//!
6//! The context provides actors with access to:
7//! - Self reference for receiving messages
8//! - Actor system for spawning child actors
9//! - Cancellation status for graceful shutdown
10//! - Timer scheduling (when enabled)
11
12use std::{
13	sync::{
14		Arc,
15		atomic::{AtomicBool, Ordering},
16	},
17	time::Duration,
18};
19
20use crate::actor::{mailbox::ActorRef, system::ActorSystem, timers::TimerHandle};
21
22/// A cancellation token for signaling shutdown.
23///
24/// This is a simple atomic boolean that can be shared across actors.
25#[derive(Clone)]
26pub struct CancellationToken {
27	cancelled: Arc<AtomicBool>,
28}
29
30impl CancellationToken {
31	/// Create a new cancellation token.
32	pub fn new() -> Self {
33		Self {
34			cancelled: Arc::new(AtomicBool::new(false)),
35		}
36	}
37
38	/// Signal cancellation.
39	pub fn cancel(&self) {
40		self.cancelled.store(true, Ordering::SeqCst);
41	}
42
43	/// Check if cancellation was requested.
44	pub fn is_cancelled(&self) -> bool {
45		self.cancelled.load(Ordering::SeqCst)
46	}
47}
48
49impl Default for CancellationToken {
50	fn default() -> Self {
51		Self::new()
52	}
53}
54
55/// Context provided to actors during execution.
56///
57/// Provides access to:
58/// - Self reference (to give to other actors)
59/// - Actor system (to spawn child actors and run compute)
60/// - Cancellation (for graceful shutdown)
61pub struct Context<M> {
62	self_ref: ActorRef<M>,
63	system: ActorSystem,
64	cancel: CancellationToken,
65}
66
67impl<M: Send + 'static> Context<M> {
68	/// Create a new context.
69	pub(crate) fn new(self_ref: ActorRef<M>, system: ActorSystem, cancel: CancellationToken) -> Self {
70		Self {
71			self_ref,
72			system,
73			cancel,
74		}
75	}
76
77	/// Get a reference to send messages to self.
78	pub fn self_ref(&self) -> ActorRef<M> {
79		self.self_ref.clone()
80	}
81
82	/// Get the actor system (for spawning child actors).
83	pub fn system(&self) -> &ActorSystem {
84		&self.system
85	}
86
87	/// Check if shutdown was requested.
88	pub fn is_cancelled(&self) -> bool {
89		self.cancel.is_cancelled()
90	}
91
92	/// Get the cancellation token.
93	pub fn cancellation_token(&self) -> CancellationToken {
94		self.cancel.clone()
95	}
96}
97
98impl<M: Send + 'static> Context<M> {
99	/// Schedule a message to be sent to this actor after a delay.
100	///
101	/// Uses a factory function to create the message, so `M` doesn't need to be `Clone`.
102	/// Returns a handle that can be used to cancel the timer.
103	#[cfg(reifydb_target = "native")]
104	pub fn schedule_once<F: FnOnce() -> M + Send + 'static>(&self, delay: Duration, factory: F) -> TimerHandle {
105		let actor_ref = self.self_ref.clone();
106		self.system.scheduler().schedule_once(delay, move || {
107			let _ = actor_ref.send(factory());
108		})
109	}
110
111	/// Schedule a message to be sent to this actor after a delay.
112	///
113	/// Uses a factory function to create the message, so `M` doesn't need to be `Clone`.
114	/// Returns a handle that can be used to cancel the timer.
115	#[cfg(reifydb_target = "wasm")]
116	pub fn schedule_once<F: FnOnce() -> M + Send + 'static>(&self, delay: Duration, factory: F) -> TimerHandle {
117		crate::actor::timers::wasm::schedule_once_fn(self.self_ref.clone(), delay, factory)
118	}
119}
120
121impl<M: Send + Sync + Clone + 'static> Context<M> {
122	/// Schedule a message to be sent to this actor repeatedly at an interval.
123	///
124	/// The timer continues until cancelled or the actor is dropped.
125	/// Returns a handle that can be used to cancel the timer.
126	#[cfg(reifydb_target = "native")]
127	pub fn schedule_repeat(&self, interval: Duration, msg: M) -> TimerHandle {
128		let actor_ref = self.self_ref.clone();
129		self.system.scheduler().schedule_repeat(interval, move || actor_ref.send(msg.clone()).is_ok())
130	}
131
132	/// Schedule a message to be sent to this actor repeatedly at an interval.
133	///
134	/// The timer continues until cancelled or the actor is dropped.
135	/// Returns a handle that can be used to cancel the timer.
136	#[cfg(reifydb_target = "wasm")]
137	pub fn schedule_repeat(&self, interval: Duration, msg: M) -> TimerHandle {
138		crate::actor::timers::wasm::schedule_repeat(self.self_ref.clone(), interval, msg)
139	}
140}
141
142impl<M> Clone for Context<M> {
143	fn clone(&self) -> Self {
144		Self {
145			self_ref: self.self_ref.clone(),
146			system: self.system.clone(),
147			cancel: self.cancel.clone(),
148		}
149	}
150}