//! Multi-tier cache management system use crate::{ error::{OptimizerError, Result}, optimizer::CacheConfig, pattern_db::CompilationPattern, }; use dashmap::DashMap; use parking_lot::RwLock; use serde::{Deserialize, Serialize}; use std::{sync::Arc, time::Instant}; /// Multi-tier cache manager for compilation artifacts pub struct CacheManager { config: CacheConfig, hot_cache: Arc>, warm_cache: Arc>, cold_cache: Arc>, stats: Arc>, } impl CacheManager { /// Create a new cache manager with default configuration pub fn new() -> Result { Ok(Self::with_config(CacheConfig::default())?) } /// Create with custom configuration pub fn with_config(config: CacheConfig) -> Result { Ok(Self { config, hot_cache: Arc::new(DashMap::new()), warm_cache: Arc::new(DashMap::new()), cold_cache: Arc::new(DashMap::new()), stats: Arc::new(RwLock::new(CacheStats::default())), }) } /// Pre-seed caches with known patterns pub async fn pre_seed_with_patterns(&self, patterns: &[CompilationPattern]) -> Result<()> { let mut stats = self.stats.write(); stats.pre_seed_operations += 1; for pattern in patterns { // Simulate pre-seeding by adding pattern entries to warm cache let entry = CacheEntry { data: pattern.fingerprint.clone(), created_at: chrono::Utc::now(), last_accessed: chrono::Utc::now(), access_count: 0, size_bytes: pattern.fingerprint.len(), }; self.warm_cache.insert(pattern.pattern_id.clone(), entry); stats.entries_pre_seeded += 1; } Ok(()) } /// Perform intelligent cache warming pub async fn intelligent_warm(&self) -> Result { let start_time = Instant::now(); let mut stats = self.stats.write(); stats.warming_operations += 1; // Simulate intelligent warming by promoting entries from cold to warm let entries_warmed = self.promote_cold_to_warm().await?; let warming_time = start_time.elapsed(); stats.total_warming_time += warming_time; Ok(WarmingResult { entries_warmed, warming_time, cache_hit_rate: self.calculate_hit_rate(), }) } /// Get an entry from the cache hierarchy pub async fn get(&self, key: &str) -> Option> { let mut stats = self.stats.write(); stats.total_accesses += 1; // Check hot cache first if let Some(mut entry) = self.hot_cache.get_mut(key) { entry.last_accessed = chrono::Utc::now(); entry.access_count += 1; stats.hot_hits += 1; return Some(entry.data.clone()); } // Check warm cache if let Some(entry) = self.warm_cache.get(key) { let mut entry_clone = entry.clone(); entry_clone.last_accessed = chrono::Utc::now(); entry_clone.access_count += 1; // Promote to hot cache self.hot_cache.insert(key.to_string(), entry_clone.clone()); stats.warm_hits += 1; return Some(entry_clone.data); } // Check cold cache if let Some(entry) = self.cold_cache.get(key) { let mut entry_clone = entry.clone(); entry_clone.last_accessed = chrono::Utc::now(); entry_clone.access_count += 1; // Promote to warm cache self.warm_cache.insert(key.to_string(), entry_clone.clone()); stats.cold_hits += 1; return Some(entry_clone.data); } stats.misses += 1; None } /// Store an entry in the cache pub async fn put(&self, key: String, data: Vec) -> Result<()> { let entry = CacheEntry { data, created_at: chrono::Utc::now(), last_accessed: chrono::Utc::now(), access_count: 0, size_bytes: 0, // Would calculate actual size }; // Store in hot cache for immediate access self.hot_cache.insert(key, entry); let mut stats = self.stats.write(); stats.total_insertions += 1; Ok(()) } /// Clear all caches pub async fn clear_all(&self) -> Result<()> { self.hot_cache.clear(); self.warm_cache.clear(); self.cold_cache.clear(); let mut stats = self.stats.write(); *stats = CacheStats::default(); Ok(()) } /// Get current cache statistics pub fn get_stats(&self) -> CacheStats { self.stats.read().clone() } async fn promote_cold_to_warm(&self) -> Result { let mut promoted = 0; // Simplified promotion logic for entry in self.cold_cache.iter() { if entry.access_count > 0 { let (key, value) = entry.pair(); self.warm_cache.insert(key.clone(), value.clone()); promoted += 1; if promoted >= 10 { break; // Limit promotions per warming cycle } } } Ok(promoted) } fn calculate_hit_rate(&self) -> f64 { let stats = self.stats.read(); if stats.total_accesses == 0 { return 0.0; } let total_hits = stats.hot_hits + stats.warm_hits + stats.cold_hits; (total_hits as f64) / (stats.total_accesses as f64) * 100.0 } } /// Result of cache warming operation #[derive(Debug, Clone)] pub struct WarmingResult { /// Number of entries warmed pub entries_warmed: usize, /// Time spent warming pub warming_time: std::time::Duration, /// Current cache hit rate pub cache_hit_rate: f64, } /// Cache entry with metadata #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CacheEntry { /// Cached data pub data: Vec, /// When entry was created pub created_at: chrono::DateTime, /// Last access time pub last_accessed: chrono::DateTime, /// Number of times accessed pub access_count: u64, /// Size in bytes pub size_bytes: usize, } /// Cache performance statistics #[derive(Debug, Clone, Default)] pub struct CacheStats { /// Total cache accesses pub total_accesses: u64, /// Hot cache hits pub hot_hits: u64, /// Warm cache hits pub warm_hits: u64, /// Cold cache hits pub cold_hits: u64, /// Cache misses pub misses: u64, /// Total insertions pub total_insertions: u64, /// Pre-seed operations performed pub pre_seed_operations: u64, /// Entries pre-seeded pub entries_pre_seeded: u64, /// Warming operations performed pub warming_operations: u64, /// Total time spent warming pub total_warming_time: std::time::Duration, }