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)]
130pub struct ObservePeer<A> {
131 pub peer: A,
132}
133
134impl<A> From<A> for ObservePeer<A> {
135 fn from(peer: A) -> Self {
136 Self { peer }
137 }
138}
139
140impl<A> ObservePeer<A> {
141 #[must_use]
142 pub const fn new(peer: A) -> Self {
143 Self { peer }
144 }
145}
146
147#[derive(Debug, Clone, Copy, PartialEq, Eq)]
156pub struct UnwatchPeer<A> {
157 pub peer: A,
158}
159
160impl<A> UnwatchPeer<A> {
161 #[must_use]
162 pub const fn new(peer: A) -> Self {
163 Self { peer }
164 }
165}
166
167impl<A> From<A> for UnwatchPeer<A> {
168 fn from(peer: A) -> Self {
169 Self::new(peer)
170 }
171}
172
173#[derive(Debug, Clone, PartialEq, Eq)]
174pub struct PeerStopped<A: Address> {
175 pub peer: A,
176 pub outcome: Result<Exit<A>, Crash>,
177}
178
179impl<A: Address> PeerStopped<A> {
180 #[must_use]
181 pub fn new(peer: A, outcome: Result<Exit<A>, Crash>) -> Self {
182 Self { peer, outcome }
183 }
184}
185
186pub trait PeerEvent: UserEvent {
187 fn peer_stopped(event: PeerStopped<Self::Addr>) -> Option<Self>;
188}
189
190#[derive(Debug, Clone, PartialEq, Eq)]
191pub struct ChildStopped<A: Address> {
192 pub nonce: A::Nonce,
193 pub outcome: Result<Exit<A>, Crash>,
194 pub at: Instant,
195}
196
197impl<A: Address> ChildStopped<A> {
198 #[must_use]
199 pub fn new(nonce: A::Nonce, outcome: Result<Exit<A>, Crash>, at: Instant) -> Self {
200 Self { nonce, outcome, at }
201 }
202}
203
204#[derive(Debug, Clone, Copy, PartialEq, Eq)]
213pub struct ObserveChild<N> {
214 pub nonce: N,
215}
216
217impl<N> ObserveChild<N> {
218 #[must_use]
219 pub const fn new(nonce: N) -> Self {
220 Self { nonce }
221 }
222}
223
224#[derive(Debug, Clone, PartialEq, Eq)]
228pub struct ReportWorkerStopped<A: Address> {
229 pub worker: A::Nonce,
230 pub outcome: Result<Exit<A>, Crash>,
231 pub at: Instant,
232}
233
234impl<A: Address> ReportWorkerStopped<A> {
235 #[must_use]
236 pub fn new(worker: A::Nonce, outcome: Result<Exit<A>, Crash>, at: Instant) -> Self {
237 Self {
238 worker,
239 outcome,
240 at,
241 }
242 }
243}
244
245impl<A: Address> From<ChildStopped<A>> for ReportWorkerStopped<A> {
246 fn from(stopped: ChildStopped<A>) -> Self {
247 Self::new(stopped.nonce, stopped.outcome, stopped.at)
248 }
249}
250
251#[derive(Debug, Clone, PartialEq, Eq)]
253pub struct WorkerStopped<A: Address> {
254 pub proxy: A::Nonce,
255 pub worker: A::Nonce,
256 pub outcome: Result<Exit<A>, Crash>,
257 pub at: Instant,
258}
259
260impl<A: Address> WorkerStopped<A> {
261 #[must_use]
262 pub fn new(
263 proxy: A::Nonce,
264 worker: A::Nonce,
265 outcome: Result<Exit<A>, Crash>,
266 at: Instant,
267 ) -> Self {
268 Self {
269 proxy,
270 worker,
271 outcome,
272 at,
273 }
274 }
275}
276
277impl<A: Address> From<(A::Nonce, ReportWorkerStopped<A>)> for WorkerStopped<A> {
278 fn from((proxy, stopped): (A::Nonce, ReportWorkerStopped<A>)) -> Self {
279 Self::new(proxy, stopped.worker, stopped.outcome, stopped.at)
280 }
281}
282
283pub trait ChildEvent: UserEvent {
284 fn child_stopped(event: ChildStopped<Self::Addr>) -> Option<Self>;
285}
286
287pub trait WorkerEvent: UserEvent {
288 fn worker_stopped(event: WorkerStopped<Self::Addr>) -> Option<Self>;
289}
290
291#[derive(Debug, Clone, Copy, PartialEq, Eq)]
296pub enum CreationRejection {
297 NonceAlreadyBound,
300 InitializationFailed,
302 EnvironmentFailed,
304}
305
306#[derive(Debug, Clone, Copy, PartialEq, Eq)]
313pub struct CreationResolved<N> {
314 pub nonce: N,
315 pub kind: CreationKind<N>,
316 pub result: Result<(), CreationRejection>,
317}
318
319impl<N> CreationResolved<N> {
320 #[must_use]
321 pub const fn new(
322 nonce: N,
323 kind: CreationKind<N>,
324 result: Result<(), CreationRejection>,
325 ) -> Self {
326 Self {
327 nonce,
328 kind,
329 result,
330 }
331 }
332
333 #[must_use]
334 pub const fn installed(nonce: N, kind: CreationKind<N>) -> Self {
335 Self::new(nonce, kind, Ok(()))
336 }
337
338 #[must_use]
340 pub const fn birth(nonce: N) -> Self {
341 Self::installed(nonce, CreationKind::Birth)
342 }
343
344 #[must_use]
346 pub const fn replacement_incarnation(nonce: N, replaces: N) -> Self {
347 Self::installed(nonce, CreationKind::ReplacementIncarnation { replaces })
348 }
349
350 #[must_use]
351 pub const fn rejected(nonce: N, kind: CreationKind<N>, rejection: CreationRejection) -> Self {
352 Self::new(nonce, kind, Err(rejection))
353 }
354}
355
356#[derive(Debug, Clone, Copy, PartialEq, Eq)]
359pub struct ObserveCreation<N> {
360 pub nonce: N,
361}
362
363impl<N> ObserveCreation<N> {
364 #[must_use]
365 pub const fn new(nonce: N) -> Self {
366 Self { nonce }
367 }
368}
369
370pub trait CreationEvent: UserEvent {
371 fn creation_resolved(event: CreationResolved<<Self::Addr as Address>::Nonce>) -> Option<Self>;
372}
373
374#[derive(Debug, Clone, Copy, PartialEq, Eq)]
377pub struct ReportWorkerCreationResolved<N> {
378 pub worker: N,
379 pub kind: CreationKind<N>,
380 pub result: Result<(), CreationRejection>,
381}
382
383impl<N> ReportWorkerCreationResolved<N> {
384 #[must_use]
385 pub const fn new(
386 worker: N,
387 kind: CreationKind<N>,
388 result: Result<(), CreationRejection>,
389 ) -> Self {
390 Self {
391 worker,
392 kind,
393 result,
394 }
395 }
396}
397
398impl<N> From<CreationResolved<N>> for ReportWorkerCreationResolved<N> {
399 fn from(resolved: CreationResolved<N>) -> Self {
400 Self::new(resolved.nonce, resolved.kind, resolved.result)
401 }
402}
403
404#[derive(Debug, Clone, Copy, PartialEq, Eq)]
406pub struct WorkerCreationResolved<N> {
407 pub proxy: N,
408 pub worker: N,
409 pub kind: CreationKind<N>,
410 pub result: Result<(), CreationRejection>,
411}
412
413impl<N> WorkerCreationResolved<N> {
414 #[must_use]
415 pub const fn new(
416 proxy: N,
417 worker: N,
418 kind: CreationKind<N>,
419 result: Result<(), CreationRejection>,
420 ) -> Self {
421 Self {
422 proxy,
423 worker,
424 kind,
425 result,
426 }
427 }
428}
429
430impl<N> From<(N, ReportWorkerCreationResolved<N>)> for WorkerCreationResolved<N> {
431 fn from((proxy, resolved): (N, ReportWorkerCreationResolved<N>)) -> Self {
432 Self::new(proxy, resolved.worker, resolved.kind, resolved.result)
433 }
434}
435
436pub trait WorkerCreationEvent: UserEvent {
437 fn worker_creation_resolved(
438 event: WorkerCreationResolved<<Self::Addr as Address>::Nonce>,
439 ) -> Option<Self>;
440}
441
442#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
444pub struct ShutdownRequested;
445
446pub trait ShutdownEvent: UserEvent {
447 fn shutdown_requested(event: ShutdownRequested) -> Option<Self>;
448}
449
450#[cfg(test)]
451mod tests {
452 use super::*;
453 use crate::MailAddr;
454
455 #[test]
456 fn lifecycle_conversions_preserve_every_semantic_field() {
457 let at = Instant::now();
458 let child = ChildStopped::<MailAddr>::new(3, Err(Crash::Failed), at);
459 let report = ReportWorkerStopped::from(child);
460 let worker = WorkerStopped::from((7, report));
461 assert_eq!(worker.proxy, 7);
462 assert_eq!(worker.worker, 3);
463 assert_eq!(worker.outcome, Err(Crash::Failed));
464 assert_eq!(worker.at, at);
465
466 let creation = CreationResolved::<u64>::rejected(
467 4,
468 CreationKind::replacement_of(3),
469 CreationRejection::EnvironmentFailed,
470 );
471 let report = ReportWorkerCreationResolved::from(creation);
472 let worker = WorkerCreationResolved::from((7, report));
473 assert_eq!(worker.proxy, 7);
474 assert_eq!(worker.worker, 4);
475 assert_eq!(worker.kind, CreationKind::replacement_of(3));
476 assert_eq!(worker.result, Err(CreationRejection::EnvironmentFailed));
477 }
478
479 #[test]
480 fn timer_newtypes_and_requests_have_lossless_construction() {
481 let id = TimerId::from(2);
482 let generation = TimerGeneration::from(5);
483 assert_eq!(u64::from(id), 2);
484 assert_eq!(u64::from(generation), 5);
485 assert_eq!(
486 TimerElapsed::from((id, generation)),
487 TimerElapsed::new(id, generation)
488 );
489 }
490}