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