1use crate::behavior::{Actions, Address, Behavior, BirthMode, SendAlgebra, User, UserEvent};
9use crate::protocol::{
10 ChildEvent, ChildStopped, PeerEvent, PeerStopped, ShutdownEvent, ShutdownRequested, TimeEvent,
11 TimeReached, WorkerEvent, WorkerStopped,
12};
13use crate::{Exit, Step};
14
15#[derive(Debug, Clone, PartialEq, Eq)]
17pub enum ShutdownProtocol<E> {
18 Inner(E),
19 ShutdownRequested(ShutdownRequested),
20}
21
22impl<E> ShutdownEvent for ShutdownProtocol<E> {
23 fn shutdown_requested(event: ShutdownRequested) -> Option<Self> {
24 Some(Self::ShutdownRequested(event))
25 }
26}
27
28impl<E: UserEvent> UserEvent for ShutdownProtocol<E> {
29 type Addr = E::Addr;
30 type Message = E::Message;
31
32 fn user(from: Self::Addr, message: Self::Message) -> Self {
33 Self::Inner(E::user(from, message))
34 }
35
36 fn into_user(self) -> Result<User<Self::Addr, Self::Message>, Self> {
37 match self {
38 Self::Inner(event) => event.into_user().map_err(Self::Inner),
39 shutdown @ Self::ShutdownRequested(_) => Err(shutdown),
40 }
41 }
42}
43
44impl<E: TimeEvent> TimeEvent for ShutdownProtocol<E> {
45 fn time_reached(event: TimeReached) -> Option<Self> {
46 E::time_reached(event).map(Self::Inner)
47 }
48}
49
50impl<E: PeerEvent<A>, A: Address> PeerEvent<A> for ShutdownProtocol<E> {
51 fn peer_stopped(event: PeerStopped<A>) -> Option<Self> {
52 E::peer_stopped(event).map(Self::Inner)
53 }
54}
55
56impl<E: ChildEvent<A>, A: Address> ChildEvent<A> for ShutdownProtocol<E> {
57 fn child_stopped(event: ChildStopped<A>) -> Option<Self> {
58 E::child_stopped(event).map(Self::Inner)
59 }
60}
61
62impl<E: WorkerEvent<A>, A: Address> WorkerEvent<A> for ShutdownProtocol<E> {
63 fn worker_stopped(event: WorkerStopped<A>) -> Option<Self> {
64 E::worker_stopped(event).map(Self::Inner)
65 }
66}
67
68pub struct StopOnShutdown<B> {
70 inner: B,
71}
72
73impl<B> StopOnShutdown<B> {
74 #[must_use]
75 pub fn new(inner: B) -> Self {
76 Self { inner }
77 }
78
79 #[must_use]
80 pub fn inner(&self) -> &B {
81 &self.inner
82 }
83}
84
85pub type ShutdownReaction<B> = fn(
88 &mut B,
89 ShutdownRequested,
90) -> Result<
91 Actions<
92 <B as Behavior>::Addr,
93 <B as Behavior>::Ph,
94 <B as Behavior>::Sends,
95 <B as Behavior>::Birth,
96 >,
97 <B as Behavior>::Error,
98>;
99
100pub struct FinalizeOnShutdown<B: Behavior> {
102 inner: B,
103 finalize: ShutdownReaction<B>,
104}
105
106impl<B: Behavior> FinalizeOnShutdown<B> {
107 #[must_use]
108 pub fn new(inner: B, finalize: ShutdownReaction<B>) -> Self {
109 Self { inner, finalize }
110 }
111
112 #[must_use]
113 pub fn inner(&self) -> &B {
114 &self.inner
115 }
116}
117
118macro_rules! impl_shutdown_behavior {
119 ($wrapper:ident, $shutdown:expr) => {
120 impl<B, A, Ph, Sends, Br> Behavior for $wrapper<B>
121 where
122 A: Address + Send,
123 Sends: SendAlgebra,
124 Br: BirthMode,
125 B: Behavior<Addr = A, Ph = Ph, Sends = Sends, Birth = Br> + Send,
126 B::Event: Send,
127 B::Msg: Send,
128 {
129 type Addr = A;
130 type Msg = B::Msg;
131 type Event = ShutdownProtocol<B::Event>;
132 type Sends = Sends;
133 type Ph = Ph;
134 type Error = B::Error;
135 type Birth = Br;
136
137 async fn init(&mut self) -> Result<Actions<A, Ph, Sends, Br>, B::Error> {
138 self.inner.init().await
139 }
140
141 async fn step(
142 &mut self,
143 event: Self::Event,
144 ) -> Result<Actions<A, Ph, Sends, Br>, B::Error> {
145 match event {
146 ShutdownProtocol::Inner(event) => self.inner.step(event).await,
147 ShutdownProtocol::ShutdownRequested(request) => $shutdown(self, request),
148 }
149 }
150 }
151 };
152}
153
154impl_shutdown_behavior!(StopOnShutdown, |_this: &mut StopOnShutdown<B>, _request| {
155 Ok(Actions::stop(Exit::Normal))
156});
157
158impl_shutdown_behavior!(
159 FinalizeOnShutdown,
160 |this: &mut FinalizeOnShutdown<B>, request| {
161 let actions = (this.finalize)(&mut this.inner, request)?;
162 Ok(Actions {
163 sends: actions.sends,
164 creates: actions.creates,
165 become_: Step::Stop(Exit::Normal),
166 })
167 }
168);