use std::time::{Duration, Instant};
use parking_lot::Mutex;
#[derive(Debug)]
pub struct Batch<T> {
inner: Mutex<BatchInner<T>>,
max_records: usize,
max_age: Duration,
}
#[derive(Debug)]
struct BatchInner<T> {
items: Vec<T>,
opened_at: Instant,
}
impl<T> Batch<T> {
#[must_use]
pub fn new(max_records: usize, max_age: Duration) -> Self {
Self {
inner: Mutex::new(BatchInner {
items: Vec::with_capacity(max_records),
opened_at: Instant::now(),
}),
max_records,
max_age,
}
}
pub fn push(&self, item: T) -> Option<Vec<T>> {
let mut inner = self.inner.lock();
inner.items.push(item);
if inner.items.len() >= self.max_records || inner.opened_at.elapsed() >= self.max_age {
let drained = std::mem::replace(&mut inner.items, Vec::with_capacity(self.max_records));
inner.opened_at = Instant::now();
return Some(drained);
}
None
}
pub fn drain(&self) -> Vec<T> {
let mut inner = self.inner.lock();
let drained = std::mem::replace(&mut inner.items, Vec::with_capacity(self.max_records));
inner.opened_at = Instant::now();
drained
}
}