1use std::marker::PhantomData;
5use std::sync::Arc;
6
7use ahash::{HashMap, HashSet};
8use dashmap::DashMap;
9use futures_util::future::join_all;
10use tracing::{error, info, warn};
11
12use acktor::{
13 Actor, ActorContext, ActorId, Address, ErrorReport, Handler, JoinHandle, Recipient, Signal,
14 message::FutureMessageResult,
15 observer::{ObserverSet, SubjectActor},
16 supervisor::SupervisionEvent,
17 utils::{debug_trace, terminate_actor},
18};
19
20use crate::double_map::DoubleMap;
21use crate::errors::NodeError;
22use crate::ipc_method::{IpcConnection, IpcListener};
23use crate::remote_actor::{
24 RemoteActor, RemoteActorFactory, RemoteActorFactoryRegistry, RemoteActorRegistry,
25 RemoteActorShim,
26};
27use crate::session::{self, Session, SessionHandle};
28
29pub mod command;
30
31mod event;
32pub use event::NodeEvent;
33
34mod context;
35use context::NodeContext;
36
37pub(crate) mod factory;
38use factory::Factory;
39
40type Result<T> = std::result::Result<T, NodeError>;
41
42pub(crate) type LabelMap = Arc<DashMap<String, ActorId, ahash::RandomState>>;
43
44#[derive(Default)]
50pub struct Node {
51 listener_labels: HashSet<String>,
52 listeners: Vec<Box<dyn IpcListener>>,
53 factory_registry: Option<RemoteActorFactoryRegistry>,
55 factory: Option<Address<Factory>>,
56 registry: RemoteActorRegistry,
59 label_map: LabelMap,
60 sessions: DoubleMap<ActorId, String, Address<Session>>,
61 children: HashMap<Recipient<Signal>, JoinHandle<()>>,
62 observers: ObserverSet<NodeEvent>,
63}
64
65impl Node {
66 pub fn new() -> Self {
68 Self::default()
69 }
70
71 pub fn with_listener<L>(mut self, listener: L) -> Self
78 where
79 L: IpcListener,
80 {
81 if self.listener_labels.contains(listener.local_endpoint()) {
82 self.listeners
83 .retain(|l| l.local_endpoint() != listener.local_endpoint());
84 } else {
85 self.listener_labels
86 .insert(listener.local_endpoint().to_string());
87 }
88 self.listeners.push(Box::new(listener));
89 self
90 }
91
92 pub fn with_actor<A>(self, actor: Address<A>) -> Self
94 where
95 A: RemoteActor,
96 {
97 self.registry.insert(actor);
98 self
99 }
100
101 pub fn with_actor_factory<A>(mut self) -> Self
104 where
105 A: RemoteActorFactory,
106 {
107 self.factory_registry.get_or_insert_default().insert(
108 A::TYPE_NAME.to_string(),
109 Arc::new(RemoteActorShim::<A>(PhantomData)),
110 );
111 self
112 }
113
114 async fn create_session(
115 &mut self,
116 connection: Box<dyn IpcConnection>,
117 session_label: Option<String>,
118 ctx: &mut <Self as Actor>::Context,
119 ) -> Result<Address<Session>> {
120 let endpoint = connection.peer_endpoint().to_string();
121
122 let session_label = session_label.unwrap_or_else(|| endpoint.clone());
123
124 if self.sessions.contains_key2(&session_label) {
125 return Err(NodeError::CreateSessionFailed(
126 format!("session with label '{}' already exists", session_label).into(),
127 ));
128 }
129
130 let (address, join_handle) = Session::create(endpoint.clone(), |child_ctx| {
131 child_ctx.set_supervisor(Some(ctx.address().into()));
132
133 Ok(Session::new(
137 connection,
138 self.factory.clone().unwrap(),
139 self.registry.clone(),
140 self.label_map.clone(),
141 ))
142 })
143 .map_err(|e| NodeError::CreateSessionFailed(e.into()))?;
144
145 let session_id = address.index();
146
147 let _ = self
150 .sessions
151 .insert(session_id, session_label.clone(), address.clone());
152
153 self.children.insert(address.clone().into(), join_handle);
154
155 self.notify_observers(NodeEvent::SessionCreated(address.clone(), session_label))
156 .await;
157
158 Ok(address)
159 }
160
161 fn get_session(&self, session_ref: &SessionHandle) -> Result<Address<Session>> {
162 match session_ref {
163 SessionHandle::Address(address) => self
164 .sessions
165 .get_by_key1(&address.index())
166 .cloned()
167 .ok_or_else(|| NodeError::SessionNotFound(address.index().to_string())),
168 SessionHandle::Index(index) => self
169 .sessions
170 .get_by_key1(index)
171 .cloned()
172 .ok_or_else(|| NodeError::SessionNotFound(index.to_string())),
173 SessionHandle::Label(label) => self
174 .sessions
175 .get_by_key2(label)
176 .cloned()
177 .ok_or_else(|| NodeError::SessionNotFound(label.clone())),
178 }
179 }
180}
181
182impl Actor for Node {
183 type Context = NodeContext;
184 type Error = NodeError;
185
186 async fn post_start(&mut self, _ctx: &mut Self::Context) -> Result<()> {
187 let factory_registry = self.factory_registry.take().unwrap_or_default();
188
189 let (address, join_handle) = Factory::new(
191 factory_registry,
192 self.registry.clone(),
193 self.label_map.clone(),
194 )
195 .run("factory")?;
196
197 self.children.insert(address.clone().into(), join_handle);
198 self.factory = Some(address);
199
200 info!("Node is ready");
201
202 Ok(())
203 }
204
205 async fn post_stop(&mut self, _ctx: &mut Self::Context) -> Result<()> {
206 join_all(
207 self.children
208 .drain()
209 .map(|(address, join_handle)| terminate_actor(address, join_handle)),
210 )
211 .await;
212
213 info!("Node is stopped");
214
215 Ok(())
216 }
217}
218
219impl SubjectActor<NodeEvent> for Node {
220 fn observers_mut(&mut self) -> &mut ObserverSet<NodeEvent> {
221 &mut self.observers
222 }
223}
224
225impl<L> Handler<command::AddListener<L>> for Node
226where
227 L: IpcListener,
228{
229 type Result = bool;
230
231 async fn handle(
232 &mut self,
233 msg: command::AddListener<L>,
234 _ctx: &mut Self::Context,
235 ) -> Self::Result {
236 debug_trace!("Handle command {:?}", msg,);
237
238 let label = msg.0.local_endpoint();
239 if self.listener_labels.contains(label) {
240 false
241 } else {
242 self.listener_labels.insert(label.to_string());
243 self.listeners.push(Box::new(msg.0));
244 true
245 }
246 }
247}
248
249impl Handler<command::RemoveListener> for Node {
250 type Result = bool;
251
252 async fn handle(
253 &mut self,
254 msg: command::RemoveListener,
255 _ctx: &mut Self::Context,
256 ) -> Self::Result {
257 debug_trace!("Handle command {:?}", msg);
258
259 let label = msg.0;
260 self.listener_labels.remove(&label)
261 }
262}
263
264impl<A> Handler<command::AddActor<A>> for Node
265where
266 A: RemoteActor,
267{
268 type Result = bool;
269
270 async fn handle(
271 &mut self,
272 msg: command::AddActor<A>,
273 _ctx: &mut Self::Context,
274 ) -> Self::Result {
275 debug_trace!("Handle command {:?}", msg,);
276
277 self.registry.insert(msg.0)
278 }
279}
280
281impl Handler<command::RemoveActor> for Node {
282 type Result = bool;
283
284 async fn handle(
285 &mut self,
286 msg: command::RemoveActor,
287 _ctx: &mut Self::Context,
288 ) -> Self::Result {
289 debug_trace!("Handle command {:?}", msg);
290
291 let actor_id = msg.0;
292 self.label_map.retain(|_, id| *id != actor_id);
293 self.registry.remove(actor_id).is_some()
294 }
295}
296
297impl<T> Handler<command::Connect<T>> for Node
298where
299 T: IpcConnection,
300{
301 type Result = Result<Address<Session>>;
302
303 async fn handle(&mut self, msg: command::Connect<T>, ctx: &mut Self::Context) -> Self::Result {
304 debug_trace!("Handle command {:?}", msg);
305
306 let command::Connect {
307 endpoint,
308 session_label,
309 ..
310 } = msg;
311
312 let connection = T::connect(&endpoint).await?;
313 let connection: Box<dyn IpcConnection> = Box::new(connection);
314 let address = self.create_session(connection, session_label, ctx).await?;
315
316 Ok(address)
317 }
318}
319
320impl Handler<command::CreateRemoteActor> for Node {
321 type Result = FutureMessageResult<command::CreateRemoteActor>;
322
323 async fn handle(
324 &mut self,
325 msg: command::CreateRemoteActor,
326 _ctx: &mut Self::Context,
327 ) -> Self::Result {
328 debug_trace!("Handle command {:?}", msg);
329
330 let command::CreateRemoteActor {
331 session,
332 label,
333 r#type,
334 config,
335 } = msg;
336
337 let session = self.get_session(&session);
338
339 FutureMessageResult::new(async move {
340 session?
341 .send(session::command::CreateRemoteActor {
342 label,
343 r#type,
344 config,
345 })
346 .await?
347 .await?
349 .map_err(NodeError::CreateRemoteActorFailed)
350 })
351 }
352}
353
354impl Handler<command::GetRemoteActor> for Node {
355 type Result = FutureMessageResult<command::GetRemoteActor>;
356
357 async fn handle(
358 &mut self,
359 msg: command::GetRemoteActor,
360 _ctx: &mut Self::Context,
361 ) -> Self::Result {
362 debug_trace!("Handle command {:?}", msg);
363
364 let command::GetRemoteActor { session, actor } = msg;
365
366 let session = self.get_session(&session);
367
368 FutureMessageResult::new(async move {
369 session?
370 .send(session::command::GetRemoteActor { actor })
371 .await?
372 .await?
374 .map_err(NodeError::RemoteActorNotFound)
375 })
376 }
377}
378
379impl Handler<SupervisionEvent<Session>> for Node {
380 type Result = ();
381
382 async fn handle(
383 &mut self,
384 msg: SupervisionEvent<Session>,
385 _ctx: &mut Self::Context,
386 ) -> Self::Result {
387 debug_trace!("Handle supervision event {:?}", msg);
388
389 match msg {
390 SupervisionEvent::Warn(actor, e) => {
391 warn!("Session {} error: {}", actor.index(), e.report());
392 }
393 SupervisionEvent::Terminated(session, e) => {
394 if let Some(e) = e {
395 error!(
396 "Session {} is stopped with error: {}",
397 session.index(),
398 e.report()
399 );
400 }
401
402 self.sessions.retain(|_, _, v| v != &session);
403 self.children.remove(&session.clone().into());
404
405 self.notify_observers(NodeEvent::SessionDeleted(session))
406 .await;
407 }
408 _ => {}
409 }
410 }
411}