Skip to main content

rez_next_cache/
cache_config.rs

1//! Cache configuration and settings
2//!
3//! This module provides unified configuration for all cache types,
4//! integrating with existing cache configurations while adding
5//! intelligent caching features.
6
7use crate::{
8    EvictionStrategy, DEFAULT_L1_CAPACITY, DEFAULT_L2_CAPACITY, DEFAULT_MEMORY_LIMIT_MB,
9    DEFAULT_TTL_SECONDS,
10};
11use serde::{Deserialize, Serialize};
12use std::path::PathBuf;
13use std::time::Duration;
14
15/// Unified cache configuration
16///
17/// This configuration integrates settings for multi-level caching,
18/// predictive preheating, and adaptive tuning.
19#[derive(Debug, Clone, Serialize, Deserialize, Default)]
20pub struct UnifiedCacheConfig {
21    /// L1 cache configuration (memory cache)
22    pub l1_config: L1CacheConfig,
23    /// L2 cache configuration (disk cache)
24    pub l2_config: L2CacheConfig,
25    /// Predictive preheating configuration
26    pub preheating_config: PreheatingConfig,
27    /// Adaptive tuning configuration
28    pub tuning_config: TuningConfig,
29    /// Monitoring and statistics configuration
30    pub monitoring_config: MonitoringConfig,
31}
32
33/// L1 (memory) cache configuration
34#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct L1CacheConfig {
36    /// Maximum number of entries in L1 cache
37    pub max_entries: usize,
38    /// Maximum memory usage in bytes
39    pub max_memory_bytes: u64,
40    /// Default TTL for L1 entries (in seconds)
41    pub default_ttl: u64,
42    /// Eviction strategy
43    pub eviction_strategy: EvictionStrategy,
44    /// Enable concurrent access optimization
45    pub enable_concurrent_access: bool,
46    /// Shard count for DashMap (0 = auto-detect)
47    pub shard_count: usize,
48    /// Promotion threshold (access count to promote from L2 to L1)
49    pub promotion_threshold: u64,
50}
51
52impl Default for L1CacheConfig {
53    fn default() -> Self {
54        Self {
55            max_entries: DEFAULT_L1_CAPACITY,
56            max_memory_bytes: DEFAULT_MEMORY_LIMIT_MB * 1024 * 1024,
57            default_ttl: DEFAULT_TTL_SECONDS,
58            eviction_strategy: EvictionStrategy::LRU,
59            enable_concurrent_access: true,
60            shard_count: 0,         // Auto-detect based on CPU cores
61            promotion_threshold: 3, // Promote after 3 accesses
62        }
63    }
64}
65
66/// L2 (disk) cache configuration
67#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct L2CacheConfig {
69    /// Maximum number of entries in L2 cache
70    pub max_entries: usize,
71    /// Maximum disk usage in bytes
72    pub max_disk_bytes: u64,
73    /// Default TTL for L2 entries (in seconds)
74    pub default_ttl: u64,
75    /// Cache directory path
76    pub cache_dir: PathBuf,
77    /// Enable compression for disk storage
78    pub enable_compression: bool,
79    /// Cleanup interval (in seconds)
80    pub cleanup_interval: u64,
81    /// Enable background cleanup
82    pub enable_background_cleanup: bool,
83}
84
85impl Default for L2CacheConfig {
86    fn default() -> Self {
87        Self {
88            max_entries: DEFAULT_L2_CAPACITY,
89            max_disk_bytes: 1024 * 1024 * 1024,    // 1 GB
90            default_ttl: DEFAULT_TTL_SECONDS * 24, // 24 hours for disk cache
91            cache_dir: PathBuf::from(".rez_intelligent_cache"),
92            enable_compression: true,
93            cleanup_interval: 300, // 5 minutes
94            enable_background_cleanup: true,
95        }
96    }
97}
98
99/// Predictive preheating configuration
100#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct PreheatingConfig {
102    /// Enable predictive preheating
103    pub enable_predictive_preheating: bool,
104    /// Enable pattern learning
105    pub enable_pattern_learning: bool,
106    /// Minimum prediction confidence threshold (0.0 to 1.0)
107    pub min_confidence_threshold: f64,
108    /// Maximum number of entries to preheat per cycle
109    pub max_preheat_entries: usize,
110    /// Maximum concurrent preheating operations
111    pub max_concurrent_preheats: usize,
112    /// Maximum preheating queue size
113    pub max_preheat_queue_size: usize,
114    /// Preheating interval (in seconds)
115    pub preheat_interval: u64,
116    /// Preheating window (seconds before predicted access)
117    pub preheat_window_seconds: u64,
118    /// Pattern window for learning (in seconds)
119    pub pattern_window_seconds: u64,
120    /// Enable background preheating
121    pub enable_background_preheat: bool,
122    /// Maximum CPU usage for preheating (0.0 to 1.0)
123    pub max_cpu_usage: f64,
124    /// Access pattern history size
125    pub history_size: usize,
126}
127
128impl Default for PreheatingConfig {
129    fn default() -> Self {
130        Self {
131            enable_predictive_preheating: true,
132            enable_pattern_learning: true,
133            min_confidence_threshold: 0.7,
134            max_preheat_entries: 100,
135            max_concurrent_preheats: 10,
136            max_preheat_queue_size: 1000,
137            preheat_interval: 60,         // 1 minute
138            preheat_window_seconds: 300,  // 5 minutes
139            pattern_window_seconds: 3600, // 1 hour
140            enable_background_preheat: true,
141            max_cpu_usage: 0.1, // 10% CPU usage limit
142            history_size: 10000,
143        }
144    }
145}
146
147/// Adaptive tuning configuration
148#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct TuningConfig {
150    /// Enable adaptive tuning
151    pub enable_adaptive_tuning: bool,
152    /// Tuning interval (in seconds)
153    pub tuning_interval: u64,
154    /// Target hit rate for optimization
155    pub target_hit_rate: f64,
156    /// Minimum hit rate threshold for tuning
157    pub min_hit_rate: f64,
158    /// Maximum adjustment factor per tuning cycle
159    pub max_adjustment_factor: f64,
160    /// Minimum confidence for automatic tuning
161    pub min_confidence_for_auto_tuning: f64,
162    /// Performance window size for analysis
163    pub performance_window_size: usize,
164    /// Minimum samples required for tuning decisions
165    pub min_samples_for_tuning: usize,
166    /// Enable TTL adaptation
167    pub enable_ttl_adaptation: bool,
168    /// Enable capacity adaptation
169    pub enable_capacity_adaptation: bool,
170    /// Enable eviction strategy adaptation
171    pub enable_eviction_adaptation: bool,
172    /// Stability window size (number of cycles)
173    pub stability_window: usize,
174}
175
176impl Default for TuningConfig {
177    fn default() -> Self {
178        Self {
179            enable_adaptive_tuning: true,
180            tuning_interval: 300,       // 5 minutes
181            target_hit_rate: 0.9,       // 90% target hit rate
182            min_hit_rate: 0.8,          // 80% minimum hit rate
183            max_adjustment_factor: 0.1, // 10% maximum adjustment
184            min_confidence_for_auto_tuning: 0.8,
185            performance_window_size: 100,
186            min_samples_for_tuning: 10,
187            enable_ttl_adaptation: true,
188            enable_capacity_adaptation: true,
189            enable_eviction_adaptation: false, // Conservative default
190            stability_window: 5,
191        }
192    }
193}
194
195/// Monitoring and statistics configuration
196#[derive(Debug, Clone, Serialize, Deserialize)]
197pub struct MonitoringConfig {
198    /// Enable detailed statistics collection
199    pub enable_detailed_stats: bool,
200    /// Statistics collection interval (in seconds)
201    pub stats_interval: u64,
202    /// Enable performance metrics
203    pub enable_performance_metrics: bool,
204    /// Enable cache event logging
205    pub enable_event_logging: bool,
206    /// Maximum number of events to keep in memory
207    pub max_events_in_memory: usize,
208    /// Enable real-time monitoring
209    pub enable_realtime_monitoring: bool,
210}
211
212impl Default for MonitoringConfig {
213    fn default() -> Self {
214        Self {
215            enable_detailed_stats: true,
216            stats_interval: 60, // 1 minute
217            enable_performance_metrics: true,
218            enable_event_logging: false, // Disabled by default for performance
219            max_events_in_memory: 1000,
220            enable_realtime_monitoring: false, // Disabled by default
221        }
222    }
223}
224
225/// Cache operation timeout configuration
226#[derive(Debug, Clone, Serialize, Deserialize)]
227pub struct TimeoutConfig {
228    /// Timeout for cache get operations
229    pub get_timeout: Duration,
230    /// Timeout for cache put operations
231    pub put_timeout: Duration,
232    /// Timeout for cache cleanup operations
233    pub cleanup_timeout: Duration,
234    /// Timeout for preheating operations
235    pub preheat_timeout: Duration,
236}
237
238impl Default for TimeoutConfig {
239    fn default() -> Self {
240        Self {
241            get_timeout: Duration::from_millis(100),
242            put_timeout: Duration::from_millis(500),
243            cleanup_timeout: Duration::from_secs(30),
244            preheat_timeout: Duration::from_secs(10),
245        }
246    }
247}
248
249impl UnifiedCacheConfig {
250    /// Create a configuration optimized for high performance
251    pub fn high_performance() -> Self {
252        Self {
253            l1_config: L1CacheConfig {
254                max_entries: 50000,
255                max_memory_bytes: 500 * 1024 * 1024, // 500 MB
256                enable_concurrent_access: true,
257                shard_count: num_cpus::get() * 2,
258                ..Default::default()
259            },
260            l2_config: L2CacheConfig {
261                max_entries: 500000,
262                max_disk_bytes: 5 * 1024 * 1024 * 1024, // 5 GB
263                enable_compression: true,
264                enable_background_cleanup: true,
265                ..Default::default()
266            },
267            preheating_config: PreheatingConfig {
268                enable_predictive_preheating: true,
269                min_confidence_threshold: 0.6,
270                max_preheat_entries: 500,
271                max_cpu_usage: 0.2, // 20% CPU usage
272                ..Default::default()
273            },
274            tuning_config: TuningConfig {
275                enable_adaptive_tuning: true,
276                tuning_interval: 120,        // 2 minutes
277                max_adjustment_factor: 0.15, // 15% adjustment
278                ..Default::default()
279            },
280            monitoring_config: MonitoringConfig {
281                enable_detailed_stats: true,
282                enable_performance_metrics: true,
283                enable_realtime_monitoring: true,
284                ..Default::default()
285            },
286        }
287    }
288
289    /// Create a configuration optimized for low memory usage
290    pub fn low_memory() -> Self {
291        Self {
292            l1_config: L1CacheConfig {
293                max_entries: 1000,
294                max_memory_bytes: 10 * 1024 * 1024, // 10 MB
295                ..Default::default()
296            },
297            l2_config: L2CacheConfig {
298                max_entries: 10000,
299                max_disk_bytes: 100 * 1024 * 1024, // 100 MB
300                enable_compression: true,
301                ..Default::default()
302            },
303            preheating_config: PreheatingConfig {
304                enable_predictive_preheating: false, // Disable preheating to save memory
305                ..Default::default()
306            },
307            tuning_config: TuningConfig {
308                enable_adaptive_tuning: false, // Disable tuning to save CPU
309                ..Default::default()
310            },
311            monitoring_config: MonitoringConfig {
312                enable_detailed_stats: false,
313                enable_performance_metrics: false,
314                ..Default::default()
315            },
316        }
317    }
318
319    /// Validate the configuration
320    pub fn validate(&self) -> Result<(), String> {
321        if self.l1_config.max_entries == 0 {
322            return Err("L1 max_entries must be greater than 0".to_string());
323        }
324
325        if self.l2_config.max_entries == 0 {
326            return Err("L2 max_entries must be greater than 0".to_string());
327        }
328
329        if self.preheating_config.min_confidence_threshold < 0.0
330            || self.preheating_config.min_confidence_threshold > 1.0
331        {
332            return Err(
333                "Preheating min_confidence_threshold must be between 0.0 and 1.0".to_string(),
334            );
335        }
336
337        if self.tuning_config.min_hit_rate < 0.0 || self.tuning_config.min_hit_rate > 1.0 {
338            return Err("Tuning min_hit_rate must be between 0.0 and 1.0".to_string());
339        }
340
341        Ok(())
342    }
343}
344
345#[cfg(test)]
346mod tests {
347    use super::*;
348
349    #[test]
350    fn test_default_config() {
351        let config = UnifiedCacheConfig::default();
352        assert!(config.validate().is_ok());
353    }
354
355    #[test]
356    fn test_high_performance_config() {
357        let config = UnifiedCacheConfig::high_performance();
358        assert!(config.validate().is_ok());
359        assert!(config.l1_config.max_entries > DEFAULT_L1_CAPACITY);
360    }
361
362    #[test]
363    fn test_low_memory_config() {
364        let config = UnifiedCacheConfig::low_memory();
365        assert!(config.validate().is_ok());
366        assert!(config.l1_config.max_entries < DEFAULT_L1_CAPACITY);
367        assert!(!config.preheating_config.enable_predictive_preheating);
368    }
369
370    #[test]
371    fn test_config_validation() {
372        let mut config = UnifiedCacheConfig::default();
373        config.l1_config.max_entries = 0;
374        assert!(config.validate().is_err());
375    }
376}