1use std::fmt::{self, Debug};
10use std::result::Result as StdResult;
11
12use ahash::HashMap;
13use bytes::Bytes;
14use futures_util::{FutureExt, TryFutureExt};
15use tokio::time::{Duration, Instant};
16use tracing::{Instrument, info, warn};
17
18use acktor::{
19 Actor, ActorContext, ActorId, Address, ErrorReport, Handler, Message, Recipient, Sender,
20 SenderId, channel::oneshot, message::FutureMessageResult, utils::debug_trace,
21};
22use acktor_ipc_proto::{actor_message, ipc_message, node_message, utils as proto_utils};
23
24use crate::actor_handle::ActorHandle;
25use crate::codec::{Decode, DecodeContext, Encode};
26use crate::errors::{DecodeError, SessionError};
27use crate::ipc_method::IpcConnection;
28use crate::node::{
29 LabelMap,
30 factory::{self, Factory},
31};
32use crate::remote_actor::RemoteActorRegistry;
33use crate::remote_address::RemoteAddress;
34use crate::remote_message::RemoteMessage;
35
36pub mod command;
37
38mod session_handle;
39pub use session_handle::SessionHandle;
40
41mod context;
42use context::SessionContext;
43
44type Result<T> = StdResult<T, SessionError>;
45
46#[derive(Message)]
47#[result_type(())]
48struct ActorMessageResponse {
49 tag: u64,
50 result: StdResult<Bytes, String>,
51}
52
53impl Debug for ActorMessageResponse {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 f.debug_tuple("ActorMessageResponse")
56 .field(&self.tag)
57 .finish()
58 }
59}
60
61#[derive(Message)]
62#[result_type(())]
63struct CreateActorResponse {
64 tag: u64,
65 result: StdResult<ActorId, String>,
66}
67
68impl Debug for CreateActorResponse {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 f.debug_tuple("CreateActorResponse")
71 .field(&self.tag)
72 .finish()
73 }
74}
75
76pub struct Session {
78 connection: Box<dyn IpcConnection>,
79 factory: Address<Factory>,
80 registry: RemoteActorRegistry,
81 label_map: LabelMap,
82 tag: u64, decode_context: Option<DecodeContext>,
84 node_msg_res_tx_map: HashMap<u64, (oneshot::Sender<Result<RemoteAddress>>, Instant)>,
85 actor_msg_res_tx_map: HashMap<u64, (oneshot::Sender<Bytes>, Instant)>,
86}
87
88impl Session {
89 pub(crate) fn new(
92 connection: Box<dyn IpcConnection>,
93 factory: Address<Factory>,
94 registry: RemoteActorRegistry,
95 label_map: LabelMap,
96 ) -> Self {
97 Self {
98 connection,
99 factory,
100 registry,
101 label_map,
102 tag: 0,
103 decode_context: None,
104 actor_msg_res_tx_map: HashMap::default(),
105 node_msg_res_tx_map: HashMap::default(),
106 }
107 }
108
109 fn cleanup_expired_response_tx(&mut self) {
110 let now = Instant::now();
111
112 self.node_msg_res_tx_map
113 .retain(|_, (_, timestamp)| now.duration_since(*timestamp) < Duration::from_secs(30));
114 self.actor_msg_res_tx_map
115 .retain(|_, (_, timestamp)| now.duration_since(*timestamp) < Duration::from_secs(30));
116 }
117
118 fn next_tag(&mut self) -> u64 {
119 let tag = self.tag;
120 self.tag = self.tag.wrapping_add(1);
121 tag
122 }
123
124 async fn send_ipc_message(&mut self, ipc_msg: ipc_message::IpcMessage) -> Result<()> {
125 let encoded_ipc_msg = ipc_msg.encode_to_bytes(None)?;
126 self.connection
127 .send(encoded_ipc_msg)
128 .await
129 .map_err(SessionError::SendOutboundMessageFailed)?;
130
131 Ok(())
132 }
133
134 fn decode_context(&self) -> Result<&DecodeContext> {
135 self.decode_context
136 .as_ref()
137 .ok_or_else(|| DecodeError::MissingDecodeContext.into())
138 }
139
140 fn find_actor(&self, actor: &ActorHandle) -> Result<Recipient<RemoteMessage>> {
141 match actor {
142 ActorHandle::Index(actor_id) => {
143 if actor_id.is_remote() {
144 return Err(DecodeError::DecodeRemoteAddress.into());
145 }
146
147 self.registry
148 .get(*actor_id)
149 .ok_or_else(|| SessionError::ActorNotFound(actor_id.to_string()))
150 }
151
152 ActorHandle::Label(label) => self
153 .label_map
154 .get(label)
155 .ok_or_else(|| SessionError::ActorNotFound(label.clone()))
156 .and_then(|actor_id| {
157 self.registry
161 .get(*actor_id)
162 .ok_or_else(|| SessionError::ActorNotFound(label.clone()))
163 }),
164 }
165 }
166
167 async fn handle_node_message(
168 &mut self,
169 message: node_message::NodeMessage,
170 ctx: &mut <Self as Actor>::Context,
171 ) -> Result<()> {
172 match message.message {
173 Some(node_message::MessageType::CreateActor(node_message::CreateActor {
174 label,
175 r#type,
176 config,
177 tag,
178 })) => {
179 let factory = self.factory.clone();
180 let address = ctx.address();
181
182 tokio::spawn(
184 async move {
185 factory
186 .send(factory::CreateActor {
187 label,
188 r#type,
189 config,
190 })
191 .await?
192 .await?
193 }
194 .then(move |result| async move {
195 address
200 .do_send(CreateActorResponse {
201 tag,
202 result: result.map_err(|e| e.report()),
203 })
204 .await
205 })
206 .inspect_err(|e| {
207 warn!(
210 "Could not send `NodeMessageResponse::CreateActor` to remote peer: {}",
211 e.report()
212 );
213 })
214 .in_current_span(),
215 );
216
217 Ok(())
218 }
219
220 Some(node_message::MessageType::GetActor(node_message::GetActor { actor, tag })) => {
221 let actor = match actor {
223 Some(proto_utils::ActorHandle { handle }) => match handle {
224 Some(proto_utils::ActorHandleType::Index(actor_id)) => {
225 ActorHandle::Index(actor_id)
226 }
227 Some(proto_utils::ActorHandleType::Label(label)) => {
228 ActorHandle::Label(label)
229 }
230 None => {
231 return Err(DecodeError::from(
232 "missing field `handle` in `ActorHandle`",
233 )
234 .into());
235 }
236 },
237
238 _ => {
239 return Err(DecodeError::from(
240 "missing field `actor` in `NodeMessage::GetActor`",
241 )
242 .into());
243 }
244 };
245
246 let result = self.find_actor(&actor).map(|recipient| recipient.index());
247
248 let ipc_msg = ipc_message::IpcMessage::node_message_response(
249 node_message::NodeMessageResponse::get_actor(
250 tag,
251 result.map_err(|e| e.report()),
252 ),
253 );
254
255 self.send_ipc_message(ipc_msg).await.inspect_err(|e| {
256 warn!(
259 "Could not send `NodeMessageResponse::GetActor` to remote peer: {}",
260 e.report()
261 );
262 })
263 }
264
265 _ => Err(DecodeError::from("missing field `message` in `NodeMessage`").into()),
266 }
267 }
268
269 fn _handle_node_message_response(
270 &mut self,
271 tag: u64,
272 result: Option<node_message::ResultType>,
273 name: &str,
274 ) -> Result<()> {
275 let (sender, _) = self
276 .node_msg_res_tx_map
277 .remove(&tag)
278 .ok_or(SessionError::InvalidNodeMsgResTxTag(tag))?;
282
283 let result = match result {
286 Some(node_message::ResultType::ActorId(actor_id)) => match self.decode_context() {
287 Ok(ctx) => ctx.create_remote_address(actor_id).map_err(Into::into),
288 Err(e) => Err(e),
289 },
290 Some(node_message::ResultType::Err(e)) => Err(SessionError::RemotePeerError(e)),
291
292 _ => Err(DecodeError::from(format!(
293 "missing field `result` in `NodeMessageResponse::{}`",
294 name
295 ))
296 .into()),
297 };
298
299 sender
300 .send(result)
301 .map_err(|_| SessionError::ForwardNodeMsgResFailed)
304 }
305
306 fn handle_node_message_response(
307 &mut self,
308 response: node_message::NodeMessageResponse,
309 _ctx: &mut <Self as Actor>::Context,
310 ) -> Result<()> {
311 let tag = response.tag;
312
313 match response.response {
314 Some(node_message::ResponseType::CreateActor(node_message::ResultRemoteAddress {
315 result,
316 })) => self._handle_node_message_response(tag, result, "CreateActor"),
317
318 Some(node_message::ResponseType::GetActor(node_message::ResultRemoteAddress {
319 result,
320 })) => self._handle_node_message_response(tag, result, "GetActor"),
321
322 _ => Err(DecodeError::from("missing field `response` in `NodeMessageResponse`").into()),
323 }
324 }
325
326 async fn handle_actor_message(
327 &mut self,
328 message: actor_message::ActorMessage,
329 ctx: &mut <Self as Actor>::Context,
330 ) -> Result<()> {
331 let actor_message::ActorMessage {
332 actor_id,
333 message_id,
334 message,
335 tag,
336 } = message;
337
338 match tag {
339 Some(tag) => {
340 let address = ctx.address();
343 let recipient = self.find_actor(&ActorHandle::Index(actor_id));
344 let decode_context = self.decode_context().cloned();
345 let (tx, rx) = oneshot::channel();
346
347 tokio::spawn(
349 async move {
350 recipient?
351 .do_send(
352 RemoteMessage::send(actor_id, message_id, message, tx)
353 .with_context(decode_context?),
354 )
355 .await
356 .map_err(|e| SessionError::ForwardInboundMessageFailed(e.into()))?;
357
358 let result = rx
359 .await
360 .map_err(|e| SessionError::HandleInboundMessageFailed(e.into()))?;
361
362 Ok::<Bytes, SessionError>(result)
363 }
364 .then(move |result| async move {
365 address
370 .do_send(ActorMessageResponse {
371 tag,
372 result: result.map_err(|e| e.report()),
373 })
374 .await
375 })
376 .inspect_err(|e| {
377 warn!(
380 "Could not send `ActorMessageResponse` to remote peer: {}",
381 e.report()
382 );
383 })
384 .in_current_span(),
385 );
386
387 Ok(())
388 }
389
390 None => {
391 self.find_actor(&ActorHandle::Index(actor_id))?
396 .do_send(
397 RemoteMessage::do_send(actor_id, message_id, message)
398 .with_context(self.decode_context()?.clone()),
399 )
400 .await
401 .map_err(|e| SessionError::ForwardInboundMessageFailed(e.into()))
402 }
403 }
404 }
405
406 async fn handle_actor_message_response(
407 &mut self,
408 response: actor_message::ActorMessageResponse,
409 _ctx: &mut <Self as Actor>::Context,
410 ) -> Result<()> {
411 let tag = response.tag;
412
413 let (sender, _) = self
414 .actor_msg_res_tx_map
415 .remove(&tag)
416 .ok_or(SessionError::InvalidActorMsgResTxTag(tag))?;
420
421 let result: Result<_> = match response.response {
424 Some(actor_message::ResponseType::Ok(bytes)) => Ok(bytes),
425 Some(actor_message::ResponseType::Err(err)) => Err(SessionError::RemotePeerError(err)),
426 None => {
427 Err(DecodeError::from("missing field `response` in `ActorMessageResponse`").into())
428 }
429 };
430
431 match result {
434 Ok(bytes) => sender
435 .send(bytes)
436 .map_err(|_| SessionError::ForwardActorMessageResFailed),
437 Err(e) => sender
438 .send_err(e)
439 .map_err(|_| SessionError::ForwardActorMessageResFailed),
440 }
441 }
442
443 async fn handle_ipc_message(
444 &mut self,
445 message: Bytes,
446 ctx: &mut <Self as Actor>::Context,
447 ) -> Result<()> {
448 let ipc_message = ipc_message::IpcMessage::decode(message, None)?;
449
450 match ipc_message.message {
451 Some(ipc_message::IpcMessageType::NodeMessage(message)) => {
452 self.handle_node_message(message, ctx).await
453 }
454 Some(ipc_message::IpcMessageType::NodeMessageResponse(response)) => {
455 self.handle_node_message_response(response, ctx)
456 }
457 Some(ipc_message::IpcMessageType::ActorMessage(message)) => {
458 self.handle_actor_message(message, ctx).await
459 }
460 Some(ipc_message::IpcMessageType::ActorMessageResponse(response)) => {
461 self.handle_actor_message_response(response, ctx).await
462 }
463 _ => Err(DecodeError::from("missing field `message` in `IpcMessage`").into()),
464 }
465 }
466}
467
468impl Actor for Session {
469 type Context = SessionContext;
470 type Error = SessionError;
471
472 async fn post_start(&mut self, ctx: &mut Self::Context) -> Result<()> {
473 info!("Session {} is started", self.connection.peer_endpoint());
474
475 self.decode_context = Some(DecodeContext::new(ctx.address(), self.registry.clone()));
476
477 Ok(())
478 }
479
480 async fn post_stop(&mut self, _ctx: &mut Self::Context) -> Result<()> {
481 self.connection
482 .close()
483 .await
484 .map_err(SessionError::IoError)?;
485
486 info!("Session {} is stopped", self.connection.peer_endpoint());
487
488 Ok(())
489 }
490}
491
492impl Handler<command::CreateRemoteActor> for Session {
497 type Result = FutureMessageResult<command::CreateRemoteActor>;
498
499 async fn handle(
500 &mut self,
501 msg: command::CreateRemoteActor,
502 _ctx: &mut <Self as Actor>::Context,
503 ) -> Self::Result {
504 debug_trace!("Handle command {:?}", msg);
505
506 let command::CreateRemoteActor {
507 label,
508 r#type,
509 config,
510 } = msg;
511
512 let (tx, rx) = oneshot::channel();
513
514 let tag = self.next_tag();
515 let ipc_msg = ipc_message::IpcMessage::node_message(
516 node_message::NodeMessage::create_actor(label, r#type, config, tag),
517 );
518
519 if let Err(e) = self.send_ipc_message(ipc_msg).await {
520 warn!(
521 "Could not send `NodeMessage::CreateActor` to remote peer: {}",
522 e.report()
523 );
524 if let Err(e) = tx.send(Err(e)) {
527 warn!(
530 "Could not report the error in `Handler<CreateRemoteActor>` to original \
531 sender: {}",
532 e.report()
533 );
534 }
535 } else {
536 self.node_msg_res_tx_map.insert(tag, (tx, Instant::now()));
537 }
538
539 FutureMessageResult::new(rx.map(|r| r.unwrap_or_else(|e| Err(e.into()))))
540 }
541}
542
543impl Handler<command::GetRemoteActor> for Session {
548 type Result = FutureMessageResult<command::GetRemoteActor>;
549
550 async fn handle(
551 &mut self,
552 msg: command::GetRemoteActor,
553 _ctx: &mut <Self as Actor>::Context,
554 ) -> Self::Result {
555 debug_trace!("Handle command {:?}", msg);
556
557 let command::GetRemoteActor { actor } = msg;
558
559 let (tx, rx) = oneshot::channel();
560
561 let tag = self.next_tag();
562 let ipc_msg = match &actor {
563 ActorHandle::Index(actor_id) => ipc_message::IpcMessage::node_message(
564 node_message::NodeMessage::get_actor_with_index(*actor_id, tag),
565 ),
566 ActorHandle::Label(label) => ipc_message::IpcMessage::node_message(
567 node_message::NodeMessage::get_actor_with_label(label.clone(), tag),
568 ),
569 };
570
571 if let Err(e) = self.send_ipc_message(ipc_msg).await {
572 warn!(
573 "Could not send `NodeMessage::GetActor` to remote peer: {}",
574 e.report()
575 );
576 if let Err(e) = tx.send(Err(e)) {
579 warn!(
582 "Could not report the error in `Handler<GetRemoteActor>` to original sender: \
583 {}",
584 e.report()
585 );
586 }
587 } else {
588 self.node_msg_res_tx_map.insert(tag, (tx, Instant::now()));
589 }
590
591 FutureMessageResult::new(rx.map(|r| r.unwrap_or_else(|e| Err(e.into()))))
592 }
593}
594
595impl Handler<RemoteMessage> for Session {
600 type Result = ();
601
602 async fn handle(
603 &mut self,
604 msg: RemoteMessage,
605 _ctx: &mut <Self as Actor>::Context,
606 ) -> Self::Result {
607 debug_trace!("Handle command {:?}", msg);
608
609 let RemoteMessage {
610 actor_id,
611 message_id,
612 message,
613 result_tx,
614 ..
615 } = msg;
616
617 match result_tx {
618 Some(tx) => {
619 let tag = self.next_tag();
622 let ipc_msg = ipc_message::IpcMessage::actor_message(
623 actor_message::ActorMessage::send(actor_id, message_id, message, tag),
624 );
625
626 if let Err(e) = self.send_ipc_message(ipc_msg).await {
627 warn!(
628 "Could not send `ActorMessage` to remote peer: {}",
629 e.report()
630 );
631 if let Err(e) = tx.send_err(e) {
636 warn!(
639 "Could not report the error in `Handler<RemoteMessage>` to original \
640 sender: {}",
641 e.report()
642 );
643 }
644
645 return;
646 }
647
648 self.actor_msg_res_tx_map.insert(tag, (tx, Instant::now()));
649 }
650
651 None => {
652 let ipc_msg = ipc_message::IpcMessage::actor_message(
655 actor_message::ActorMessage::do_send(actor_id, message_id, message),
656 );
657
658 if let Err(e) = self.send_ipc_message(ipc_msg).await {
659 warn!(
662 "Could not do_send `ActorMessage` to remote peer: {}",
663 e.report()
664 );
665 }
666 }
667 }
668 }
669}
670
671impl Handler<CreateActorResponse> for Session {
672 type Result = ();
673
674 async fn handle(&mut self, msg: CreateActorResponse, _ctx: &mut Self::Context) -> Self::Result {
675 debug_trace!("Handle command {:?}", msg);
676
677 let CreateActorResponse { tag, result } = msg;
678
679 let ipc_msg = ipc_message::IpcMessage::node_message_response(
680 node_message::NodeMessageResponse::create_actor(tag, result),
681 );
682
683 if let Err(e) = self.send_ipc_message(ipc_msg).await {
684 warn!(
687 "Could not send `NodeMessageResponse::CreateActor` to remote peer: {}",
688 e.report()
689 )
690 }
691 }
692}
693
694impl Handler<ActorMessageResponse> for Session {
695 type Result = ();
696
697 async fn handle(
698 &mut self,
699 msg: ActorMessageResponse,
700 _ctx: &mut <Self as Actor>::Context,
701 ) -> Self::Result {
702 debug_trace!("Handle command {:?}", msg);
703
704 let ActorMessageResponse { tag, result } = msg;
705
706 let ipc_msg = ipc_message::IpcMessage::actor_message_response(
707 actor_message::ActorMessageResponse::new(tag, result),
708 );
709
710 if let Err(e) = self.send_ipc_message(ipc_msg).await {
711 warn!(
712 "Could not send `ActorMessageResponse` to remote peer: {}",
713 e.report()
714 )
715 }
716 }
717}
718
719#[cfg(test)]
720mod tests {
721 use super::*;
722
723 #[test]
724 fn test_debug_str() {
725 let ok = ActorMessageResponse {
726 tag: 42,
727 result: Ok(Bytes::from_static(b"payload")),
728 };
729 assert_eq!(format!("{ok:?}"), "ActorMessageResponse(42)");
730
731 let err = ActorMessageResponse {
732 tag: 7,
733 result: Err("boom".to_string()),
734 };
735 assert_eq!(format!("{err:?}"), "ActorMessageResponse(7)");
736
737 let ok = CreateActorResponse {
738 tag: 42,
739 result: Ok(1234),
740 };
741 assert_eq!(format!("{ok:?}"), "CreateActorResponse(42)");
742
743 let err = CreateActorResponse {
744 tag: 7,
745 result: Err("boom".to_string()),
746 };
747 assert_eq!(format!("{err:?}"), "CreateActorResponse(7)");
748 }
749}