use std::collections::VecDeque;
use crate::types::{ConversationId, MemoryTier};
pub enum BufferedWrite {
SaveMessage {
conversation_id: ConversationId,
role: String,
content: String,
tier: MemoryTier,
},
UpsertPersonaFact {
category: String,
content: String,
confidence: f64,
source_conversation_id: Option<i64>,
supersedes_id: Option<i64>,
},
StoreEmbedding {
collection: String,
point_id: String,
vector: Vec<f32>,
payload: serde_json::Value,
},
}
pub struct WriteBuffer {
pending: VecDeque<BufferedWrite>,
capacity: usize,
}
impl WriteBuffer {
#[must_use]
pub fn new(capacity: usize) -> Self {
Self {
pending: VecDeque::with_capacity(capacity),
capacity,
}
}
pub fn push(&mut self, write: BufferedWrite) -> bool {
self.pending.push_back(write);
self.pending.len() >= self.capacity
}
pub fn drain(&mut self) -> Vec<BufferedWrite> {
self.pending.drain(..).collect()
}
#[must_use]
pub fn len(&self) -> usize {
self.pending.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.pending.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::types::{ConversationId, MemoryTier};
fn make_save_message() -> BufferedWrite {
BufferedWrite::SaveMessage {
conversation_id: ConversationId(1),
role: "user".into(),
content: "hello".into(),
tier: MemoryTier::Episodic,
}
}
#[test]
fn push_increases_len() {
let mut buf = WriteBuffer::new(5);
assert!(buf.is_empty());
buf.push(make_save_message());
assert_eq!(buf.len(), 1);
}
#[test]
fn push_returns_false_below_capacity() {
let mut buf = WriteBuffer::new(3);
let at_capacity = buf.push(make_save_message());
assert!(!at_capacity);
let at_capacity = buf.push(make_save_message());
assert!(!at_capacity);
}
#[test]
fn push_returns_true_at_capacity() {
let mut buf = WriteBuffer::new(2);
buf.push(make_save_message());
let at_capacity = buf.push(make_save_message());
assert!(at_capacity);
}
#[test]
fn drain_returns_all_items_and_clears_buffer() {
let mut buf = WriteBuffer::new(10);
buf.push(make_save_message());
buf.push(make_save_message());
buf.push(make_save_message());
let drained = buf.drain();
assert_eq!(drained.len(), 3);
assert!(buf.is_empty());
assert_eq!(buf.len(), 0);
}
#[test]
fn drain_on_empty_buffer_returns_empty_vec() {
let mut buf = WriteBuffer::new(5);
let drained = buf.drain();
assert!(drained.is_empty());
}
#[test]
fn capacity_one_signals_on_first_push() {
let mut buf = WriteBuffer::new(1);
let at_capacity = buf.push(make_save_message());
assert!(at_capacity);
}
}