Skip to main content

atomr_core/actor/
props.rs

1//! `Props` — a recipe for constructing an actor.
2//! akka.net: `Actor/Props.cs`.
3
4use std::fmt;
5use std::sync::Arc;
6
7use super::deploy::Deploy;
8use super::traits::Actor;
9use crate::supervision::SupervisorStrategy;
10
11pub type Factory<A> = Arc<dyn Fn() -> A + Send + Sync>;
12
13/// Typed props. The factory produces fresh `A` instances on initial start
14/// and on restart.
15pub struct Props<A: Actor> {
16    factory: Factory<A>,
17    pub dispatcher: Option<String>,
18    pub mailbox: Option<String>,
19    pub deploy: Deploy,
20    pub supervisor_strategy: Option<SupervisorStrategy>,
21}
22
23impl<A: Actor> Clone for Props<A> {
24    fn clone(&self) -> Self {
25        Self {
26            factory: self.factory.clone(),
27            dispatcher: self.dispatcher.clone(),
28            mailbox: self.mailbox.clone(),
29            deploy: self.deploy.clone(),
30            supervisor_strategy: self.supervisor_strategy.clone(),
31        }
32    }
33}
34
35impl<A: Actor> fmt::Debug for Props<A> {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        f.debug_struct("Props")
38            .field("dispatcher", &self.dispatcher)
39            .field("mailbox", &self.mailbox)
40            .field("deploy", &self.deploy)
41            .finish_non_exhaustive()
42    }
43}
44
45impl<A: Actor> Props<A> {
46    /// Create props from a zero-argument factory. Mirrors `Props.Create<T>(() => new T())`.
47    pub fn create<F>(factory: F) -> Self
48    where
49        F: Fn() -> A + Send + Sync + 'static,
50    {
51        Self {
52            factory: Arc::new(factory),
53            dispatcher: None,
54            mailbox: None,
55            deploy: Deploy::local(),
56            supervisor_strategy: None,
57        }
58    }
59
60    pub fn with_dispatcher(mut self, d: impl Into<String>) -> Self {
61        self.dispatcher = Some(d.into());
62        self
63    }
64
65    pub fn with_mailbox(mut self, m: impl Into<String>) -> Self {
66        self.mailbox = Some(m.into());
67        self
68    }
69
70    pub fn with_supervisor_strategy(mut self, s: SupervisorStrategy) -> Self {
71        self.supervisor_strategy = Some(s);
72        self
73    }
74
75    pub fn with_deploy(mut self, d: Deploy) -> Self {
76        self.deploy = d;
77        self
78    }
79
80    pub fn new_actor(&self) -> A {
81        (self.factory)()
82    }
83}
84
85/// Type-erased props — used when an actor needs to hold props of an
86/// unknown `A` (e.g. remote deployment, routers).
87#[derive(Clone)]
88pub struct BoxedProps {
89    pub spawn: Arc<dyn Fn() -> Arc<dyn std::any::Any + Send + Sync> + Send + Sync>,
90    pub dispatcher: Option<String>,
91    pub mailbox: Option<String>,
92    pub deploy: Deploy,
93}
94
95impl fmt::Debug for BoxedProps {
96    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97        f.debug_struct("BoxedProps").finish_non_exhaustive()
98    }
99}
100
101#[cfg(test)]
102mod tests {
103    use super::*;
104    use crate::actor::context::Context;
105
106    #[derive(Default)]
107    struct A(u32);
108
109    #[async_trait::async_trait]
110    impl Actor for A {
111        type Msg = ();
112        async fn handle(&mut self, _: &mut Context<Self>, _: ()) {}
113    }
114
115    #[test]
116    fn create_and_instantiate() {
117        let p = Props::create(|| A(5));
118        let a = p.new_actor();
119        assert_eq!(a.0, 5);
120    }
121}