Skip to main content

oxigdal_cache_advanced/
lib.rs

1//! Advanced Multi-Tier Caching for OxiGDAL
2//!
3//! This crate provides intelligent caching with:
4//! - Multi-tier cache (L1: memory, L2: SSD, L3: network)
5//! - Predictive prefetching with ML
6//! - Adaptive compression
7//! - Distributed cache protocol
8//! - Cache analytics and warming
9//! - Advanced eviction policies
10
11#![warn(missing_docs)]
12#![deny(unsafe_code)]
13
14pub mod analytics;
15pub mod coherency;
16pub mod compression;
17pub mod distributed;
18pub mod error;
19pub mod eviction;
20pub mod multi_tier;
21pub mod observability;
22pub mod partitioning;
23pub mod predictive;
24pub mod tiering;
25pub mod warming;
26pub mod write_policy;
27
28pub use error::{CacheError, Result};
29pub use multi_tier::{CacheKey, CacheTier, CacheValue, MultiTierCache};
30
31/// Cache statistics
32#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
33pub struct CacheStats {
34    /// Total number of cache hits
35    pub hits: u64,
36    /// Total number of cache misses
37    pub misses: u64,
38    /// Number of evictions
39    pub evictions: u64,
40    /// Total bytes stored
41    pub bytes_stored: u64,
42    /// Number of items in cache
43    pub item_count: usize,
44}
45
46impl CacheStats {
47    /// Create new cache statistics
48    pub fn new() -> Self {
49        Self {
50            hits: 0,
51            misses: 0,
52            evictions: 0,
53            bytes_stored: 0,
54            item_count: 0,
55        }
56    }
57
58    /// Calculate hit rate as a percentage
59    pub fn hit_rate(&self) -> f64 {
60        if self.hits + self.misses == 0 {
61            0.0
62        } else {
63            (self.hits as f64) / ((self.hits + self.misses) as f64) * 100.0
64        }
65    }
66
67    /// Calculate average item size in bytes
68    pub fn avg_item_size(&self) -> f64 {
69        if self.item_count == 0 {
70            0.0
71        } else {
72            (self.bytes_stored as f64) / (self.item_count as f64)
73        }
74    }
75}
76
77impl Default for CacheStats {
78    fn default() -> Self {
79        Self::new()
80    }
81}
82
83/// Cache configuration
84#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
85pub struct CacheConfig {
86    /// L1 cache size in bytes
87    pub l1_size: usize,
88    /// L2 cache size in bytes
89    pub l2_size: usize,
90    /// L3 cache size in bytes
91    pub l3_size: usize,
92    /// Enable compression
93    pub enable_compression: bool,
94    /// Enable predictive prefetching
95    pub enable_prefetch: bool,
96    /// Enable distributed cache
97    pub enable_distributed: bool,
98    /// Cache directory for disk-based tiers
99    pub cache_dir: Option<std::path::PathBuf>,
100}
101
102impl Default for CacheConfig {
103    fn default() -> Self {
104        Self {
105            l1_size: 128 * 1024 * 1024,       // 128 MB
106            l2_size: 1024 * 1024 * 1024,      // 1 GB
107            l3_size: 10 * 1024 * 1024 * 1024, // 10 GB
108            enable_compression: true,
109            enable_prefetch: true,
110            enable_distributed: false,
111            cache_dir: None,
112        }
113    }
114}
115
116#[cfg(test)]
117mod tests {
118    use super::*;
119
120    #[test]
121    fn test_cache_stats_hit_rate() {
122        let mut stats = CacheStats::new();
123        stats.hits = 80;
124        stats.misses = 20;
125
126        approx::assert_relative_eq!(stats.hit_rate(), 80.0, epsilon = 0.01);
127    }
128
129    #[test]
130    fn test_cache_stats_avg_size() {
131        let mut stats = CacheStats::new();
132        stats.bytes_stored = 1000;
133        stats.item_count = 10;
134
135        approx::assert_relative_eq!(stats.avg_item_size(), 100.0, epsilon = 0.01);
136    }
137
138    #[test]
139    fn test_default_config() {
140        let config = CacheConfig::default();
141        assert!(config.enable_compression);
142        assert!(config.enable_prefetch);
143        assert!(!config.enable_distributed);
144    }
145}