Skip to main content

ractor/actor/
actor_ref.rs

1// Copyright (c) Sean Lawlor
2//
3// This source code is licensed under both the MIT license found in the
4// LICENSE-MIT file in the root directory of this source tree.
5
6//! [ActorRef] is a strongly-typed wrapper over an [ActorCell]
7
8use std::marker::PhantomData;
9
10use super::ActorCell;
11use crate::ActorName;
12use crate::Message;
13use crate::MessagingErr;
14use crate::SupervisionEvent;
15
16/// An [ActorRef] is a strongly-typed wrapper over an [ActorCell]
17/// to provide some syntactic wrapping on the requirement to pass
18/// the actor's message type everywhere.
19///
20/// An [ActorRef] is the primary means of communication typically used
21/// when interfacing with [super::Actor]s
22pub struct ActorRef<TMessage> {
23    pub(crate) inner: ActorCell,
24    _tactor: PhantomData<fn() -> TMessage>,
25}
26
27impl<TMessage> Clone for ActorRef<TMessage> {
28    fn clone(&self) -> Self {
29        ActorRef {
30            inner: self.inner.clone(),
31            _tactor: PhantomData,
32        }
33    }
34}
35
36impl<TMessage> std::ops::Deref for ActorRef<TMessage> {
37    type Target = ActorCell;
38
39    fn deref(&self) -> &Self::Target {
40        &self.inner
41    }
42}
43
44impl<TMessage> From<ActorCell> for ActorRef<TMessage> {
45    fn from(value: ActorCell) -> Self {
46        Self {
47            inner: value,
48            _tactor: PhantomData,
49        }
50    }
51}
52
53impl<TActor> From<ActorRef<TActor>> for ActorCell {
54    fn from(value: ActorRef<TActor>) -> Self {
55        value.inner
56    }
57}
58
59impl<TMessage> std::fmt::Debug for ActorRef<TMessage> {
60    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61        self.inner.fmt(f)
62    }
63}
64
65impl<TMessage> PartialEq for ActorRef<TMessage> {
66    fn eq(&self, other: &Self) -> bool {
67        self.inner == other.inner
68    }
69}
70
71impl<TMessage> Eq for ActorRef<TMessage> {}
72
73impl<TMessage> std::hash::Hash for ActorRef<TMessage> {
74    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
75        self.inner.hash(state);
76    }
77}
78
79impl<TMessage> ActorRef<TMessage> {
80    /// Retrieve a cloned [ActorCell] representing this [ActorRef]
81    pub fn get_cell(&self) -> ActorCell {
82        self.inner.clone()
83    }
84
85    /// Notify the supervisor and all monitors that a supervision event occurred.
86    /// Monitors receive a reduced copy of the supervision event which won't contain
87    /// the [crate::actor::BoxedState] and collapses the [crate::ActorProcessingErr]
88    /// exception to a [String]
89    ///
90    /// * `evt` - The event to send to this [crate::Actor]'s supervisors
91    pub fn notify_supervisor_and_monitors(&self, evt: SupervisionEvent) {
92        self.inner.notify_supervisor(evt)
93    }
94}
95
96impl<TMessage> crate::actor::ActorRef<TMessage>
97where
98    TMessage: Message,
99{
100    /// Send a strongly-typed message, constructing the boxed message on the fly
101    ///
102    /// * `message` - The message to send
103    ///
104    /// Returns [Ok(())] on successful message send, [Err(MessagingErr)] otherwise
105    pub fn send_message(&self, message: TMessage) -> Result<(), MessagingErr<TMessage>> {
106        // Use unchecked version - ActorRef<TMessage> provides compile-time type safety
107        self.inner.inner.send_message_unchecked::<TMessage>(message)
108    }
109
110    // ========================== General Actor Operation Aliases ========================== //
111
112    // -------------------------- ActorRegistry -------------------------- //
113
114    /// Try and retrieve a strongly-typed actor from the registry.
115    ///
116    /// Alias of [crate::registry::where_is]
117    pub fn where_is(name: ActorName) -> Option<crate::actor::ActorRef<TMessage>> {
118        if let Some(actor) = crate::registry::where_is(name) {
119            // check the type id when pulling from the registry
120            let check = actor.is_message_type_of::<TMessage>();
121            if check.is_none() || matches!(check, Some(true)) {
122                return Some(actor.into());
123            }
124        }
125        None
126    }
127}