1use std::collections::{BTreeMap, VecDeque};
3
4pub const EVENT_LIMIT: usize = 256;
5pub const EVENT_BYTES: usize = 900;
6const RETRY_MS: u64 = 100;
7#[derive(Clone, Debug, PartialEq, Eq)]
8pub struct EventPacket {
9 pub sequence: u64,
10 pub payload: Vec<u8>,
11}
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum Error {
14 Full,
15 Oversized,
16 SequenceExhausted,
17 OutsideWindow,
18}
19struct Pending {
20 packet: EventPacket,
21 last_sent: Option<u64>,
22}
23#[derive(Default)]
24pub struct EventSender {
25 next: u64,
26 pending: VecDeque<Pending>,
27}
28impl EventSender {
29 pub fn queue(&mut self, payload: &[u8]) -> Result<u64, Error> {
30 if payload.len() > EVENT_BYTES {
31 return Err(Error::Oversized);
32 }
33 if self.pending.len() >= EVENT_LIMIT {
34 return Err(Error::Full);
35 }
36 let sequence = self.next;
37 self.next = self.next.checked_add(1).ok_or(Error::SequenceExhausted)?;
38 self.pending.push_back(Pending {
39 packet: EventPacket {
40 sequence,
41 payload: payload.to_vec(),
42 },
43 last_sent: None,
44 });
45 Ok(sequence)
46 }
47 pub fn due(&mut self, now: u64, budget: usize) -> Vec<EventPacket> {
49 self.pending
50 .iter_mut()
51 .filter(|p| {
52 p.last_sent
53 .is_none_or(|last| now.saturating_sub(last) >= RETRY_MS)
54 })
55 .take(budget.min(EVENT_LIMIT))
56 .map(|p| {
57 p.last_sent = Some(now);
58 p.packet.clone()
59 })
60 .collect()
61 }
62 pub fn acknowledge(&mut self, sequence: u64) -> bool {
64 if let Some(index) = self
65 .pending
66 .iter()
67 .position(|p| p.packet.sequence == sequence)
68 {
69 self.pending.remove(index);
70 true
71 } else {
72 false
73 }
74 }
75 pub fn pending(&self) -> usize {
76 self.pending.len()
77 }
78}
79#[derive(Default)]
80pub struct EventReceiver {
81 next: u64,
82 buffered: BTreeMap<u64, Vec<u8>>,
83}
84impl EventReceiver {
85 pub fn receive(&mut self, packet: &EventPacket) -> Result<Vec<EventPacket>, Error> {
88 if packet.payload.len() > EVENT_BYTES {
89 return Err(Error::Oversized);
90 }
91 if packet.sequence < self.next {
92 return Ok(Vec::new());
93 }
94 if packet.sequence - self.next >= EVENT_LIMIT as u64 {
95 return Err(Error::OutsideWindow);
96 }
97 self.buffered
98 .entry(packet.sequence)
99 .or_insert_with(|| packet.payload.clone());
100 let mut delivered = Vec::new();
101 while let Some(payload) = self.buffered.remove(&self.next) {
102 let sequence = self.next;
103 self.next = self.next.checked_add(1).ok_or(Error::SequenceExhausted)?;
104 delivered.push(EventPacket { sequence, payload });
105 }
106 Ok(delivered)
107 }
108 pub fn next_sequence(&self) -> u64 {
109 self.next
110 }
111 pub fn contains_buffered(&self, sequence: u64) -> bool {
112 self.buffered.contains_key(&sequence)
113 }
114 pub fn buffered(&self) -> usize {
115 self.buffered.len()
116 }
117}
118#[cfg(test)]
119mod tests {
120 use super::*;
121 #[test]
122 fn lost_reordered_and_duplicate_events_deliver_once_in_order() {
123 let (mut sender, mut receiver) = (EventSender::default(), EventReceiver::default());
124 for i in 0..8 {
125 sender.queue(&[i]).unwrap();
126 }
127 let packets = sender.due(0, 8);
128 let mut delivered = Vec::new();
129 for i in [7, 2, 2, 5, 1, 4, 6, 3] {
130 delivered.extend(receiver.receive(&packets[i]).unwrap());
131 sender.acknowledge(i as u64);
132 }
133 assert!(delivered.is_empty());
134 assert_eq!(sender.pending(), 1);
135 assert!(sender.due(99, 8).is_empty());
136 let retry = sender.due(100, 8);
137 delivered.extend(receiver.receive(&retry[0]).unwrap());
138 sender.acknowledge(0);
139 assert_eq!(
140 delivered.iter().map(|p| p.payload[0]).collect::<Vec<_>>(),
141 (0..8).collect::<Vec<_>>()
142 );
143 assert!(receiver.receive(&retry[0]).unwrap().is_empty());
144 assert_eq!(sender.pending(), 0);
145 }
146 #[test]
147 fn flow_control_bounds_memory_and_rejects_future_ack() {
148 let mut sender = EventSender::default();
149 for _ in 0..EVENT_LIMIT {
150 sender.queue(&[1]).unwrap();
151 }
152 assert_eq!(sender.queue(&[]), Err(Error::Full));
153 assert!(!sender.acknowledge(9999));
154 assert_eq!(sender.due(0, 3).len(), 3);
155 let mut receiver = EventReceiver::default();
156 assert_eq!(
157 receiver.receive(&EventPacket {
158 sequence: 9999,
159 payload: vec![]
160 }),
161 Err(Error::OutsideWindow)
162 );
163 assert_eq!(receiver.buffered(), 0);
164 }
165}