use agentkit_loop::{AgentEvent, LoopObserver};
pub struct BufferedReporter<T: LoopObserver> {
inner: T,
buffer: std::sync::Mutex<Vec<AgentEvent>>,
capacity: usize,
}
impl<T: LoopObserver> BufferedReporter<T> {
pub fn new(inner: T, capacity: usize) -> Self {
Self {
inner,
buffer: std::sync::Mutex::new(Vec::with_capacity(capacity)),
capacity,
}
}
pub fn flush(&self) {
let drained = std::mem::replace(
&mut *self.buffer.lock().unwrap_or_else(|e| e.into_inner()),
Vec::with_capacity(self.capacity),
);
for event in drained {
self.inner.handle_event(event);
}
}
pub fn pending(&self) -> usize {
self.buffer.lock().unwrap_or_else(|e| e.into_inner()).len()
}
pub fn inner(&self) -> &T {
&self.inner
}
}
impl<T: LoopObserver> LoopObserver for BufferedReporter<T> {
fn handle_event(&self, event: AgentEvent) {
let needs_flush = {
let mut buffer = self.buffer.lock().unwrap_or_else(|e| e.into_inner());
buffer.push(event);
self.capacity > 0 && buffer.len() >= self.capacity
};
if needs_flush {
self.flush();
}
}
}
impl<T: LoopObserver> Drop for BufferedReporter<T> {
fn drop(&mut self) {
self.flush();
}
}