ant_quic/bootstrap_cache/
config.rs1use std::path::PathBuf;
4use std::time::Duration;
5
6#[derive(Debug, Clone)]
8pub struct BootstrapCacheConfig {
9 pub cache_dir: PathBuf,
11
12 pub max_peers: usize,
14
15 pub epsilon: f64,
18
19 pub stale_threshold: Duration,
21
22 pub save_interval: Duration,
24
25 pub quality_update_interval: Duration,
27
28 pub cleanup_interval: Duration,
30
31 pub min_peers_to_save: usize,
33
34 pub enable_file_locking: bool,
36
37 pub weights: QualityWeights,
39}
40
41#[derive(Debug, Clone)]
43pub struct QualityWeights {
44 pub success_rate: f64,
46 pub rtt: f64,
48 pub freshness: f64,
50 pub capabilities: f64,
52}
53
54impl Default for BootstrapCacheConfig {
55 fn default() -> Self {
56 Self {
57 cache_dir: default_cache_dir(),
58 max_peers: 20_000,
59 epsilon: 0.1,
60 stale_threshold: Duration::from_secs(7 * 24 * 3600), 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,
65 enable_file_locking: true,
66 weights: QualityWeights::default(),
67 }
68 }
69}
70
71impl Default for QualityWeights {
72 fn default() -> Self {
73 Self {
74 success_rate: 0.4,
75 rtt: 0.25,
76 freshness: 0.15,
77 capabilities: 0.2,
78 }
79 }
80}
81
82impl BootstrapCacheConfig {
83 pub fn builder() -> BootstrapCacheConfigBuilder {
85 BootstrapCacheConfigBuilder::default()
86 }
87}
88
89#[derive(Default)]
91pub struct BootstrapCacheConfigBuilder {
92 config: BootstrapCacheConfig,
93}
94
95impl BootstrapCacheConfigBuilder {
96 pub fn cache_dir(mut self, dir: impl Into<PathBuf>) -> Self {
98 self.config.cache_dir = dir.into();
99 self
100 }
101
102 pub fn max_peers(mut self, max: usize) -> Self {
104 self.config.max_peers = max;
105 self
106 }
107
108 pub fn epsilon(mut self, epsilon: f64) -> Self {
110 self.config.epsilon = epsilon.clamp(0.0, 1.0);
111 self
112 }
113
114 pub fn stale_threshold(mut self, duration: Duration) -> Self {
116 self.config.stale_threshold = duration;
117 self
118 }
119
120 pub fn save_interval(mut self, duration: Duration) -> Self {
122 self.config.save_interval = duration;
123 self
124 }
125
126 pub fn quality_update_interval(mut self, duration: Duration) -> Self {
128 self.config.quality_update_interval = duration;
129 self
130 }
131
132 pub fn cleanup_interval(mut self, duration: Duration) -> Self {
134 self.config.cleanup_interval = duration;
135 self
136 }
137
138 pub fn min_peers_to_save(mut self, min: usize) -> Self {
140 self.config.min_peers_to_save = min;
141 self
142 }
143
144 pub fn enable_file_locking(mut self, enable: bool) -> Self {
146 self.config.enable_file_locking = enable;
147 self
148 }
149
150 pub fn weights(mut self, weights: QualityWeights) -> Self {
152 self.config.weights = weights;
153 self
154 }
155
156 pub fn build(self) -> BootstrapCacheConfig {
158 self.config
159 }
160}
161
162fn default_cache_dir() -> PathBuf {
163 if let Some(cache_dir) = dirs::cache_dir() {
165 cache_dir.join("ant-quic")
166 } else if let Some(home) = dirs::home_dir() {
167 home.join(".cache").join("ant-quic")
168 } else {
169 PathBuf::from(".ant-quic-cache")
170 }
171}
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn test_default_config() {
179 let config = BootstrapCacheConfig::default();
180 assert_eq!(config.max_peers, 20_000);
181 assert!((config.epsilon - 0.1).abs() < f64::EPSILON);
182 assert_eq!(config.stale_threshold, Duration::from_secs(7 * 24 * 3600));
183 }
184
185 #[test]
186 fn test_builder() {
187 let config = BootstrapCacheConfig::builder()
188 .max_peers(10_000)
189 .epsilon(0.2)
190 .cache_dir("/tmp/test")
191 .build();
192
193 assert_eq!(config.max_peers, 10_000);
194 assert!((config.epsilon - 0.2).abs() < f64::EPSILON);
195 assert_eq!(config.cache_dir, PathBuf::from("/tmp/test"));
196 }
197
198 #[test]
199 fn test_epsilon_clamping() {
200 let config = BootstrapCacheConfig::builder().epsilon(1.5).build();
201 assert!((config.epsilon - 1.0).abs() < f64::EPSILON);
202
203 let config = BootstrapCacheConfig::builder().epsilon(-0.5).build();
204 assert!(config.epsilon.abs() < f64::EPSILON);
205 }
206}