1use std::marker::PhantomData;
5use std::sync::Arc;
6
7use ahash::{HashMap, HashSet};
8use futures_util::future::join_all;
9use tracing::{error, info, warn};
10
11use acktor::{
12 Actor, ActorContext, ActorId, Address, ErrorReport, Handler, JoinHandle, Recipient, Signal,
13 message::FutureMessageResult,
14 observer::{ObserverSet, SubjectActor},
15 supervisor::SupervisionEvent,
16 utils::{ShortName, debug_trace, terminate_actor},
17};
18
19use crate::actor_ref::ActorRef;
20use crate::double_map::DoubleMap;
21use crate::error::NodeError;
22use crate::ipc_method::{IpcConnection, IpcListener};
23use crate::remote::{
24 RemoteAddressable, RemoteFactoryRegistry, RemoteFactoryShim, RemoteMailboxRegistry,
25 RemoteSpawnable,
26};
27use crate::session::{self, Session};
28
29pub mod command;
30
31mod event;
32pub use event::NodeEvent;
33
34mod context;
35use context::NodeContext;
36
37pub(crate) mod actor_mgr;
38use actor_mgr::{ActorLabelMap, ActorMgr};
39
40type Result<T> = std::result::Result<T, NodeError>;
41
42pub struct Node {
48 listener_labels: HashSet<String>,
49 listeners: Vec<Box<dyn IpcListener>>,
50 registry: RemoteMailboxRegistry,
53 actor_mgr: Option<Address<ActorMgr>>,
55 sessions: DoubleMap<ActorId, String, Address<Session>>,
57 children: HashMap<Recipient<Signal>, JoinHandle<()>>,
58 observers: ObserverSet<NodeEvent>,
59 _factories: Option<RemoteFactoryRegistry>,
65 _actor_labels: Option<ActorLabelMap>,
71}
72
73impl Default for Node {
74 #[inline]
75 fn default() -> Self {
76 Self {
77 listener_labels: HashSet::default(),
78 listeners: Vec::new(),
79 registry: RemoteMailboxRegistry::default(),
80 actor_mgr: None,
81 sessions: DoubleMap::default(),
82 children: HashMap::default(),
83 observers: ObserverSet::new(),
84 _factories: Some(RemoteFactoryRegistry::default()),
85 _actor_labels: Some(ActorLabelMap::default()),
86 }
87 }
88}
89
90impl Node {
91 pub fn new() -> Self {
93 Self::default()
94 }
95
96 pub fn with_listener<L>(mut self, listener: L) -> Self
103 where
104 L: IpcListener,
105 {
106 if self.listener_labels.contains(listener.local_endpoint()) {
107 self.listeners
108 .retain(|l| l.local_endpoint() != listener.local_endpoint());
109 } else {
110 self.listener_labels
111 .insert(listener.local_endpoint().to_string());
112 }
113 self.listeners.push(Box::new(listener));
114 self
115 }
116
117 pub fn with_actor<A, S>(mut self, label: S, actor: Address<A>) -> Self
124 where
125 A: Actor + RemoteAddressable,
126 S: AsRef<str>,
127 {
128 if let Some(actor_labels) = &mut self._actor_labels {
129 let actor_id = actor.index();
130 if !actor_labels.contains_key(label.as_ref()) && self.registry.insert(actor.into()) {
131 actor_labels.insert(label.as_ref().to_string(), actor_id.as_local());
132 }
133 }
134 self
135 }
136
137 pub fn with_factory<A>(mut self) -> Self
142 where
143 A: Actor + RemoteSpawnable,
144 {
145 if let Some(factories) = &mut self._factories {
146 factories.insert(
147 A::TYPE_ID.as_u64(),
148 Arc::new(RemoteFactoryShim::<A>(PhantomData)),
149 );
150 }
151 self
152 }
153
154 async fn create_session(
155 &mut self,
156 connection: Box<dyn IpcConnection>,
157 session_label: Option<String>,
158 ctx: &mut <Self as Actor>::Context,
159 ) -> Result<Address<Session>> {
160 let endpoint = connection.peer_endpoint().to_string();
161
162 let label = session_label.unwrap_or_else(|| endpoint.clone());
163
164 if self.sessions.contains_key2(&label) {
165 return Err(NodeError::CreateSessionFailed(
166 format!("session with label '{}' already exists", label).into(),
167 ));
168 }
169
170 let session = Session::new(
171 connection,
172 self.registry.clone(),
173 self.actor_mgr.clone().ok_or_else(|| {
174 NodeError::CreateSessionFailed("actor manager does not exist".into())
175 })?,
176 );
177
178 let (address, join_handle) = Session::create(endpoint.clone(), |child_ctx| {
179 child_ctx.set_supervisor(Some(ctx.address().into()));
180 Ok(session)
181 })
182 .map_err(|e| NodeError::CreateSessionFailed(e.into()))?;
183
184 let session_id = address.index();
185
186 let _ = self
189 .sessions
190 .insert(session_id, label.clone(), address.clone());
191
192 self.children.insert(address.clone().into(), join_handle);
193
194 self.notify_observers(NodeEvent::SessionCreated(address.clone(), label))
195 .await;
196
197 Ok(address)
198 }
199
200 fn get_session(&self, session_ref: &ActorRef) -> Result<Address<Session>> {
201 match session_ref {
202 ActorRef::Index(index) => self
203 .sessions
204 .get_by_key1(index)
205 .cloned()
206 .ok_or_else(|| NodeError::SessionNotFound(index.to_string())),
207
208 ActorRef::Label(label) => self
209 .sessions
210 .get_by_key2(label)
211 .cloned()
212 .ok_or_else(|| NodeError::SessionNotFound(label.clone())),
213 }
214 }
215}
216
217impl Actor for Node {
218 type Context = NodeContext;
219 type Error = NodeError;
220
221 async fn post_start(&mut self, _ctx: &mut Self::Context) -> Result<()> {
222 let factories = self._factories.take().unwrap_or_default();
223 let actor_labels = self._actor_labels.take().unwrap_or_default();
224
225 let (address, join_handle) =
227 ActorMgr::new(self.registry.clone(), actor_labels, factories).start("mgr")?;
228 self.children.insert(address.clone().into(), join_handle);
229 self.actor_mgr = Some(address);
230
231 info!("Node is ready");
232
233 Ok(())
234 }
235
236 async fn post_stop(&mut self, _ctx: &mut Self::Context) -> Result<()> {
237 join_all(
238 self.children
239 .drain()
240 .map(|(address, join_handle)| terminate_actor(address, join_handle)),
241 )
242 .await;
243
244 info!("Node is stopped");
245
246 Ok(())
247 }
248}
249
250impl SubjectActor<NodeEvent> for Node {
251 fn observers_mut(&mut self) -> &mut ObserverSet<NodeEvent> {
252 &mut self.observers
253 }
254}
255
256impl<L> Handler<command::AddListener<L>> for Node
257where
258 L: IpcListener,
259{
260 type Result = bool;
261
262 async fn handle(
263 &mut self,
264 msg: command::AddListener<L>,
265 _ctx: &mut Self::Context,
266 ) -> Self::Result {
267 debug_trace!("Handle command {:?}", msg,);
268
269 let label = msg.0.local_endpoint();
270 if self.listener_labels.contains(label) {
271 false
272 } else {
273 self.listener_labels.insert(label.to_string());
274 self.listeners.push(Box::new(msg.0));
275 true
276 }
277 }
278}
279
280impl Handler<command::RemoveListener> for Node {
281 type Result = bool;
282
283 async fn handle(
284 &mut self,
285 msg: command::RemoveListener,
286 ctx: &mut Self::Context,
287 ) -> Self::Result {
288 debug_trace!("Handle command {:?}", msg);
289
290 let label = msg.0;
291 if self.listener_labels.remove(&label) {
292 ctx.abort_accept_task(&label);
293 true
294 } else {
295 false
296 }
297 }
298}
299
300impl<T> Handler<command::Connect<T>> for Node
301where
302 T: IpcConnection,
303{
304 type Result = Result<Address<Session>>;
305
306 async fn handle(&mut self, msg: command::Connect<T>, ctx: &mut Self::Context) -> Self::Result {
307 debug_trace!("Handle command {:?}", msg);
308
309 let command::Connect {
310 endpoint,
311 session_label,
312 ..
313 } = msg;
314
315 let connection = T::connect(&endpoint).await?;
316 let connection: Box<dyn IpcConnection> = Box::new(connection);
317 let address = self.create_session(connection, session_label, ctx).await?;
318
319 Ok(address)
320 }
321}
322
323impl<A> Handler<command::AddActor<A>> for Node
324where
325 A: Actor + RemoteAddressable,
326{
327 type Result = bool;
328
329 async fn handle(
330 &mut self,
331 msg: command::AddActor<A>,
332 _ctx: &mut Self::Context,
333 ) -> Self::Result {
334 debug_trace!("Handle command {:?}", msg);
335
336 if let Some(actor_mgr) = &self.actor_mgr
337 && let Ok(rx) = actor_mgr.send(msg).await
338 {
339 return rx.await.unwrap_or(false);
340 }
341
342 false
343 }
344}
345
346impl Handler<command::RemoveActor> for Node {
347 type Result = bool;
348
349 async fn handle(
350 &mut self,
351 msg: command::RemoveActor,
352 _ctx: &mut Self::Context,
353 ) -> Self::Result {
354 debug_trace!("Handle command {:?}", msg);
355
356 if let Some(actor_mgr) = &self.actor_mgr
357 && let Ok(rx) = actor_mgr.send(msg).await
358 {
359 return rx.await.unwrap_or(false);
360 }
361
362 false
363 }
364}
365
366impl<A> Handler<command::RemoteCreateActor<A>> for Node
367where
368 A: Actor + RemoteSpawnable,
369{
370 type Result = FutureMessageResult<command::RemoteCreateActor<A>>;
371
372 async fn handle(
373 &mut self,
374 msg: command::RemoteCreateActor<A>,
375 _ctx: &mut Self::Context,
376 ) -> Self::Result {
377 debug_trace!("Handle command RemoteCreateActor<{}>", ShortName::of::<A>());
378
379 let command::RemoteCreateActor {
380 session,
381 label,
382 config,
383 ..
384 } = msg;
385
386 let session = self.get_session(&session);
387
388 FutureMessageResult::new(async move {
389 session?
390 .send(session::command::RemoteCreateActor::new(label, config))
391 .await?
392 .await?
394 .map_err(Into::into)
395 })
396 }
397}
398
399impl<A> Handler<command::RemoteGetActor<A>> for Node
400where
401 A: Actor + RemoteAddressable,
402{
403 type Result = FutureMessageResult<command::RemoteGetActor<A>>;
404
405 async fn handle(
406 &mut self,
407 msg: command::RemoteGetActor<A>,
408 _ctx: &mut Self::Context,
409 ) -> Self::Result {
410 debug_trace!("Handle command GetRemoteActor");
411
412 let command::RemoteGetActor { session, actor, .. } = msg;
413
414 let session = self.get_session(&session);
415
416 FutureMessageResult::new(async move {
417 session?
418 .send(session::command::RemoteGetActor::new(actor))
419 .await?
420 .await?
422 .map_err(Into::into)
423 })
424 }
425}
426
427impl Handler<SupervisionEvent<Session>> for Node {
428 type Result = ();
429
430 async fn handle(
431 &mut self,
432 msg: SupervisionEvent<Session>,
433 _ctx: &mut Self::Context,
434 ) -> Self::Result {
435 debug_trace!("Handle supervision event {:?}", msg);
436
437 match msg {
438 SupervisionEvent::Warn(actor, e) => {
439 warn!("Session {} error: {}", actor.index(), e.report());
440 }
441 SupervisionEvent::Terminated(session, e) => {
442 if let Some(e) = e {
443 error!(
444 "Session {} is stopped with error: {}",
445 session.index(),
446 e.report()
447 );
448 }
449
450 self.sessions.retain(|_, _, v| v != &session);
451 self.children.remove(&session.clone().into());
452
453 self.notify_observers(NodeEvent::SessionDeleted(session))
454 .await;
455 }
456 _ => {}
457 }
458 }
459}