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}