synaptic_cache/
in_memory.rs1use std::collections::HashMap;
2use std::time::{Duration, Instant};
3
4use async_trait::async_trait;
5use synaptic_core::{ChatResponse, SynapticError};
6use tokio::sync::RwLock;
7
8use crate::LlmCache;
9
10struct CacheEntry {
11 response: ChatResponse,
12 created_at: Instant,
13}
14
15pub struct InMemoryCache {
17 store: RwLock<HashMap<String, CacheEntry>>,
18 ttl: Option<Duration>,
19}
20
21impl InMemoryCache {
22 pub fn new() -> Self {
24 Self {
25 store: RwLock::new(HashMap::new()),
26 ttl: None,
27 }
28 }
29
30 pub fn with_ttl(duration: Duration) -> Self {
32 Self {
33 store: RwLock::new(HashMap::new()),
34 ttl: Some(duration),
35 }
36 }
37}
38
39impl Default for InMemoryCache {
40 fn default() -> Self {
41 Self::new()
42 }
43}
44
45#[async_trait]
46impl LlmCache for InMemoryCache {
47 async fn get(&self, key: &str) -> Result<Option<ChatResponse>, SynapticError> {
48 let store = self.store.read().await;
49 match store.get(key) {
50 Some(entry) => {
51 if let Some(ttl) = self.ttl {
52 if entry.created_at.elapsed() > ttl {
53 return Ok(None);
54 }
55 }
56 Ok(Some(entry.response.clone()))
57 }
58 None => Ok(None),
59 }
60 }
61
62 async fn put(&self, key: &str, response: &ChatResponse) -> Result<(), SynapticError> {
63 let mut store = self.store.write().await;
64 store.insert(
65 key.to_string(),
66 CacheEntry {
67 response: response.clone(),
68 created_at: Instant::now(),
69 },
70 );
71 Ok(())
72 }
73
74 async fn clear(&self) -> Result<(), SynapticError> {
75 let mut store = self.store.write().await;
76 store.clear();
77 Ok(())
78 }
79}