use std::collections::{HashMap, VecDeque};
use tokio::sync::Mutex;
use waproto::whatsapp::Message;
pub(crate) const DEFAULT_CAPACITY: usize = 200;
#[derive(Default)]
struct Inner {
order: VecDeque<String>,
by_id: HashMap<String, Message>,
}
pub(crate) struct RecentMessages {
inner: Mutex<Inner>,
capacity: usize,
}
impl Default for RecentMessages {
fn default() -> Self {
Self::with_capacity(DEFAULT_CAPACITY)
}
}
impl RecentMessages {
pub fn with_capacity(capacity: usize) -> Self {
Self {
inner: Mutex::new(Inner::default()),
capacity: capacity.max(1),
}
}
pub async fn remember(&self, id: impl Into<String>, message: Message) {
let id = id.into();
if id.is_empty() {
return;
}
let mut inner = self.inner.lock().await;
if inner.by_id.insert(id.clone(), message).is_some() {
inner.order.retain(|existing| existing != &id);
}
inner.order.push_back(id);
while inner.order.len() > self.capacity {
if let Some(evicted) = inner.order.pop_front() {
inner.by_id.remove(&evicted);
}
}
}
pub async fn get(&self, id: &str) -> Option<Message> {
self.inner.lock().await.by_id.get(id).cloned()
}
#[cfg(test)]
pub async fn len(&self) -> usize {
self.inner.lock().await.by_id.len()
}
}