common_batcher/
pending_batch.rs1use tokio::time::Instant;
16
17#[derive(Debug)]
19pub struct PendingBatch<T> {
20 items: Vec<T>,
21 total_rows: usize,
22 first_submitted_at: Option<Instant>,
23}
24
25impl<T> Default for PendingBatch<T> {
26 fn default() -> Self {
27 Self {
28 items: Vec::new(),
29 total_rows: 0,
30 first_submitted_at: None,
31 }
32 }
33}
34
35impl<T> PendingBatch<T> {
36 pub fn new() -> Self {
38 Self::default()
39 }
40
41 pub fn push(&mut self, item: T, total_rows: usize, now: Instant) {
43 self.first_submitted_at.get_or_insert(now);
44 self.items.push(item);
45 self.total_rows = self.total_rows.saturating_add(total_rows);
47 }
48
49 pub fn total_rows(&self) -> usize {
51 self.total_rows
52 }
53
54 pub fn len(&self) -> usize {
56 self.items.len()
57 }
58
59 pub fn is_empty(&self) -> bool {
61 self.items.is_empty()
62 }
63
64 pub fn first_submitted_at(&self) -> Option<Instant> {
66 self.first_submitted_at
67 }
68
69 pub fn take(&mut self) -> Vec<T> {
71 self.total_rows = 0;
72 self.first_submitted_at = None;
73 std::mem::take(&mut self.items)
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use std::time::Duration;
80
81 use super::*;
82
83 #[test]
84 fn test_complete_submissions_and_reset() {
85 let mut batch = PendingBatch::new();
86 let first = Instant::now();
87 assert!(batch.is_empty());
88 assert_eq!(batch.first_submitted_at(), None);
89 batch.push(vec![1, 2], 2, first);
90 batch.push(vec![3, 4, 5], 3, first + Duration::from_secs(1));
91 assert_eq!(batch.len(), 2);
92 assert_eq!(batch.total_rows(), 5);
93 assert_eq!(batch.first_submitted_at(), Some(first));
94 assert_eq!(batch.take(), vec![vec![1, 2], vec![3, 4, 5]]);
95 assert!(batch.is_empty());
96 assert_eq!(batch.total_rows(), 0);
97 assert_eq!(batch.first_submitted_at(), None);
98 let next = first + Duration::from_secs(2);
99 batch.push(vec![6], 1, next);
100 assert_eq!(batch.first_submitted_at(), Some(next));
101 }
102
103 #[test]
104 fn test_zero_rows_and_saturating_count() {
105 let mut batch = PendingBatch::new();
106 let now = Instant::now();
107 batch.push(1, 0, now);
108 assert!(!batch.is_empty());
109 assert_eq!(batch.total_rows(), 0);
110 batch.push(2, usize::MAX, now);
111 batch.push(3, 1, now);
112 assert_eq!(batch.total_rows(), usize::MAX);
113 assert_eq!(batch.take(), vec![1, 2, 3]);
114 }
115}