Get cached result if available
(&self, key: &QueryCacheKey)
| 222 | |
| 223 | /// Get cached result if available |
| 224 | pub fn get(&self, key: &QueryCacheKey) -> Option<CacheHit> { |
| 225 | { |
| 226 | let mut stats = self.stats.write().unwrap(); |
| 227 | stats.total_requests += 1; |
| 228 | } |
| 229 | |
| 230 | // Try L1 first |
| 231 | { |
| 232 | let mut l1_cache = self.l1_cache.write().unwrap(); |
| 233 | if let Some(entry) = l1_cache.get_mut(key) { |
| 234 | if entry.is_valid() { |
| 235 | entry.metadata.update_access(); |
| 236 | self.l1_lru.write().unwrap().access(key); |
| 237 | |
| 238 | let mut stats = self.stats.write().unwrap(); |
| 239 | stats.l1_hits += 1; |
| 240 | stats.time_savings_ms += entry.execution_time.as_millis() as u64; |
| 241 | |
| 242 | return Some(CacheHit { |
| 243 | key: key.clone(), |
| 244 | hit_level: CacheLevel::L1, |
| 245 | access_time: Instant::now(), |
| 246 | saved_execution_time: entry.execution_time, |
| 247 | }); |
| 248 | } else { |
| 249 | // Remove expired entry |
| 250 | l1_cache.remove(key); |
| 251 | } |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | // Try L2 |
| 256 | { |
| 257 | let should_promote; |
| 258 | let _execution_time; |
| 259 | let cache_hit; |
| 260 | |
| 261 | { |
| 262 | let mut l2_cache = self.l2_cache.write().unwrap(); |
| 263 | if let Some(entry) = l2_cache.get_mut(key) { |
| 264 | if entry.is_valid() { |
| 265 | entry.metadata.update_access(); |
| 266 | self.l2_lru.write().unwrap().access(key); |
| 267 | |
| 268 | // Check if we should promote to L1 |
| 269 | should_promote = entry.metadata.access_count >= 3; |
| 270 | _execution_time = entry.execution_time; |
| 271 | |
| 272 | cache_hit = Some(CacheHit { |
| 273 | key: key.clone(), |
| 274 | hit_level: CacheLevel::L2, |
| 275 | access_time: Instant::now(), |
| 276 | saved_execution_time: entry.execution_time, |
| 277 | }); |
| 278 | |
| 279 | let mut stats = self.stats.write().unwrap(); |
| 280 | stats.l2_hits += 1; |
| 281 | stats.time_savings_ms += entry.execution_time.as_millis() as u64; |