actors_rs/actor/
mod.rs

1pub(crate) mod actor_cell;
2pub(crate) mod actor_ref;
3pub(crate) mod channel;
4pub(crate) mod macros;
5pub(crate) mod props;
6pub(crate) mod selection;
7pub(crate) mod uri;
8
9use std::fmt;
10
11use crate::validate::InvalidName;
12
13// Public riker::actor API (plus the pub data types in this file)
14pub use self::{
15    actor_cell::Context,
16    channel::{
17        channel, All, Channel, ChannelMsg, ChannelRef, DLChannelMsg, DeadLetter, EventsChannel,
18        Publish, Subscribe, SysTopic, Topic, Unsubscribe, UnsubscribeAll,
19    },
20    macros::actor,
21    props::{ActorArgs, ActorFactory, ActorFactoryArgs, ActorProducer, BoxActorProd, Props},
22    selection::{ActorSelection, ActorSelectionFactory},
23    uri::{ActorId, ActorPath, ActorUri},
24};
25use crate::actor_ref::BasicActorRef;
26use crate::actor_ref::Sender;
27use crate::system::SystemMsg;
28use crate::Message;
29
30pub type MsgResult<T> = Result<(), MsgError<T>>;
31
32/// Internal message error when a message can't be added to an actor's mailbox
33#[doc(hidden)]
34#[derive(Clone, Debug)]
35pub struct MsgError<T> {
36    pub msg: T,
37}
38
39impl<T> MsgError<T> {
40    pub const fn new(msg: T) -> Self {
41        Self { msg }
42    }
43}
44
45impl<T> fmt::Display for MsgError<T> {
46    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
47        f.write_str("The actor does not exist. It may have been terminated")
48    }
49}
50
51/// Error type when an `try_tell` fails on `Option<ActorRef<Msg>>`
52#[derive(Debug)]
53pub struct TryMsgError<T> {
54    pub msg: T,
55}
56
57impl<T> TryMsgError<T> {
58    pub const fn new(msg: T) -> Self {
59        Self { msg }
60    }
61}
62
63impl<T> fmt::Display for TryMsgError<T> {
64    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65        f.write_str("Option<ActorRef> is None")
66    }
67}
68
69/// Error type when an actor fails to start during `actor_of`.
70#[derive(Debug)]
71pub enum CreateError {
72    Panicked,
73    System,
74    InvalidName(String),
75    AlreadyExists(ActorPath),
76}
77
78impl fmt::Display for CreateError {
79    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80        match *self {
81            Self::Panicked => {
82                f.write_str("Failed to create actor. Cause: Actor panicked while starting")
83            }
84            Self::System => f.write_str("Failed to create actor. Cause: System failure"),
85            Self::InvalidName(ref name) => f.write_str(&format!(
86                "Failed to create actor. Cause: Invalid actor name ({})",
87                name
88            )),
89            Self::AlreadyExists(ref path) => f.write_str(&format!(
90                "Failed to create actor. Cause: An actor at the same path already exists ({})",
91                path
92            )),
93        }
94    }
95}
96
97impl From<InvalidName> for CreateError {
98    fn from(err: InvalidName) -> Self {
99        Self::InvalidName(err.name)
100    }
101}
102
103/// Error type when an actor fails to restart.
104#[derive(Debug)]
105pub struct RestartError;
106
107impl fmt::Display for RestartError {
108    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
109        f.write_str("Failed to restart actor. Cause: Actor panicked while starting")
110    }
111}
112
113pub trait Actor: Send + 'static {
114    type Msg: Message;
115
116    /// Invoked when an actor is being started by the system.
117    ///
118    /// Any initialization inherent to the actor's role should be
119    /// performed here.
120    ///
121    /// Panics in `pre_start` do not invoke the
122    /// supervision strategy and the actor will be terminated.
123    fn pre_start(&mut self, _ctx: &Context<Self::Msg>) {}
124
125    /// Invoked after an actor has started.
126    ///
127    /// Any post initialization can be performed here, such as writing
128    /// to a log file, emmitting metrics.
129    ///
130    /// Panics in `post_start` follow the supervision strategy.
131    fn post_start(&mut self, _ctx: &Context<Self::Msg>) {}
132
133    /// Invoked after an actor has been stopped.
134    fn post_stop(&mut self) {}
135
136    /// Return a supervisor strategy that will be used when handling failed child actors.
137    fn supervisor_strategy(&self) -> Strategy {
138        Strategy::Restart
139    }
140
141    /// Invoked when an actor receives a message
142    ///
143    /// It is guaranteed that only one message in the actor's mailbox is processed
144    /// at any one time, including `recv` and `sys_recv`.
145    fn recv(&mut self, ctx: &Context<Self::Msg>, msg: Self::Msg, sender: Sender);
146
147    /// Invoked when an actor receives a system message
148    ///
149    /// It is guaranteed that only one message in the actor's mailbox is processed
150    /// at any one time, including `recv` and `sys_recv`.
151    fn sys_recv(&mut self, _ctx: &Context<Self::Msg>, _msg: SystemMsg, _sender: Sender) {}
152}
153
154impl<A: Actor + ?Sized> Actor for Box<A> {
155    type Msg = A::Msg;
156
157    fn pre_start(&mut self, ctx: &Context<Self::Msg>) {
158        (**self).pre_start(ctx);
159    }
160
161    fn post_start(&mut self, ctx: &Context<Self::Msg>) {
162        (**self).post_start(ctx)
163    }
164
165    fn post_stop(&mut self) {
166        (**self).post_stop()
167    }
168
169    fn supervisor_strategy(&self) -> Strategy {
170        (**self).supervisor_strategy()
171    }
172
173    fn recv(&mut self, ctx: &Context<Self::Msg>, msg: Self::Msg, sender: Option<BasicActorRef>) {
174        (**self).recv(ctx, msg, sender)
175    }
176
177    fn sys_recv(
178        &mut self,
179        ctx: &Context<Self::Msg>,
180        msg: SystemMsg,
181        sender: Option<BasicActorRef>,
182    ) {
183        (**self).sys_recv(ctx, msg, sender)
184    }
185}
186
187/// Receive and handle a specific message type
188///
189/// This trait is typically used in conjuction with the #[actor]
190/// attribute macro and implemented for each message type to receive.
191///
192/// # Examples
193///
194/// ```
195/// # use actors_rs::*;
196///
197/// #[derive(Clone, Debug)]
198/// pub struct Foo;
199/// #[derive(Clone, Debug)]
200/// pub struct Bar;
201/// #[actor(Foo, Bar)] // <-- set our actor to receive Foo and Bar types
202/// #[derive(Default)]
203/// struct MyActor;
204///
205/// impl Actor for MyActor {
206///     type Msg = MyActorMsg; // <-- MyActorMsg is provided for us
207///
208///     fn recv(&mut self,
209///                 ctx: &Context<Self::Msg>,
210///                 msg: Self::Msg,
211///                 sender: Sender) {
212///         self.receive(ctx, msg, sender); // <-- call the respective implementation
213///     }
214/// }
215///
216/// impl Receive<Foo> for MyActor {
217///     type Msg = MyActorMsg;
218///
219///     fn receive(&mut self,
220///                 ctx: &Context<Self::Msg>,
221///                 msg: Foo, // <-- receive Foo
222///                 sender: Sender) {
223///         println!("Received a Foo");
224///     }
225/// }
226///
227/// impl Receive<Bar> for MyActor {
228///     type Msg = MyActorMsg;
229///
230///     fn receive(&mut self,
231///                 ctx: &Context<Self::Msg>,
232///                 msg: Bar, // <-- receive Bar
233///                 sender: Sender) {
234///         println!("Received a Bar");
235///     }
236/// }
237///
238/// // main
239/// let sys = ActorSystem::new().unwrap();
240/// let actor = sys.actor_of::<MyActor>("my-actor").unwrap();
241///
242/// actor.tell(Foo, None);
243/// actor.tell(Bar, None);
244/// ```
245pub trait Receive<Msg: Message> {
246    type Msg: Message;
247
248    /// Invoked when an actor receives a message
249    ///
250    /// It is guaranteed that only one message in the actor's mailbox is processed
251    /// at any one time, including `receive`, `other_receive` and `system_receive`.
252    fn receive(&mut self, ctx: &Context<Self::Msg>, msg: Msg, sender: Option<BasicActorRef>);
253}
254
255/// The actor trait object
256pub type BoxActor<Msg> = Box<dyn Actor<Msg = Msg> + Send>;
257
258/// Supervision strategy
259///
260/// Returned in `Actor.supervision_strategy`
261pub enum Strategy {
262    /// Stop the child actor
263    Stop,
264
265    /// Attempt to restart the child actor
266    Restart,
267
268    /// Escalate the failure to a parent
269    Escalate,
270}