1use crate::behavior::{
4 Actions, Address, Become, Behavior, BirthMode, Delivery, Recipient, SendAlgebra, SendProduct,
5 User, UserEvent,
6};
7use crate::deadlined::{TimeEvent, TimeReached};
8use crate::supervising::{ChildEvent, ChildStopped};
9use crate::{Crash, Exit, Step};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub struct ObservePeer<A> {
13 pub peer: A,
14}
15
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct PeerStopped<A: Address> {
18 pub peer: A,
19 pub outcome: Result<Exit<A>, Crash>,
20}
21
22#[derive(Debug, Clone, PartialEq, Eq)]
23pub enum WatchEvent<E, A: Address> {
24 Inner(E),
25 PeerStopped(PeerStopped<A>),
26}
27
28pub trait PeerEvent<A: Address>: Sized {
29 fn peer_stopped(event: PeerStopped<A>) -> Option<Self>;
30}
31
32impl<E, A: Address> PeerEvent<A> for WatchEvent<E, A> {
33 fn peer_stopped(event: PeerStopped<A>) -> Option<Self> {
34 Some(Self::PeerStopped(event))
35 }
36}
37
38impl<E: UserEvent, A: Address> UserEvent for WatchEvent<E, A> {
39 type Addr = E::Addr;
40 type Message = E::Message;
41
42 fn user(from: Self::Addr, message: Self::Message) -> Self {
43 Self::Inner(E::user(from, message))
44 }
45
46 fn into_user(self) -> Result<User<Self::Addr, Self::Message>, Self> {
47 match self {
48 Self::Inner(event) => event.into_user().map_err(Self::Inner),
49 stopped @ Self::PeerStopped(_) => Err(stopped),
50 }
51 }
52}
53
54impl<E: TimeEvent, A: Address> TimeEvent for WatchEvent<E, A> {
55 fn time_reached(event: TimeReached) -> Option<Self> {
56 E::time_reached(event).map(Self::Inner)
57 }
58}
59
60impl<E: ChildEvent<A>, A: Address> ChildEvent<A> for WatchEvent<E, A> {
61 fn child_stopped(event: ChildStopped<A>) -> Option<Self> {
62 E::child_stopped(event).map(Self::Inner)
63 }
64}
65
66pub type LinkReaction<B> = fn(
67 &mut B,
68 <B as Behavior>::Addr,
69 &Result<Exit<<B as Behavior>::Addr>, Crash>,
70) -> Result<Become<<B as Behavior>::Addr>, <B as Behavior>::Error>;
71
72pub type WatchSends<B> = SendProduct<
73 <B as Behavior>::Sends,
74 Vec<Delivery<<B as Behavior>::Addr, ObservePeer<<B as Behavior>::Addr>>>,
75>;
76
77pub type WatchActions<B> =
78 Actions<<B as Behavior>::Addr, <B as Behavior>::Ph, WatchSends<B>, <B as Behavior>::Birth>;
79
80pub struct Watching<B: Behavior> {
81 inner: B,
82 peer: B::Addr,
83 on_stopped: LinkReaction<B>,
84}
85
86impl<B: Behavior> Watching<B> {
87 #[must_use]
88 pub fn new(inner: B, peer: B::Addr, on_stopped: LinkReaction<B>) -> Self {
89 Self {
90 inner,
91 peer,
92 on_stopped,
93 }
94 }
95
96 #[must_use]
97 pub fn inner(&self) -> &B {
98 &self.inner
99 }
100}
101
102impl<B, A, Ph, Sends, Br> Behavior for Watching<B>
103where
104 A: Address + Send,
105 Sends: SendAlgebra,
106 Br: BirthMode,
107 B: Behavior<
108 Addr = A,
109 Ph = Ph,
110 Sends = Sends,
111 Birth = Br,
112 Effect = Actions<A, Ph, Sends, Br>,
113 Done = Exit<A>,
114 > + Send,
115 B::Event: PeerEvent<B::Addr> + Send,
116 B::Msg: Send,
117{
118 type Addr = A;
119 type Msg = B::Msg;
120 type Event = WatchEvent<B::Event, B::Addr>;
121 type Sends = SendProduct<Sends, Vec<Delivery<A, ObservePeer<A>>>>;
122 type Ph = Ph;
123 type Error = B::Error;
124 type Birth = Br;
125 type Effect = Actions<A, Ph, Self::Sends, Br>;
126 type Done = Exit<A>;
127
128 async fn init(&mut self) -> Result<Self::Effect, B::Error> {
129 let actions = self.inner.init().await?;
130 Ok(Self::wrap(
131 actions,
132 vec![Delivery::new(
133 Recipient::service(),
134 ObservePeer { peer: self.peer },
135 )],
136 ))
137 }
138
139 async fn step(&mut self, event: Self::Event) -> Result<Self::Effect, B::Error> {
140 match event {
141 WatchEvent::PeerStopped(event) if event.peer == self.peer => {
142 let become_ = match (self.on_stopped)(&mut self.inner, event.peer, &event.outcome)?
143 {
144 Step::Continue => Step::Continue,
145 Step::Goto(never) => match never {},
146 Step::Stop(exit) => Step::Stop(exit),
147 };
148 Ok(Actions {
149 sends: Self::Sends::empty(),
150 creates: Vec::new(),
151 become_,
152 })
153 }
154 WatchEvent::PeerStopped(event) => match B::Event::peer_stopped(event) {
155 Some(inner) => self
156 .inner
157 .step(inner)
158 .await
159 .map(|actions| Self::wrap(actions, Vec::new())),
160 None => Ok(Actions::cont()),
161 },
162 WatchEvent::Inner(event) => self
163 .inner
164 .step(event)
165 .await
166 .map(|actions| Self::wrap(actions, Vec::new())),
167 }
168 }
169}
170
171impl<B: Behavior> Watching<B> {
172 fn wrap(
173 actions: Actions<B::Addr, B::Ph, B::Sends, B::Birth>,
174 own: Vec<Delivery<B::Addr, ObservePeer<B::Addr>>>,
175 ) -> WatchActions<B> {
176 Actions {
177 sends: SendProduct {
178 inner: actions.sends,
179 own,
180 },
181 creates: actions.creates,
182 become_: actions.become_,
183 }
184 }
185}
186
187pub fn stop_on_abnormal_death<B: Behavior>(
192 _behavior: &mut B,
193 peer: B::Addr,
194 outcome: &Result<Exit<B::Addr>, Crash>,
195) -> Result<Become<B::Addr>, B::Error> {
196 Ok(match outcome {
197 Ok(Exit::Normal | Exit::Collected) => Step::Continue,
198 _ => Step::Stop(Exit::LinkDied(peer)),
199 })
200}