candle_coreml/config/generator/
caching.rs1use crate::cache::manager::CacheManager;
6use crate::config::model::ModelConfig;
7use anyhow::Result;
8use tracing::{debug, info};
9
10pub struct ConfigCaching {
11 cache_manager: CacheManager,
12}
13
14impl ConfigCaching {
15 pub fn new(cache_manager: CacheManager) -> Self {
16 Self { cache_manager }
17 }
18
19 pub fn cache_config(&self, model_id: &str, config: &ModelConfig) -> Result<()> {
21 let configs_dir = self.cache_manager.configs_dir();
22 std::fs::create_dir_all(&configs_dir)?;
23
24 let config_filename = self.normalize_model_id_for_filename(model_id);
25 let config_path = configs_dir.join(config_filename);
26
27 let config_json = serde_json::to_string_pretty(config)?;
28 std::fs::write(&config_path, config_json)?;
29
30 info!("💾 Cached generated config at: {}", config_path.display());
31 Ok(())
32 }
33
34 pub fn load_cached_config(&self, model_id: &str) -> Result<Option<ModelConfig>> {
36 let configs_dir = self.cache_manager.configs_dir();
37 let config_filename = self.normalize_model_id_for_filename(model_id);
38 let config_path = configs_dir.join(config_filename);
39
40 if !config_path.exists() {
41 debug!("📖 No cached config found for: {}", model_id);
42 return Ok(None);
43 }
44
45 let config_json = std::fs::read_to_string(&config_path)?;
46 let config: ModelConfig = serde_json::from_str(&config_json)?;
47
48 debug!("📖 Loaded cached config for: {}", model_id);
49 Ok(Some(config))
50 }
51
52 pub fn has_cached_config(&self, model_id: &str) -> bool {
54 let configs_dir = self.cache_manager.configs_dir();
55 let config_filename = self.normalize_model_id_for_filename(model_id);
56 let config_path = configs_dir.join(config_filename);
57
58 config_path.exists()
59 }
60
61 pub fn clear_cached_config(&self, model_id: &str) -> Result<()> {
63 let configs_dir = self.cache_manager.configs_dir();
64 let config_filename = self.normalize_model_id_for_filename(model_id);
65 let config_path = configs_dir.join(config_filename);
66
67 if config_path.exists() {
68 std::fs::remove_file(&config_path)?;
69 info!("🗑️ Cleared cached config for: {}", model_id);
70 }
71
72 Ok(())
73 }
74
75 pub fn list_cached_configs(&self) -> Result<Vec<String>> {
77 let configs_dir = self.cache_manager.configs_dir();
78 let mut model_ids = Vec::new();
79
80 if !configs_dir.exists() {
81 return Ok(model_ids);
82 }
83
84 for entry in std::fs::read_dir(&configs_dir)? {
85 let entry = entry?;
86 let path = entry.path();
87
88 if path.is_file() && path.extension().is_some_and(|ext| ext == "json") {
89 if let Some(filename) = path.file_stem().and_then(|s| s.to_str()) {
90 let model_id = filename.replace("--", "/");
92 model_ids.push(model_id);
93 }
94 }
95 }
96
97 model_ids.sort();
98 Ok(model_ids)
99 }
100
101 pub fn get_cache_stats(&self) -> Result<CacheStats> {
103 let configs_dir = self.cache_manager.configs_dir();
104
105 if !configs_dir.exists() {
106 return Ok(CacheStats::default());
107 }
108
109 let mut stats = CacheStats::default();
110 let mut total_size = 0u64;
111
112 for entry in std::fs::read_dir(&configs_dir)? {
113 let entry = entry?;
114 let path = entry.path();
115
116 if path.is_file() && path.extension().is_some_and(|ext| ext == "json") {
117 stats.cached_configs += 1;
118
119 if let Ok(metadata) = std::fs::metadata(&path) {
120 total_size += metadata.len();
121 }
122 }
123 }
124
125 stats.total_size_bytes = total_size;
126 Ok(stats)
127 }
128
129 pub fn clear_all_cached_configs(&self) -> Result<usize> {
131 let configs_dir = self.cache_manager.configs_dir();
132 let mut cleared_count = 0;
133
134 if !configs_dir.exists() {
135 return Ok(cleared_count);
136 }
137
138 for entry in std::fs::read_dir(&configs_dir)? {
139 let entry = entry?;
140 let path = entry.path();
141
142 if path.is_file() && path.extension().is_some_and(|ext| ext == "json") {
143 std::fs::remove_file(&path)?;
144 cleared_count += 1;
145 }
146 }
147
148 info!("🗑️ Cleared {} cached configurations", cleared_count);
149 Ok(cleared_count)
150 }
151
152 fn normalize_model_id_for_filename(&self, model_id: &str) -> String {
155 format!("{}.json", model_id.replace('/', "--"))
156 }
157}
158
159#[derive(Debug, Default)]
160pub struct CacheStats {
161 pub cached_configs: usize,
162 pub total_size_bytes: u64,
163}
164
165impl CacheStats {
166 pub fn total_size_mb(&self) -> f64 {
167 self.total_size_bytes as f64 / (1024.0 * 1024.0)
168 }
169
170 pub fn average_size_kb(&self) -> f64 {
171 if self.cached_configs == 0 {
172 0.0
173 } else {
174 (self.total_size_bytes as f64 / self.cached_configs as f64) / 1024.0
175 }
176 }
177}