use crate::{
EvictionStrategy, DEFAULT_L1_CAPACITY, DEFAULT_L2_CAPACITY, DEFAULT_MEMORY_LIMIT_MB,
DEFAULT_TTL_SECONDS,
};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use std::time::Duration;
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct UnifiedCacheConfig {
pub l1_config: L1CacheConfig,
pub l2_config: L2CacheConfig,
pub preheating_config: PreheatingConfig,
pub tuning_config: TuningConfig,
pub monitoring_config: MonitoringConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct L1CacheConfig {
pub max_entries: usize,
pub max_memory_bytes: u64,
pub default_ttl: u64,
pub eviction_strategy: EvictionStrategy,
pub enable_concurrent_access: bool,
pub shard_count: usize,
pub promotion_threshold: u64,
}
impl Default for L1CacheConfig {
fn default() -> Self {
Self {
max_entries: DEFAULT_L1_CAPACITY,
max_memory_bytes: DEFAULT_MEMORY_LIMIT_MB * 1024 * 1024,
default_ttl: DEFAULT_TTL_SECONDS,
eviction_strategy: EvictionStrategy::LRU,
enable_concurrent_access: true,
shard_count: 0, promotion_threshold: 3, }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct L2CacheConfig {
pub max_entries: usize,
pub max_disk_bytes: u64,
pub default_ttl: u64,
pub cache_dir: PathBuf,
pub enable_compression: bool,
pub cleanup_interval: u64,
pub enable_background_cleanup: bool,
}
impl Default for L2CacheConfig {
fn default() -> Self {
Self {
max_entries: DEFAULT_L2_CAPACITY,
max_disk_bytes: 1024 * 1024 * 1024, default_ttl: DEFAULT_TTL_SECONDS * 24, cache_dir: PathBuf::from(".rez_intelligent_cache"),
enable_compression: true,
cleanup_interval: 300, enable_background_cleanup: true,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PreheatingConfig {
pub enable_predictive_preheating: bool,
pub enable_pattern_learning: bool,
pub min_confidence_threshold: f64,
pub max_preheat_entries: usize,
pub max_concurrent_preheats: usize,
pub max_preheat_queue_size: usize,
pub preheat_interval: u64,
pub preheat_window_seconds: u64,
pub pattern_window_seconds: u64,
pub enable_background_preheat: bool,
pub max_cpu_usage: f64,
pub history_size: usize,
}
impl Default for PreheatingConfig {
fn default() -> Self {
Self {
enable_predictive_preheating: true,
enable_pattern_learning: true,
min_confidence_threshold: 0.7,
max_preheat_entries: 100,
max_concurrent_preheats: 10,
max_preheat_queue_size: 1000,
preheat_interval: 60, preheat_window_seconds: 300, pattern_window_seconds: 3600, enable_background_preheat: true,
max_cpu_usage: 0.1, history_size: 10000,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TuningConfig {
pub enable_adaptive_tuning: bool,
pub tuning_interval: u64,
pub target_hit_rate: f64,
pub min_hit_rate: f64,
pub max_adjustment_factor: f64,
pub min_confidence_for_auto_tuning: f64,
pub performance_window_size: usize,
pub min_samples_for_tuning: usize,
pub enable_ttl_adaptation: bool,
pub enable_capacity_adaptation: bool,
pub enable_eviction_adaptation: bool,
pub stability_window: usize,
}
impl Default for TuningConfig {
fn default() -> Self {
Self {
enable_adaptive_tuning: true,
tuning_interval: 300, target_hit_rate: 0.9, min_hit_rate: 0.8, max_adjustment_factor: 0.1, min_confidence_for_auto_tuning: 0.8,
performance_window_size: 100,
min_samples_for_tuning: 10,
enable_ttl_adaptation: true,
enable_capacity_adaptation: true,
enable_eviction_adaptation: false, stability_window: 5,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MonitoringConfig {
pub enable_detailed_stats: bool,
pub stats_interval: u64,
pub enable_performance_metrics: bool,
pub enable_event_logging: bool,
pub max_events_in_memory: usize,
pub enable_realtime_monitoring: bool,
}
impl Default for MonitoringConfig {
fn default() -> Self {
Self {
enable_detailed_stats: true,
stats_interval: 60, enable_performance_metrics: true,
enable_event_logging: false, max_events_in_memory: 1000,
enable_realtime_monitoring: false, }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TimeoutConfig {
pub get_timeout: Duration,
pub put_timeout: Duration,
pub cleanup_timeout: Duration,
pub preheat_timeout: Duration,
}
impl Default for TimeoutConfig {
fn default() -> Self {
Self {
get_timeout: Duration::from_millis(100),
put_timeout: Duration::from_millis(500),
cleanup_timeout: Duration::from_secs(30),
preheat_timeout: Duration::from_secs(10),
}
}
}
impl UnifiedCacheConfig {
pub fn high_performance() -> Self {
Self {
l1_config: L1CacheConfig {
max_entries: 50000,
max_memory_bytes: 500 * 1024 * 1024, enable_concurrent_access: true,
shard_count: num_cpus::get() * 2,
..Default::default()
},
l2_config: L2CacheConfig {
max_entries: 500000,
max_disk_bytes: 5 * 1024 * 1024 * 1024, enable_compression: true,
enable_background_cleanup: true,
..Default::default()
},
preheating_config: PreheatingConfig {
enable_predictive_preheating: true,
min_confidence_threshold: 0.6,
max_preheat_entries: 500,
max_cpu_usage: 0.2, ..Default::default()
},
tuning_config: TuningConfig {
enable_adaptive_tuning: true,
tuning_interval: 120, max_adjustment_factor: 0.15, ..Default::default()
},
monitoring_config: MonitoringConfig {
enable_detailed_stats: true,
enable_performance_metrics: true,
enable_realtime_monitoring: true,
..Default::default()
},
}
}
pub fn low_memory() -> Self {
Self {
l1_config: L1CacheConfig {
max_entries: 1000,
max_memory_bytes: 10 * 1024 * 1024, ..Default::default()
},
l2_config: L2CacheConfig {
max_entries: 10000,
max_disk_bytes: 100 * 1024 * 1024, enable_compression: true,
..Default::default()
},
preheating_config: PreheatingConfig {
enable_predictive_preheating: false, ..Default::default()
},
tuning_config: TuningConfig {
enable_adaptive_tuning: false, ..Default::default()
},
monitoring_config: MonitoringConfig {
enable_detailed_stats: false,
enable_performance_metrics: false,
..Default::default()
},
}
}
pub fn validate(&self) -> Result<(), String> {
if self.l1_config.max_entries == 0 {
return Err("L1 max_entries must be greater than 0".to_string());
}
if self.l2_config.max_entries == 0 {
return Err("L2 max_entries must be greater than 0".to_string());
}
if self.preheating_config.min_confidence_threshold < 0.0
|| self.preheating_config.min_confidence_threshold > 1.0
{
return Err(
"Preheating min_confidence_threshold must be between 0.0 and 1.0".to_string(),
);
}
if self.tuning_config.min_hit_rate < 0.0 || self.tuning_config.min_hit_rate > 1.0 {
return Err("Tuning min_hit_rate must be between 0.0 and 1.0".to_string());
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = UnifiedCacheConfig::default();
assert!(config.validate().is_ok());
}
#[test]
fn test_high_performance_config() {
let config = UnifiedCacheConfig::high_performance();
assert!(config.validate().is_ok());
assert!(config.l1_config.max_entries > DEFAULT_L1_CAPACITY);
}
#[test]
fn test_low_memory_config() {
let config = UnifiedCacheConfig::low_memory();
assert!(config.validate().is_ok());
assert!(config.l1_config.max_entries < DEFAULT_L1_CAPACITY);
assert!(!config.preheating_config.enable_predictive_preheating);
}
#[test]
fn test_config_validation() {
let mut config = UnifiedCacheConfig::default();
config.l1_config.max_entries = 0;
assert!(config.validate().is_err());
}
}