1pub(crate) mod forward;
8
9use std::time::Duration;
10
11use tokio::time::Instant;
12
13use crate::behavior::Address;
14use crate::calculus::UserEvent;
15use crate::{Crash, CreationKind, Exit};
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
18pub struct TimerId(pub u64);
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
21pub struct TimerGeneration(pub u64);
22
23impl From<u64> for TimerId {
24 fn from(value: u64) -> Self {
25 Self(value)
26 }
27}
28
29impl From<TimerId> for u64 {
30 fn from(value: TimerId) -> Self {
31 value.0
32 }
33}
34
35impl From<u64> for TimerGeneration {
36 fn from(value: u64) -> Self {
37 Self(value)
38 }
39}
40
41impl From<TimerGeneration> for u64 {
42 fn from(value: TimerGeneration) -> Self {
43 value.0
44 }
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq)]
48pub struct ScheduleAt {
49 pub id: TimerId,
50 pub generation: TimerGeneration,
51 pub at: Instant,
52}
53
54impl ScheduleAt {
55 #[must_use]
56 pub const fn new(id: TimerId, generation: TimerGeneration, at: Instant) -> Self {
57 Self { id, generation, at }
58 }
59}
60
61impl From<(TimerId, TimerGeneration, Instant)> for ScheduleAt {
62 fn from((id, generation, at): (TimerId, TimerGeneration, Instant)) -> Self {
63 Self::new(id, generation, at)
64 }
65}
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
73pub struct ScheduleAfter {
74 pub id: TimerId,
75 pub generation: TimerGeneration,
76 pub after: Duration,
77}
78
79impl ScheduleAfter {
80 #[must_use]
81 pub const fn new(id: TimerId, generation: TimerGeneration, after: Duration) -> Self {
82 Self {
83 id,
84 generation,
85 after,
86 }
87 }
88}
89
90impl From<(TimerId, TimerGeneration, Duration)> for ScheduleAfter {
91 fn from((id, generation, after): (TimerId, TimerGeneration, Duration)) -> Self {
92 Self::new(id, generation, after)
93 }
94}
95
96#[derive(Debug, Clone, Copy, PartialEq, Eq)]
97pub struct TimerElapsed {
98 pub id: TimerId,
99 pub generation: TimerGeneration,
100}
101
102impl TimerElapsed {
103 #[must_use]
104 pub const fn new(id: TimerId, generation: TimerGeneration) -> Self {
105 Self { id, generation }
106 }
107}
108
109impl From<(TimerId, TimerGeneration)> for TimerElapsed {
110 fn from((id, generation): (TimerId, TimerGeneration)) -> Self {
111 Self::new(id, generation)
112 }
113}
114
115pub trait TimeEvent: UserEvent {
116 fn time_reached(event: TimerElapsed) -> Option<Self>;
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq)]
120pub struct ObservePeer<A> {
121 pub peer: A,
122}
123
124impl<A> From<A> for ObservePeer<A> {
125 fn from(peer: A) -> Self {
126 Self { peer }
127 }
128}
129
130impl<A> ObservePeer<A> {
131 #[must_use]
132 pub const fn new(peer: A) -> Self {
133 Self { peer }
134 }
135}
136
137#[derive(Debug, Clone, PartialEq, Eq)]
138pub struct PeerStopped<A: Address> {
139 pub peer: A,
140 pub outcome: Result<Exit<A>, Crash>,
141}
142
143impl<A: Address> PeerStopped<A> {
144 #[must_use]
145 pub fn new(peer: A, outcome: Result<Exit<A>, Crash>) -> Self {
146 Self { peer, outcome }
147 }
148}
149
150pub trait PeerEvent: UserEvent {
151 fn peer_stopped(event: PeerStopped<Self::Addr>) -> Option<Self>;
152}
153
154#[derive(Debug, Clone, PartialEq, Eq)]
155pub struct ChildStopped<A: Address> {
156 pub nonce: A::Nonce,
157 pub outcome: Result<Exit<A>, Crash>,
158 pub at: Instant,
159}
160
161impl<A: Address> ChildStopped<A> {
162 #[must_use]
163 pub fn new(nonce: A::Nonce, outcome: Result<Exit<A>, Crash>, at: Instant) -> Self {
164 Self { nonce, outcome, at }
165 }
166}
167
168#[derive(Debug, Clone, Copy, PartialEq, Eq)]
169pub struct ObserveChild<N> {
170 pub nonce: N,
171}
172
173impl<N> ObserveChild<N> {
174 #[must_use]
175 pub const fn new(nonce: N) -> Self {
176 Self { nonce }
177 }
178}
179
180#[derive(Debug, Clone, PartialEq, Eq)]
184pub struct ReportWorkerStopped<A: Address> {
185 pub worker: A::Nonce,
186 pub outcome: Result<Exit<A>, Crash>,
187 pub at: Instant,
188}
189
190impl<A: Address> ReportWorkerStopped<A> {
191 #[must_use]
192 pub fn new(worker: A::Nonce, outcome: Result<Exit<A>, Crash>, at: Instant) -> Self {
193 Self {
194 worker,
195 outcome,
196 at,
197 }
198 }
199}
200
201impl<A: Address> From<ChildStopped<A>> for ReportWorkerStopped<A> {
202 fn from(stopped: ChildStopped<A>) -> Self {
203 Self::new(stopped.nonce, stopped.outcome, stopped.at)
204 }
205}
206
207#[derive(Debug, Clone, PartialEq, Eq)]
209pub struct WorkerStopped<A: Address> {
210 pub proxy: A::Nonce,
211 pub worker: A::Nonce,
212 pub outcome: Result<Exit<A>, Crash>,
213 pub at: Instant,
214}
215
216impl<A: Address> WorkerStopped<A> {
217 #[must_use]
218 pub fn new(
219 proxy: A::Nonce,
220 worker: A::Nonce,
221 outcome: Result<Exit<A>, Crash>,
222 at: Instant,
223 ) -> Self {
224 Self {
225 proxy,
226 worker,
227 outcome,
228 at,
229 }
230 }
231}
232
233impl<A: Address> From<(A::Nonce, ReportWorkerStopped<A>)> for WorkerStopped<A> {
234 fn from((proxy, stopped): (A::Nonce, ReportWorkerStopped<A>)) -> Self {
235 Self::new(proxy, stopped.worker, stopped.outcome, stopped.at)
236 }
237}
238
239pub trait ChildEvent: UserEvent {
240 fn child_stopped(event: ChildStopped<Self::Addr>) -> Option<Self>;
241}
242
243pub trait WorkerEvent: UserEvent {
244 fn worker_stopped(event: WorkerStopped<Self::Addr>) -> Option<Self>;
245}
246
247#[derive(Debug, Clone, Copy, PartialEq, Eq)]
252pub enum CreationRejection {
253 NonceAlreadyBound,
256 InitializationFailed,
258 EnvironmentFailed,
260}
261
262#[derive(Debug, Clone, Copy, PartialEq, Eq)]
269pub struct CreationResolved<N> {
270 pub nonce: N,
271 pub kind: CreationKind<N>,
272 pub result: Result<(), CreationRejection>,
273}
274
275impl<N> CreationResolved<N> {
276 #[must_use]
277 pub const fn new(
278 nonce: N,
279 kind: CreationKind<N>,
280 result: Result<(), CreationRejection>,
281 ) -> Self {
282 Self {
283 nonce,
284 kind,
285 result,
286 }
287 }
288
289 #[must_use]
290 pub const fn installed(nonce: N, kind: CreationKind<N>) -> Self {
291 Self::new(nonce, kind, Ok(()))
292 }
293
294 #[must_use]
296 pub const fn birth(nonce: N) -> Self {
297 Self::installed(nonce, CreationKind::Birth)
298 }
299
300 #[must_use]
302 pub const fn replacement_incarnation(nonce: N, replaces: N) -> Self {
303 Self::installed(nonce, CreationKind::ReplacementIncarnation { replaces })
304 }
305
306 #[must_use]
307 pub const fn rejected(nonce: N, kind: CreationKind<N>, rejection: CreationRejection) -> Self {
308 Self::new(nonce, kind, Err(rejection))
309 }
310}
311
312#[derive(Debug, Clone, Copy, PartialEq, Eq)]
315pub struct ObserveCreation<N> {
316 pub nonce: N,
317}
318
319impl<N> ObserveCreation<N> {
320 #[must_use]
321 pub const fn new(nonce: N) -> Self {
322 Self { nonce }
323 }
324}
325
326pub trait CreationEvent: UserEvent {
327 fn creation_resolved(event: CreationResolved<<Self::Addr as Address>::Nonce>) -> Option<Self>;
328}
329
330#[derive(Debug, Clone, Copy, PartialEq, Eq)]
333pub struct ReportWorkerCreationResolved<N> {
334 pub worker: N,
335 pub kind: CreationKind<N>,
336 pub result: Result<(), CreationRejection>,
337}
338
339impl<N> ReportWorkerCreationResolved<N> {
340 #[must_use]
341 pub const fn new(
342 worker: N,
343 kind: CreationKind<N>,
344 result: Result<(), CreationRejection>,
345 ) -> Self {
346 Self {
347 worker,
348 kind,
349 result,
350 }
351 }
352}
353
354impl<N> From<CreationResolved<N>> for ReportWorkerCreationResolved<N> {
355 fn from(resolved: CreationResolved<N>) -> Self {
356 Self::new(resolved.nonce, resolved.kind, resolved.result)
357 }
358}
359
360#[derive(Debug, Clone, Copy, PartialEq, Eq)]
362pub struct WorkerCreationResolved<N> {
363 pub proxy: N,
364 pub worker: N,
365 pub kind: CreationKind<N>,
366 pub result: Result<(), CreationRejection>,
367}
368
369impl<N> WorkerCreationResolved<N> {
370 #[must_use]
371 pub const fn new(
372 proxy: N,
373 worker: N,
374 kind: CreationKind<N>,
375 result: Result<(), CreationRejection>,
376 ) -> Self {
377 Self {
378 proxy,
379 worker,
380 kind,
381 result,
382 }
383 }
384}
385
386impl<N> From<(N, ReportWorkerCreationResolved<N>)> for WorkerCreationResolved<N> {
387 fn from((proxy, resolved): (N, ReportWorkerCreationResolved<N>)) -> Self {
388 Self::new(proxy, resolved.worker, resolved.kind, resolved.result)
389 }
390}
391
392pub trait WorkerCreationEvent: UserEvent {
393 fn worker_creation_resolved(
394 event: WorkerCreationResolved<<Self::Addr as Address>::Nonce>,
395 ) -> Option<Self>;
396}
397
398#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
400pub struct ShutdownRequested;
401
402pub trait ShutdownEvent: UserEvent {
403 fn shutdown_requested(event: ShutdownRequested) -> Option<Self>;
404}
405
406#[cfg(test)]
407mod tests {
408 use super::*;
409 use crate::MailAddr;
410
411 #[test]
412 fn lifecycle_conversions_preserve_every_semantic_field() {
413 let at = Instant::now();
414 let child = ChildStopped::<MailAddr>::new(3, Err(Crash::Failed), at);
415 let report = ReportWorkerStopped::from(child);
416 let worker = WorkerStopped::from((7, report));
417 assert_eq!(worker.proxy, 7);
418 assert_eq!(worker.worker, 3);
419 assert_eq!(worker.outcome, Err(Crash::Failed));
420 assert_eq!(worker.at, at);
421
422 let creation = CreationResolved::<u64>::rejected(
423 4,
424 CreationKind::replacement_of(3),
425 CreationRejection::EnvironmentFailed,
426 );
427 let report = ReportWorkerCreationResolved::from(creation);
428 let worker = WorkerCreationResolved::from((7, report));
429 assert_eq!(worker.proxy, 7);
430 assert_eq!(worker.worker, 4);
431 assert_eq!(worker.kind, CreationKind::replacement_of(3));
432 assert_eq!(worker.result, Err(CreationRejection::EnvironmentFailed));
433 }
434
435 #[test]
436 fn timer_newtypes_and_requests_have_lossless_construction() {
437 let id = TimerId::from(2);
438 let generation = TimerGeneration::from(5);
439 assert_eq!(u64::from(id), 2);
440 assert_eq!(u64::from(generation), 5);
441 assert_eq!(
442 TimerElapsed::from((id, generation)),
443 TimerElapsed::new(id, generation)
444 );
445 }
446}