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}