1use std::sync::Arc;
6
7use crate::{ActorId, ActorScheduler, ActorState, Message, MessagePayload, Priority};
8
9#[derive(Clone)]
11pub struct ActorHandle {
12 id: ActorId,
14 scheduler: Arc<ActorScheduler>,
16}
17
18impl ActorHandle {
19 pub(crate) fn new(id: ActorId, scheduler: Arc<ActorScheduler>) -> Self {
21 Self { id, scheduler }
22 }
23
24 pub fn id(&self) -> ActorId {
26 self.id
27 }
28
29 pub async fn send(&self, payload: MessagePayload) -> crate::Result<()> {
31 self.scheduler
32 .send(
33 self.id,
34 Message {
35 sender: None,
36 payload,
37 priority: Priority::Normal,
38 },
39 )
40 .await
41 }
42
43 pub async fn send_with_priority(
45 &self,
46 payload: MessagePayload,
47 priority: Priority,
48 ) -> crate::Result<()> {
49 self.scheduler
50 .send(
51 self.id,
52 Message {
53 sender: None,
54 payload,
55 priority,
56 },
57 )
58 .await
59 }
60
61 pub async fn send_from(&self, sender: ActorId, payload: MessagePayload) -> crate::Result<()> {
63 self.scheduler
64 .send(
65 self.id,
66 Message {
67 sender: Some(sender),
68 payload,
69 priority: Priority::Normal,
70 },
71 )
72 .await
73 }
74
75 pub async fn start(&self) -> crate::Result<()> {
77 self.send(MessagePayload::Start).await
78 }
79
80 pub async fn stop(&self) -> crate::Result<()> {
82 self.send(MessagePayload::Stop).await
83 }
84
85 pub async fn pause(&self) -> crate::Result<()> {
87 self.send(MessagePayload::Signal(crate::Signal::Pause))
88 .await
89 }
90
91 pub async fn resume(&self) -> crate::Result<()> {
93 self.send(MessagePayload::Signal(crate::Signal::Resume))
94 .await
95 }
96
97 pub async fn restart(&self) -> crate::Result<()> {
99 self.send(MessagePayload::Signal(crate::Signal::Restart))
100 .await
101 }
102
103 pub fn state(&self) -> Option<ActorState> {
105 self.scheduler.registry().get_state(&self.id)
106 }
107
108 pub fn is_running(&self) -> bool {
110 self.state() == Some(ActorState::Running)
111 }
112
113 pub fn is_stopped(&self) -> bool {
115 self.state() == Some(ActorState::Stopped)
116 }
117
118 pub fn is_suspended(&self) -> bool {
120 self.state() == Some(ActorState::Suspended)
121 }
122
123 pub fn is_backpressured(&self) -> bool {
125 self.scheduler
126 .registry()
127 .get_mailbox(&self.id)
128 .map(|m| m.is_backpressured())
129 .unwrap_or(false)
130 }
131
132 pub fn mailbox_size(&self) -> usize {
134 self.scheduler
135 .registry()
136 .get_mailbox(&self.id)
137 .map(|m| m.len())
138 .unwrap_or(0)
139 }
140
141 pub fn processed_count(&self) -> u64 {
143 self.scheduler.registry().get_processed_count(&self.id)
144 }
145}
146
147impl std::fmt::Debug for ActorHandle {
148 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149 f.debug_struct("ActorHandle")
150 .field("id", &self.id)
151 .field("state", &self.state())
152 .finish()
153 }
154}
155
156impl std::hash::Hash for ActorHandle {
157 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
158 self.id.hash(state);
159 }
160}
161
162impl PartialEq for ActorHandle {
163 fn eq(&self, other: &Self) -> bool {
164 self.id == other.id
165 }
166}
167
168impl Eq for ActorHandle {}
169
170pub struct ActorBuilder {
172 name: Option<String>,
173 priority: Priority,
174}
175
176impl ActorBuilder {
177 pub fn new() -> Self {
179 Self {
180 name: None,
181 priority: Priority::Normal,
182 }
183 }
184
185 pub fn name(mut self, name: impl Into<String>) -> Self {
187 self.name = Some(name.into());
188 self
189 }
190
191 pub fn priority(mut self, priority: Priority) -> Self {
193 self.priority = priority;
194 self
195 }
196
197 pub fn spawn(self, scheduler: &Arc<ActorScheduler>) -> crate::Result<ActorHandle> {
199 let id = scheduler.spawn_named(self.name)?;
200 Ok(ActorHandle::new(id, scheduler.clone()))
201 }
202}
203
204impl Default for ActorBuilder {
205 fn default() -> Self {
206 Self::new()
207 }
208}
209
210#[cfg(test)]
211mod tests {
212 use super::*;
213
214 #[tokio::test]
215 async fn test_actor_handle_send() {
216 let scheduler = Arc::new(ActorScheduler::new(Default::default()));
217 scheduler.start().unwrap();
218
219 let handle = ActorBuilder::new()
220 .name("test-actor")
221 .spawn(&scheduler)
222 .unwrap();
223
224 assert_eq!(handle.state(), Some(ActorState::Creating));
225
226 handle.start().await.unwrap();
227 }
228}