1use serde::{Deserialize, Serialize};
6use std::env;
7use std::path::Path;
8use thiserror::Error;
9use toml;
10
11#[derive(Debug, Error)]
13pub enum ConfigError {
14 #[error("Failed to read configuration file: {0}")]
15 ReadError(#[from] std::io::Error),
16
17 #[error("Failed to parse configuration: {0}")]
18 ParseError(#[from] toml::de::Error),
19
20 #[error("Invalid configuration: {0}")]
21 InvalidConfig(String),
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct OptimizationConfig {
27 pub global: GlobalConfig,
29 pub network: NetworkOptimizations,
31 pub dag: DagOptimizations,
33 pub swarm: SwarmOptimizations,
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct GlobalConfig {
40 pub enable_optimizations: bool,
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct NetworkOptimizations {
47 pub message_chunking: MessageChunkingConfig,
49 pub adaptive_batching: AdaptiveBatchingConfig,
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct MessageChunkingConfig {
56 pub enabled: bool,
57 pub max_chunk_size: usize,
58 pub max_chunks: usize,
59 pub chunk_timeout: u64,
60 pub enable_compression: bool,
61 pub compression_threshold: usize,
62 pub compression_level: i32,
63 pub cache_size: usize,
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct AdaptiveBatchingConfig {
69 pub enabled: bool,
70 pub max_batch_size: usize,
71 pub batch_timeout: u64,
72 pub algorithm: String,
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
77pub struct DagOptimizations {
78 pub validation_cache: ValidationCacheConfig,
80 pub traversal_index: TraversalIndexConfig,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct ValidationCacheConfig {
87 pub enabled: bool,
88 pub max_entries: usize,
89 pub ttl: u64,
90 pub enable_batch_validation: bool,
91 pub batch_size: usize,
92 pub cache_parent_validation: bool,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct TraversalIndexConfig {
98 pub enabled: bool,
99 pub common_ancestor_cache_size: usize,
100 pub path_cache_size: usize,
101 pub enable_graph_algorithms: bool,
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct SwarmOptimizations {
107 pub async_coordination: AsyncCoordinationConfig,
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct AsyncCoordinationConfig {
114 pub enabled: bool,
115 pub max_agents_per_coordinator: usize,
116 pub max_hierarchy_depth: usize,
117 pub communication_timeout: u64,
118 pub distribution_strategy: String,
119 pub enable_work_stealing: bool,
120 pub heartbeat_interval: u64,
121}
122
123impl OptimizationConfig {
124 pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, ConfigError> {
126 let contents = std::fs::read_to_string(path)?;
127 let mut config: Self = toml::from_str(&contents)?;
128
129 config.apply_env_overrides();
131
132 Ok(config)
133 }
134
135 pub fn default() -> Self {
137 Self {
138 global: GlobalConfig {
139 enable_optimizations: true,
140 },
141 network: NetworkOptimizations {
142 message_chunking: MessageChunkingConfig {
143 enabled: true,
144 max_chunk_size: 65536,
145 max_chunks: 10000,
146 chunk_timeout: 30,
147 enable_compression: true,
148 compression_threshold: 1024,
149 compression_level: 3,
150 cache_size: 1000,
151 },
152 adaptive_batching: AdaptiveBatchingConfig {
153 enabled: true,
154 max_batch_size: 100,
155 batch_timeout: 50,
156 algorithm: "exponential_backoff".to_string(),
157 },
158 },
159 dag: DagOptimizations {
160 validation_cache: ValidationCacheConfig {
161 enabled: true,
162 max_entries: 100000,
163 ttl: 3600,
164 enable_batch_validation: true,
165 batch_size: 100,
166 cache_parent_validation: true,
167 },
168 traversal_index: TraversalIndexConfig {
169 enabled: true,
170 common_ancestor_cache_size: 10000,
171 path_cache_size: 1000,
172 enable_graph_algorithms: true,
173 },
174 },
175 swarm: SwarmOptimizations {
176 async_coordination: AsyncCoordinationConfig {
177 enabled: true,
178 max_agents_per_coordinator: 10,
179 max_hierarchy_depth: 3,
180 communication_timeout: 5,
181 distribution_strategy: "load_balanced".to_string(),
182 enable_work_stealing: true,
183 heartbeat_interval: 10,
184 },
185 },
186 }
187 }
188
189 fn apply_env_overrides(&mut self) {
191 if let Ok(val) = env::var("QUDAG_ENABLE_OPTIMIZATIONS") {
193 self.global.enable_optimizations = val.parse().unwrap_or(true);
194 }
195
196 if let Ok(val) = env::var("QUDAG_NETWORK_MESSAGE_CHUNKING_ENABLED") {
198 self.network.message_chunking.enabled = val.parse().unwrap_or(true);
199 }
200 if let Ok(val) = env::var("QUDAG_NETWORK_MESSAGE_CHUNKING_MAX_CHUNK_SIZE") {
201 if let Ok(size) = val.parse() {
202 self.network.message_chunking.max_chunk_size = size;
203 }
204 }
205
206 if let Ok(val) = env::var("QUDAG_DAG_VALIDATION_CACHE_ENABLED") {
208 self.dag.validation_cache.enabled = val.parse().unwrap_or(true);
209 }
210 if let Ok(val) = env::var("QUDAG_DAG_VALIDATION_CACHE_MAX_ENTRIES") {
211 if let Ok(entries) = val.parse() {
212 self.dag.validation_cache.max_entries = entries;
213 }
214 }
215
216 if let Ok(val) = env::var("QUDAG_SWARM_ASYNC_COORDINATION_ENABLED") {
218 self.swarm.async_coordination.enabled = val.parse().unwrap_or(true);
219 }
220 if let Ok(val) = env::var("QUDAG_SWARM_ASYNC_COORDINATION_MAX_AGENTS") {
221 if let Ok(agents) = val.parse() {
222 self.swarm.async_coordination.max_agents_per_coordinator = agents;
223 }
224 }
225 }
226
227 pub fn is_enabled(&self, optimization: &str) -> bool {
229 if !self.global.enable_optimizations {
230 return false;
231 }
232
233 match optimization {
234 "message_chunking" => self.network.message_chunking.enabled,
235 "adaptive_batching" => self.network.adaptive_batching.enabled,
236 "validation_cache" => self.dag.validation_cache.enabled,
237 "traversal_index" => self.dag.traversal_index.enabled,
238 "async_coordination" => self.swarm.async_coordination.enabled,
239 _ => false,
240 }
241 }
242}
243
244#[cfg(test)]
245mod tests {
246 use super::*;
247
248 #[test]
249 fn test_default_config() {
250 let config = OptimizationConfig::default();
251 assert!(config.global.enable_optimizations);
252 assert!(config.network.message_chunking.enabled);
253 assert_eq!(config.network.message_chunking.max_chunk_size, 65536);
254 }
255
256 #[test]
257 fn test_is_enabled() {
258 let config = OptimizationConfig::default();
259 assert!(config.is_enabled("message_chunking"));
260 assert!(config.is_enabled("validation_cache"));
261 assert!(!config.is_enabled("unknown_optimization"));
262 }
263}