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