1use std::collections::HashMap;
4use std::sync::Arc;
5use tokio::sync::RwLock;
6use async_trait::async_trait;
7use serde::{Serialize, Deserialize};
8use crate::{CacheResult, CacheError, CacheEntry, CacheStats, Cache};
9use chrono::Utc;
10
11pub struct MemoryCache {
13 entries: Arc<RwLock<HashMap<String, CacheEntry<Vec<u8>>>>>,
14 stats: Arc<RwLock<CacheStats>>,
15 max_entries: Option<usize>,
16}
17
18impl MemoryCache {
19 pub fn new(max_entries: Option<usize>) -> Self {
21 Self {
22 entries: Arc::new(RwLock::new(HashMap::new())),
23 stats: Arc::new(RwLock::new(CacheStats::default())),
24 max_entries,
25 }
26 }
27
28 async fn cleanup_expired(&self) {
30 let mut entries = self.entries.write().await;
31 let mut expired_count = 0;
32
33 entries.retain(|_, entry| {
34 if entry.is_expired() {
35 expired_count += 1;
36 return false;
37 }
38 true
39 });
40
41 if expired_count > 0 {
42 let mut stats = self.stats.write().await;
43 stats.expired_entries = 0; }
45 }
46
47 async fn evict_if_needed(&self) {
49 let Some(max_entries) = self.max_entries else {
50 return;
51 };
52
53 let mut entries = self.entries.write().await;
54 if entries.len() < max_entries {
55 return;
56 }
57
58 let Some(key_to_remove) = entries
62 .iter()
63 .min_by_key(|(_, entry)| entry.last_accessed.unwrap_or(entry.created_at))
64 .map(|(k, _)| k.clone())
65 else {
66 return;
67 };
68
69 entries.remove(&key_to_remove);
70 }
71}
72
73#[async_trait]
74impl Cache for MemoryCache {
75 async fn set<T>(&self, key: &str, value: &T, ttl_seconds: Option<u64>) -> CacheResult<()>
76 where
77 T: Serialize + Send + Sync,
78 {
79 self.cleanup_expired().await;
81
82 self.evict_if_needed().await;
84
85 let data = serde_json::to_vec(value)
87 .map_err(|e| CacheError::Serialization(e.to_string()))?;
88
89 let entry = CacheEntry::new(data, ttl_seconds);
91
92 {
94 let mut entries = self.entries.write().await;
95 entries.insert(key.to_string(), entry);
96 }
97
98 {
100 let mut stats = self.stats.write().await;
101 stats.record_set();
102 stats.total_entries = self.entries.read().await.len() as u64;
103 }
104
105 Ok(())
106 }
107
108 async fn get<T>(&self, key: &str) -> CacheResult<Option<T>>
109 where
110 T: for<'de> Deserialize<'de> + Send + Sync,
111 {
112 self.cleanup_expired().await;
114
115 let entry = {
116 let entries = self.entries.read().await;
117 entries.get(key).cloned()
118 };
119
120 let Some(mut cache_entry) = entry else {
121 {
123 let mut stats = self.stats.write().await;
124 stats.record_miss();
125 }
126 return Ok(None);
127 };
128
129 if cache_entry.is_expired() {
131 {
133 let mut entries = self.entries.write().await;
134 entries.remove(key);
135 }
136
137 {
139 let mut stats = self.stats.write().await;
140 stats.record_miss();
141 stats.total_entries = self.entries.read().await.len() as u64;
142 }
143
144 return Ok(None);
145 }
146
147 cache_entry.mark_accessed();
149
150 let value = serde_json::from_slice(&cache_entry.data)
152 .map_err(|e| CacheError::Deserialization(e.to_string()))?;
153
154 {
156 let mut entries = self.entries.write().await;
157 entries.insert(key.to_string(), cache_entry);
158 }
159
160 {
162 let mut stats = self.stats.write().await;
163 stats.record_hit();
164 }
165
166 Ok(Some(value))
167 }
168
169 async fn delete(&self, key: &str) -> CacheResult<bool> {
170 let removed = {
171 let mut entries = self.entries.write().await;
172 entries.remove(key).is_some()
173 };
174
175 if removed {
176 {
178 let mut stats = self.stats.write().await;
179 stats.record_delete();
180 stats.total_entries = self.entries.read().await.len() as u64;
181 }
182 }
183
184 Ok(removed)
185 }
186
187 async fn exists(&self, key: &str) -> CacheResult<bool> {
188 self.cleanup_expired().await;
189
190 let entries = self.entries.read().await;
191 Ok(entries.get(key).is_some_and(|entry| !entry.is_expired()))
192 }
193
194 async fn expire(&self, key: &str, ttl_seconds: u64) -> CacheResult<bool> {
195 let mut entries = self.entries.write().await;
196
197 let Some(entry) = entries.get_mut(key) else {
198 return Ok(false);
199 };
200
201 entry.expires_at = Some(Utc::now() + chrono::Duration::seconds(ttl_seconds as i64));
202 Ok(true)
203 }
204
205 async fn ttl(&self, key: &str) -> CacheResult<Option<u64>> {
206 self.cleanup_expired().await;
207
208 let entries = self.entries.read().await;
209 let Some(entry) = entries.get(key) else {
210 return Ok(None); };
212
213 let Some(expires_at) = entry.expires_at else {
214 return Ok(None); };
216
217 let ttl = (expires_at - Utc::now()).num_seconds();
218 if ttl > 0 {
219 return Ok(Some(ttl as u64));
220 }
221 Ok(Some(0)) }
223
224 async fn clear(&self) -> CacheResult<()> {
225 {
226 let mut entries = self.entries.write().await;
227 entries.clear();
228 }
229
230 {
231 let mut stats = self.stats.write().await;
232 *stats = CacheStats::default();
233 }
234
235 Ok(())
236 }
237
238 async fn stats(&self) -> CacheResult<CacheStats> {
239 self.cleanup_expired().await;
240
241 let stats = self.stats.read().await;
242 let entries_count = self.entries.read().await.len() as u64;
243
244 Ok(CacheStats {
245 total_entries: entries_count,
246 expired_entries: 0, memory_usage: None, hit_rate: stats.hit_rate,
249 hits: stats.hits,
250 misses: stats.misses,
251 sets: stats.sets,
252 deletes: stats.deletes,
253 })
254 }
255
256 async fn mget<T>(&self, keys: Vec<String>) -> CacheResult<Vec<(String, Option<T>)>>
257 where
258 T: for<'de> Deserialize<'de> + Send + Sync,
259 {
260 let mut results = Vec::with_capacity(keys.len());
261
262 for key in keys {
263 let value = self.get::<T>(&key).await?;
264 results.push((key, value));
265 }
266
267 Ok(results)
268 }
269
270 async fn mset<T>(&self, entries: Vec<(String, T, Option<u64>)>) -> CacheResult<()>
271 where
272 T: Serialize + Send + Sync,
273 {
274 for (key, value, ttl) in entries {
275 self.set(&key, &value, ttl).await?;
276 }
277
278 Ok(())
279 }
280
281 async fn mdelete(&self, keys: Vec<String>) -> CacheResult<u64> {
282 let mut deleted_count = 0;
283
284 for key in keys {
285 if self.delete(&key).await? {
286 deleted_count += 1;
287 }
288 }
289
290 Ok(deleted_count)
291 }
292}