mm1_sup/
uniform.rs

1use crate::common::child_spec::ChildSpec;
2mod sup_actor;
3mod sup_context;
4
5pub use sup_actor::uniform_sup;
6pub use sup_context::UniformSupContext;
7
8pub mod child_type {
9    use mm1_common::types::AnyError;
10    use tokio::time::Instant;
11
12    use crate::common::factory::ActorFactory;
13    use crate::common::restart_intensity::{RestartIntensity, RestartStats};
14
15    pub trait UniformChildType<A> {
16        type Data;
17
18        fn new_data(&self, args: A) -> Self::Data;
19        fn make_runnable<F>(
20            &self,
21            factory: &F,
22            data: &mut Self::Data,
23        ) -> Result<F::Runnable, AnyError>
24        where
25            F: ActorFactory<Args = A>;
26        fn should_restart(
27            &self,
28            data: &mut Self::Data,
29            normal_exit: bool,
30        ) -> Result<bool, AnyError>;
31    }
32
33    #[derive(Debug, Clone, Copy)]
34    pub struct Temporary;
35
36    pub type Permanent = Restarting<true>;
37
38    pub type Transient = Restarting<false>;
39
40    impl<A> UniformChildType<A> for Temporary {
41        type Data = Option<A>;
42
43        fn new_data(&self, args: A) -> Self::Data {
44            Some(args)
45        }
46
47        fn make_runnable<F>(
48            &self,
49            factory: &F,
50            data: &mut Self::Data,
51        ) -> Result<F::Runnable, AnyError>
52        where
53            F: ActorFactory<Args = A>,
54        {
55            let args = data.take().ok_or_else(|| eyre::format_err!("args gone"))?;
56            let runnable = factory.produce(args);
57            Ok(runnable)
58        }
59
60        fn should_restart(
61            &self,
62            _data: &mut Self::Data,
63            _normal_exit: bool,
64        ) -> Result<bool, AnyError> {
65            Ok(false)
66        }
67    }
68
69    #[doc(hidden)]
70    pub struct Restarting<const RESTART_ON_NORMAL_EXIT: bool> {
71        restart_intensity: RestartIntensity,
72    }
73
74    impl<const RESTART_ON_NORMAL_EXIT: bool, A> UniformChildType<A>
75        for Restarting<RESTART_ON_NORMAL_EXIT>
76    where
77        A: Clone,
78    {
79        type Data = ChildData<A>;
80
81        fn new_data(&self, args: A) -> Self::Data {
82            let restarts = self.restart_intensity.new_stats();
83            ChildData { args, restarts }
84        }
85
86        fn make_runnable<F>(
87            &self,
88            factory: &F,
89            data: &mut Self::Data,
90        ) -> Result<F::Runnable, AnyError>
91        where
92            F: ActorFactory<Args = A>,
93        {
94            let args = data.args.clone();
95            let runnable = factory.produce(args);
96            Ok(runnable)
97        }
98
99        fn should_restart(
100            &self,
101            data: &mut Self::Data,
102            _normal_exit: bool,
103        ) -> Result<bool, AnyError> {
104            self.restart_intensity
105                .report_exit(&mut data.restarts, Instant::now())?;
106            Ok(RESTART_ON_NORMAL_EXIT)
107        }
108    }
109
110    #[doc(hidden)]
111    pub struct ChildData<A> {
112        args:     A,
113        restarts: RestartStats,
114    }
115}
116
117pub struct UniformSup<F, C> {
118    pub child_spec: ChildSpec<F, C>,
119}
120
121impl<F, C> UniformSup<F, C> {
122    pub fn new(child_spec: ChildSpec<F, C>) -> Self {
123        Self { child_spec }
124    }
125}
126
127impl<F, C> Clone for UniformSup<F, C>
128where
129    ChildSpec<F, C>: Clone,
130{
131    fn clone(&self) -> Self {
132        Self {
133            child_spec: self.child_spec.clone(),
134        }
135    }
136}