Skip to main content

atomr_core/dispatch/
mailbox.rs

1//! Mailbox configuration.
2//!
3//! The mailbox holds queued messages for a single actor. Our implementation
4//! uses `tokio::mpsc::UnboundedReceiver` as the user queue and a separate
5//! unbounded queue for system messages; `ActorCell` polls with system priority.
6
7use std::time::Duration;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
10pub enum MailboxKind {
11    #[default]
12    Unbounded,
13    Bounded,
14    UnboundedDeque,
15    UnboundedPriority,
16    UnboundedStablePriority,
17    /// Control messages bypass user messages.
18    /// `UnboundedControlAwareMessageQueue`.
19    UnboundedControlAware,
20    /// Bounded variant with control-priority bypass.
21    BoundedControlAware,
22}
23
24/// What a bounded mailbox does when its capacity is reached.
25/// overflow policy.
26#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
27pub enum OverflowStrategy {
28    /// Drop the new (incoming) message and log it as a dead letter.
29    #[default]
30    DropNew,
31    /// Drop the oldest enqueued message and accept the new one.
32    DropHead,
33    /// Drop the most-recently-enqueued message and accept the new one.
34    DropTail,
35    /// Reject the push and signal failure to the sender.
36    Fail,
37}
38
39#[derive(Debug, Clone)]
40pub struct MailboxConfig {
41    pub kind: MailboxKind,
42    pub capacity: usize,
43    pub push_timeout: Duration,
44    /// Overflow policy used for bounded kinds. Ignored for unbounded.
45    pub overflow: OverflowStrategy,
46}
47
48impl Default for MailboxConfig {
49    fn default() -> Self {
50        Self {
51            kind: MailboxKind::Unbounded,
52            capacity: 1_000,
53            push_timeout: Duration::from_secs(10),
54            overflow: OverflowStrategy::DropNew,
55        }
56    }
57}
58
59/// Marker type exposed publicly — the concrete storage lives inside
60/// `ActorCell` (tokio mpsc channels and an auxiliary priority heap when needed).
61#[derive(Debug, Clone, Default)]
62pub struct Mailbox {
63    pub config: MailboxConfig,
64}
65
66impl Mailbox {
67    pub fn new(config: MailboxConfig) -> Self {
68        Self { config }
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[test]
77    fn default_mailbox_kind_unbounded() {
78        assert_eq!(Mailbox::default().config.kind, MailboxKind::Unbounded);
79    }
80
81    #[test]
82    fn default_overflow_drops_new() {
83        assert_eq!(MailboxConfig::default().overflow, OverflowStrategy::DropNew);
84    }
85
86    #[test]
87    fn config_for_each_kind_is_constructible() {
88        for k in [
89            MailboxKind::Unbounded,
90            MailboxKind::Bounded,
91            MailboxKind::UnboundedDeque,
92            MailboxKind::UnboundedPriority,
93            MailboxKind::UnboundedStablePriority,
94            MailboxKind::UnboundedControlAware,
95            MailboxKind::BoundedControlAware,
96        ] {
97            let c = MailboxConfig { kind: k, ..Default::default() };
98            assert_eq!(c.kind, k);
99        }
100    }
101}