Skip to main content

atomr_core/actor/
props.rs

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