use super::types::{EnhancedCacheEntry, EnhancedCacheStats};
use once_cell::sync::Lazy;
use quick_cache::sync::Cache;
use serde_json::Value;
use std::sync::Arc;
use std::time::Duration;
pub static FILE_CACHE: Lazy<FileCache> = Lazy::new(|| FileCache::new(1000));
pub struct FileCache {
file_cache: Arc<Cache<String, EnhancedCacheEntry<Value>>>,
directory_cache: Arc<Cache<String, EnhancedCacheEntry<Value>>>,
stats: Arc<std::sync::Mutex<EnhancedCacheStats>>,
max_size_bytes: usize,
ttl: Duration,
}
impl FileCache {
pub fn new(capacity: usize) -> Self {
Self {
file_cache: Arc::new(Cache::new(capacity)),
directory_cache: Arc::new(Cache::new(capacity / 2)),
stats: Arc::new(std::sync::Mutex::new(EnhancedCacheStats::default())),
max_size_bytes: 50 * 1024 * 1024, ttl: Duration::from_secs(300), }
}
pub async fn get_file(&self, key: &str) -> Option<Value> {
let mut stats = self.stats.lock().unwrap();
if let Some(entry) = self.file_cache.get(key) {
if entry.timestamp.elapsed() < self.ttl {
stats.hits += 1;
return Some(entry.data.clone());
} else {
self.file_cache.remove(key);
stats.expired_evictions += 1;
}
}
stats.misses += 1;
None
}
pub async fn put_file(&self, key: String, value: Value) {
let size_bytes = serde_json::to_string(&value).unwrap_or_default().len();
let entry = EnhancedCacheEntry::new(value, size_bytes);
let mut stats = self.stats.lock().unwrap();
if stats.total_size_bytes + size_bytes > self.max_size_bytes {
stats.memory_evictions += 1;
}
self.file_cache.insert(key, entry);
stats.entries = self.file_cache.len();
stats.total_size_bytes += size_bytes;
}
pub async fn get_directory(&self, key: &str) -> Option<Value> {
let mut stats = self.stats.lock().unwrap();
if let Some(entry) = self.directory_cache.get(key) {
if entry.timestamp.elapsed() < self.ttl {
stats.hits += 1;
return Some(entry.data.clone());
} else {
self.directory_cache.remove(key);
stats.expired_evictions += 1;
}
}
stats.misses += 1;
None
}
pub async fn put_directory(&self, key: String, value: Value) {
let size_bytes = serde_json::to_string(&value).unwrap_or_default().len();
let entry = EnhancedCacheEntry::new(value, size_bytes);
let mut stats = self.stats.lock().unwrap();
self.directory_cache.insert(key, entry);
stats.entries += self.directory_cache.len();
stats.total_size_bytes += size_bytes;
}
pub async fn stats(&self) -> EnhancedCacheStats {
self.stats.lock().unwrap().clone()
}
pub async fn clear(&self) {
self.file_cache.clear();
self.directory_cache.clear();
*self.stats.lock().unwrap() = EnhancedCacheStats::default();
}
pub fn capacity(&self) -> (usize, usize) {
(
self.file_cache.capacity().try_into().unwrap_or(0),
self.directory_cache.capacity().try_into().unwrap_or(0),
)
}
pub fn len(&self) -> (usize, usize) {
(self.file_cache.len(), self.directory_cache.len())
}
}