Skip to main content

atomr_core/event/
dead_letters.rs

1//! Dead-letter sink. akka.net: `Actor/DeadLetterMailbox.cs`, `Event/*DeadLetter.cs`.
2
3use std::any::Any;
4use std::sync::Arc;
5
6use parking_lot::Mutex;
7
8use crate::actor::ActorPath;
9
10#[derive(Debug)]
11pub struct DeadLetter {
12    pub recipient: ActorPath,
13    pub sender: Option<ActorPath>,
14    pub message: Box<dyn Any + Send>,
15}
16
17#[derive(Default, Clone)]
18pub struct DeadLettersSink {
19    buf: Arc<Mutex<Vec<DeadLetter>>>,
20}
21
22impl DeadLettersSink {
23    pub fn new() -> Self {
24        Self::default()
25    }
26
27    pub fn push(&self, dl: DeadLetter) {
28        tracing::warn!(recipient = %dl.recipient, "dead letter");
29        self.buf.lock().push(dl);
30    }
31
32    pub fn drain(&self) -> Vec<DeadLetter> {
33        std::mem::take(&mut *self.buf.lock())
34    }
35
36    pub fn len(&self) -> usize {
37        self.buf.lock().len()
38    }
39
40    pub fn is_empty(&self) -> bool {
41        self.buf.lock().is_empty()
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48    use crate::actor::Address;
49
50    #[test]
51    fn stores_dead_letters() {
52        let s = DeadLettersSink::new();
53        s.push(DeadLetter {
54            recipient: ActorPath::root(Address::local("S")).child("x"),
55            sender: None,
56            message: Box::new(1u32),
57        });
58        assert_eq!(s.len(), 1);
59        let d = s.drain();
60        assert_eq!(d.len(), 1);
61    }
62}