use async_trait::async_trait;
use tokio::sync::RwLock;
use super::session::Session;
use crate::error::Result;
use crate::message::Message;
#[derive(Debug)]
pub struct InMemorySession {
id: String,
messages: RwLock<Vec<Message>>,
}
impl InMemorySession {
#[must_use]
pub fn new(id: impl Into<String>) -> Self {
Self {
id: id.into(),
messages: RwLock::new(Vec::new()),
}
}
#[must_use]
pub fn with_messages(id: impl Into<String>, messages: Vec<Message>) -> Self {
Self {
id: id.into(),
messages: RwLock::new(messages),
}
}
#[must_use]
pub fn with_capacity(id: impl Into<String>, capacity: usize) -> Self {
Self {
id: id.into(),
messages: RwLock::new(Vec::with_capacity(capacity)),
}
}
}
#[async_trait]
impl Session for InMemorySession {
fn id(&self) -> &str {
&self.id
}
async fn get_messages(&self, limit: Option<usize>) -> Result<Vec<Message>> {
let guard = self.messages.read().await;
match limit {
Some(n) if n < guard.len() => Ok(guard[guard.len() - n..].to_vec()),
_ => Ok(guard.clone()),
}
}
async fn add_messages(&self, messages: &[Message]) -> Result<()> {
if messages.is_empty() {
return Ok(());
}
self.messages.write().await.extend(messages.iter().cloned());
Ok(())
}
async fn pop_message(&self) -> Result<Option<Message>> {
Ok(self.messages.write().await.pop())
}
async fn clear(&self) -> Result<()> {
self.messages.write().await.clear();
Ok(())
}
async fn len(&self) -> Result<usize> {
Ok(self.messages.read().await.len())
}
}