ant_quic/bootstrap_cache/
config.rs1use std::path::PathBuf;
11use std::time::Duration;
12
13#[derive(Debug, Clone)]
15pub struct BootstrapCacheConfig {
16 pub cache_dir: PathBuf,
18
19 pub max_peers: usize,
21
22 pub epsilon: f64,
25
26 pub stale_threshold: Duration,
28
29 pub reachability_ttl: Duration,
31
32 pub save_interval: Duration,
34
35 pub quality_update_interval: Duration,
37
38 pub cleanup_interval: Duration,
40
41 pub min_peers_to_save: usize,
43
44 pub enable_file_locking: bool,
46
47 pub weights: QualityWeights,
49}
50
51#[derive(Debug, Clone)]
53pub struct QualityWeights {
54 pub success_rate: f64,
56 pub rtt: f64,
58 pub freshness: f64,
60 pub capabilities: f64,
62}
63
64impl Default for BootstrapCacheConfig {
65 fn default() -> Self {
66 Self {
67 cache_dir: default_cache_dir(),
68 max_peers: 30_000,
69 epsilon: 0.1,
70 stale_threshold: Duration::from_secs(7 * 24 * 3600), reachability_ttl: crate::reachability::DIRECT_REACHABILITY_TTL,
72 save_interval: Duration::from_secs(5 * 60), quality_update_interval: Duration::from_secs(3600), cleanup_interval: Duration::from_secs(6 * 3600), min_peers_to_save: 10,
76 enable_file_locking: true,
77 weights: QualityWeights::default(),
78 }
79 }
80}
81
82impl Default for QualityWeights {
83 fn default() -> Self {
84 Self {
85 success_rate: 0.4,
86 rtt: 0.25,
87 freshness: 0.15,
88 capabilities: 0.2,
89 }
90 }
91}
92
93impl BootstrapCacheConfig {
94 pub fn builder() -> BootstrapCacheConfigBuilder {
96 BootstrapCacheConfigBuilder::default()
97 }
98}
99
100#[derive(Default)]
102pub struct BootstrapCacheConfigBuilder {
103 config: BootstrapCacheConfig,
104}
105
106impl BootstrapCacheConfigBuilder {
107 pub fn cache_dir(mut self, dir: impl Into<PathBuf>) -> Self {
109 self.config.cache_dir = dir.into();
110 self
111 }
112
113 pub fn max_peers(mut self, max: usize) -> Self {
115 self.config.max_peers = max;
116 self
117 }
118
119 pub fn epsilon(mut self, epsilon: f64) -> Self {
121 self.config.epsilon = epsilon.clamp(0.0, 1.0);
122 self
123 }
124
125 pub fn reachability_ttl(mut self, ttl: Duration) -> Self {
127 self.config.reachability_ttl = ttl;
128 self
129 }
130
131 pub fn stale_threshold(mut self, duration: Duration) -> Self {
133 self.config.stale_threshold = duration;
134 self
135 }
136
137 pub fn save_interval(mut self, duration: Duration) -> Self {
139 self.config.save_interval = duration;
140 self
141 }
142
143 pub fn quality_update_interval(mut self, duration: Duration) -> Self {
145 self.config.quality_update_interval = duration;
146 self
147 }
148
149 pub fn cleanup_interval(mut self, duration: Duration) -> Self {
151 self.config.cleanup_interval = duration;
152 self
153 }
154
155 pub fn min_peers_to_save(mut self, min: usize) -> Self {
157 self.config.min_peers_to_save = min;
158 self
159 }
160
161 pub fn enable_file_locking(mut self, enable: bool) -> Self {
163 self.config.enable_file_locking = enable;
164 self
165 }
166
167 pub fn weights(mut self, weights: QualityWeights) -> Self {
169 self.config.weights = weights;
170 self
171 }
172
173 pub fn build(self) -> BootstrapCacheConfig {
175 self.config
176 }
177}
178
179fn default_cache_dir() -> PathBuf {
180 if let Ok(tmpdir) = std::env::var("TMPDIR") {
182 return PathBuf::from(tmpdir).join("ant-quic-cache");
183 }
184
185 if let Some(cache_dir) = dirs::cache_dir() {
187 cache_dir.join("ant-quic")
188 } else if let Some(home) = dirs::home_dir() {
189 home.join(".cache").join("ant-quic")
190 } else {
191 PathBuf::from(".ant-quic-cache")
192 }
193}
194
195#[cfg(test)]
196mod tests {
197 use super::*;
198
199 #[test]
200 fn test_default_config() {
201 let config = BootstrapCacheConfig::default();
202 assert_eq!(config.max_peers, 30_000);
203 assert!((config.epsilon - 0.1).abs() < f64::EPSILON);
204 assert_eq!(config.stale_threshold, Duration::from_secs(7 * 24 * 3600));
205 }
206
207 #[test]
208 fn test_builder() {
209 let config = BootstrapCacheConfig::builder()
210 .max_peers(10_000)
211 .epsilon(0.2)
212 .cache_dir("/tmp/test")
213 .build();
214
215 assert_eq!(config.max_peers, 10_000);
216 assert!((config.epsilon - 0.2).abs() < f64::EPSILON);
217 assert_eq!(config.cache_dir, PathBuf::from("/tmp/test"));
218 }
219
220 #[test]
221 fn test_epsilon_clamping() {
222 let config = BootstrapCacheConfig::builder().epsilon(1.5).build();
223 assert!((config.epsilon - 1.0).abs() < f64::EPSILON);
224
225 let config = BootstrapCacheConfig::builder().epsilon(-0.5).build();
226 assert!(config.epsilon.abs() < f64::EPSILON);
227 }
228}