agner_actors/
exit.rs

1use std::sync::Arc;
2
3use crate::actor_id::ActorID;
4use crate::imports::ArcError;
5
6mod into_exit;
7
8/// An reason an actor exited.
9///
10/// Exit reasons are supposed to be cheaply cloneable, as when an actor fails each linked actor
11/// receives a signal containing a clone of that reason.
12#[derive(Debug, Clone, thiserror::Error)]
13pub enum Exit {
14    #[error("Well known")]
15    Standard(#[source] WellKnown),
16
17    #[error("Actor backend failure")]
18    Backend(#[source] BackendFailure),
19
20    #[error("Custom")]
21    Custom(#[source] ArcError),
22}
23
24/// Standard exit reasons.
25#[derive(Debug, Clone, thiserror::Error)]
26pub enum WellKnown {
27    #[error("Normal")]
28    Normal,
29
30    #[error("Kill")]
31    Kill,
32
33    #[error("Exited: {}", _0)]
34    Linked(ActorID, #[source] Box<Exit>),
35
36    #[error("No Actor")]
37    NoActor,
38
39    #[error("Shutdown")]
40    Shutdown(#[source] Shutdown),
41}
42
43#[derive(Debug, Clone, Default, thiserror::Error)]
44#[error("Shutdown")]
45pub struct Shutdown(#[source] pub Option<ArcError>);
46
47#[derive(Debug, Clone, thiserror::Error)]
48pub enum BackendFailure {
49    #[error("Inbox Full: {}", _0)]
50    InboxFull(&'static str),
51
52    #[error("Rx Closed: {}", _0)]
53    RxClosed(&'static str),
54}
55
56impl Default for Exit {
57    fn default() -> Self {
58        Self::Standard(WellKnown::Normal)
59    }
60}
61impl From<WellKnown> for Exit {
62    fn from(e: WellKnown) -> Self {
63        Self::Standard(e)
64    }
65}
66impl From<BackendFailure> for Exit {
67    fn from(e: BackendFailure) -> Self {
68        Self::Backend(e)
69    }
70}
71impl From<Shutdown> for Exit {
72    fn from(shutdown: Shutdown) -> Self {
73        WellKnown::Shutdown(shutdown).into()
74    }
75}
76
77impl Exit {
78    pub fn is_normal(&self) -> bool {
79        matches!(self, Self::Standard(WellKnown::Normal))
80    }
81    pub fn is_kill(&self) -> bool {
82        matches!(self, Self::Standard(WellKnown::Kill))
83    }
84    pub fn is_linked(&self) -> bool {
85        matches!(self, Self::Standard(WellKnown::Linked(_, _)))
86    }
87    pub fn is_no_actor(&self) -> bool {
88        matches!(self, Self::Standard(WellKnown::NoActor))
89    }
90    pub fn is_shutdown(&self) -> bool {
91        matches!(self, Self::Standard(WellKnown::Shutdown(_)))
92    }
93    pub fn is_custom(&self) -> bool {
94        matches!(self, Self::Custom(_))
95    }
96
97    pub fn normal() -> Self {
98        WellKnown::Normal.into()
99    }
100    pub fn kill() -> Self {
101        WellKnown::Kill.into()
102    }
103    pub fn linked(who: ActorID, reason: impl Into<Box<Self>>) -> Self {
104        WellKnown::Linked(who, reason.into()).into()
105    }
106    pub fn no_actor() -> Self {
107        WellKnown::NoActor.into()
108    }
109    pub fn shutdown() -> Self {
110        let shutdown = Shutdown::new();
111        WellKnown::Shutdown(shutdown).into()
112    }
113    pub fn shutdown_with_source(source: ArcError) -> Self {
114        let shutdown = Shutdown::new().with_source(source);
115        WellKnown::Shutdown(shutdown).into()
116    }
117
118    pub fn custom<E: std::error::Error + Send + Sync + 'static>(e: E) -> Exit {
119        Self::Custom(Arc::new(e))
120    }
121
122    pub fn from_message<S>(message: S) -> Exit
123    where
124        S: Into<String>,
125    {
126        let s = message.into();
127        let b: Box<dyn std::error::Error + Send + Sync + 'static> = s.into();
128        Self::Custom(b.into())
129    }
130}
131
132impl Shutdown {
133    pub fn new() -> Self {
134        Default::default()
135    }
136    pub fn with_source(self, source: ArcError) -> Self {
137        Self(Some(source))
138    }
139}