Skip to main content

canlink_hal/queue/
policy.rs

1//! Queue overflow policy (FR-011)
2//!
3//! Defines strategies for handling queue overflow situations.
4
5use std::time::Duration;
6
7/// Queue overflow handling policy
8///
9/// Determines how the queue behaves when it reaches capacity.
10///
11/// # Default
12///
13/// The default policy is `DropOldest`, which is suitable for real-time
14/// monitoring scenarios where the latest data is most important.
15///
16/// # Example
17///
18/// ```rust
19/// use canlink_hal::queue::QueueOverflowPolicy;
20/// use std::time::Duration;
21///
22/// // Default policy
23/// let policy = QueueOverflowPolicy::default();
24/// assert!(matches!(policy, QueueOverflowPolicy::DropOldest));
25///
26/// // Block with timeout
27/// let policy = QueueOverflowPolicy::Block {
28///     timeout: Duration::from_millis(100),
29/// };
30/// ```
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
32pub enum QueueOverflowPolicy {
33    /// Drop the oldest message in the queue
34    ///
35    /// This is the default policy, suitable for real-time monitoring
36    /// where the latest data is most important.
37    #[default]
38    DropOldest,
39
40    /// Drop the newest message (the one being added)
41    ///
42    /// Suitable for data recording scenarios where preserving
43    /// complete history is important.
44    DropNewest,
45
46    /// Block until space is available or timeout expires
47    ///
48    /// Suitable for critical messages that should not be lost.
49    /// Returns `QueueError::QueueFull` if timeout expires.
50    Block {
51        /// Maximum time to wait for space
52        timeout: Duration,
53    },
54}
55
56impl QueueOverflowPolicy {
57    /// Create a new `DropOldest` policy
58    #[must_use]
59    pub fn drop_oldest() -> Self {
60        Self::DropOldest
61    }
62
63    /// Create a new `DropNewest` policy
64    #[must_use]
65    pub fn drop_newest() -> Self {
66        Self::DropNewest
67    }
68
69    /// Create a new Block policy with the given timeout
70    #[must_use]
71    pub fn block(timeout: Duration) -> Self {
72        Self::Block { timeout }
73    }
74
75    /// Check if this policy may block
76    #[must_use]
77    pub fn may_block(&self) -> bool {
78        matches!(self, Self::Block { .. })
79    }
80
81    /// Get the timeout if this is a Block policy
82    #[must_use]
83    pub fn timeout(&self) -> Option<Duration> {
84        match self {
85            Self::Block { timeout } => Some(*timeout),
86            _ => None,
87        }
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94
95    #[test]
96    fn test_default_policy() {
97        let policy = QueueOverflowPolicy::default();
98        assert!(matches!(policy, QueueOverflowPolicy::DropOldest));
99    }
100
101    #[test]
102    fn test_constructors() {
103        assert!(matches!(
104            QueueOverflowPolicy::drop_oldest(),
105            QueueOverflowPolicy::DropOldest
106        ));
107        assert!(matches!(
108            QueueOverflowPolicy::drop_newest(),
109            QueueOverflowPolicy::DropNewest
110        ));
111
112        let timeout = Duration::from_millis(100);
113        let policy = QueueOverflowPolicy::block(timeout);
114        assert!(matches!(policy, QueueOverflowPolicy::Block { .. }));
115        assert_eq!(policy.timeout(), Some(timeout));
116    }
117
118    #[test]
119    fn test_may_block() {
120        assert!(!QueueOverflowPolicy::DropOldest.may_block());
121        assert!(!QueueOverflowPolicy::DropNewest.may_block());
122        assert!(QueueOverflowPolicy::block(Duration::from_millis(100)).may_block());
123    }
124}