1use crate::Vector;
14use serde::{Deserialize, Serialize};
15use std::collections::HashMap;
16use std::fmt;
17use std::time::{Duration, Instant};
18
19pub use crate::advanced_caching_eviction::{MemoryCache, PersistentCache};
28pub use crate::advanced_caching_multilevel::{
29 CacheInvalidator, InvalidationStats, MultiLevelCache, MultiLevelCacheStats,
30};
31pub use crate::advanced_caching_worker::{
32 BackgroundCacheWorker, CacheAnalysisReport, CacheAnalyzer, CacheWarmer,
33};
34
35#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
41pub enum EvictionPolicy {
42 LRU,
44 LFU,
46 ARC,
48 FIFO,
50 TTL,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct CacheConfig {
57 pub max_memory_entries: usize,
59 pub max_memory_bytes: usize,
61 pub ttl: Option<Duration>,
63 pub eviction_policy: EvictionPolicy,
65 pub enable_persistent: bool,
67 pub persistent_cache_dir: Option<std::path::PathBuf>,
69 pub max_persistent_bytes: usize,
71 pub enable_compression: bool,
73 pub enable_background_updates: bool,
75 pub background_update_interval: Duration,
77}
78
79impl Default for CacheConfig {
80 fn default() -> Self {
81 Self {
82 max_memory_entries: 10_000,
83 max_memory_bytes: 1024 * 1024 * 100, ttl: Some(Duration::from_secs(3600)), eviction_policy: EvictionPolicy::LRU,
86 enable_persistent: true,
87 persistent_cache_dir: None,
88 max_persistent_bytes: 1024 * 1024 * 1024, enable_compression: true,
90 enable_background_updates: false,
91 background_update_interval: Duration::from_secs(300), }
93 }
94}
95
96#[derive(Debug, Clone)]
98pub struct CacheEntry {
99 pub data: Vector,
101 pub created_at: Instant,
103 pub last_accessed: Instant,
105 pub access_count: u64,
107 pub size_bytes: usize,
109 pub ttl: Option<Duration>,
111 pub tags: HashMap<String, String>,
113}
114
115impl CacheEntry {
116 pub fn new(data: Vector) -> Self {
117 let now = Instant::now();
118 let size_bytes = data.dimensions * std::mem::size_of::<f32>() + 64;
119
120 Self {
121 data,
122 created_at: now,
123 last_accessed: now,
124 access_count: 1,
125 size_bytes,
126 ttl: None,
127 tags: HashMap::new(),
128 }
129 }
130
131 pub fn with_ttl(mut self, ttl: Duration) -> Self {
132 self.ttl = Some(ttl);
133 self
134 }
135
136 pub fn with_tags(mut self, tags: HashMap<String, String>) -> Self {
137 self.tags = tags;
138 self
139 }
140
141 pub fn is_expired(&self) -> bool {
143 if let Some(ttl) = self.ttl {
144 self.created_at.elapsed() > ttl
145 } else {
146 false
147 }
148 }
149
150 pub fn touch(&mut self) {
152 self.last_accessed = Instant::now();
153 self.access_count += 1;
154 }
155}
156
157#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
159pub struct CacheKey {
160 pub namespace: String,
161 pub key: String,
162 pub variant: Option<String>,
163}
164
165impl CacheKey {
166 pub fn new(namespace: impl Into<String>, key: impl Into<String>) -> Self {
167 Self {
168 namespace: namespace.into(),
169 key: key.into(),
170 variant: None,
171 }
172 }
173
174 pub fn with_variant(mut self, variant: impl Into<String>) -> Self {
175 self.variant = Some(variant.into());
176 self
177 }
178}
179
180impl fmt::Display for CacheKey {
181 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
182 if let Some(ref variant) = self.variant {
183 write!(f, "{}:{}:{}", self.namespace, self.key, variant)
184 } else {
185 write!(f, "{}:{}", self.namespace, self.key)
186 }
187 }
188}
189
190#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct CacheStats {
193 pub entries: usize,
194 pub memory_bytes: usize,
195 pub max_entries: usize,
196 pub max_memory_bytes: usize,
197 pub hit_ratio: f32,
198}