use std::collections::HashMap;
use std::time::{Duration, Instant};
use async_trait::async_trait;
use synaptic_core::{ChatResponse, SynapticError};
use tokio::sync::RwLock;
use crate::LlmCache;
struct CacheEntry {
response: ChatResponse,
created_at: Instant,
}
pub struct InMemoryCache {
store: RwLock<HashMap<String, CacheEntry>>,
ttl: Option<Duration>,
}
impl InMemoryCache {
pub fn new() -> Self {
Self {
store: RwLock::new(HashMap::new()),
ttl: None,
}
}
pub fn with_ttl(duration: Duration) -> Self {
Self {
store: RwLock::new(HashMap::new()),
ttl: Some(duration),
}
}
}
impl Default for InMemoryCache {
fn default() -> Self {
Self::new()
}
}
#[async_trait]
impl LlmCache for InMemoryCache {
async fn get(&self, key: &str) -> Result<Option<ChatResponse>, SynapticError> {
let store = self.store.read().await;
match store.get(key) {
Some(entry) => {
if let Some(ttl) = self.ttl {
if entry.created_at.elapsed() > ttl {
return Ok(None);
}
}
Ok(Some(entry.response.clone()))
}
None => Ok(None),
}
}
async fn put(&self, key: &str, response: &ChatResponse) -> Result<(), SynapticError> {
let mut store = self.store.write().await;
store.insert(
key.to_string(),
CacheEntry {
response: response.clone(),
created_at: Instant::now(),
},
);
Ok(())
}
async fn clear(&self) -> Result<(), SynapticError> {
let mut store = self.store.write().await;
store.clear();
Ok(())
}
}