Skip to main content

riker/
actor.rs

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