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