use serde::{Deserialize, Serialize};
use std::env;
use std::path::Path;
use thiserror::Error;
use toml;
#[derive(Debug, Error)]
pub enum ConfigError {
#[error("Failed to read configuration file: {0}")]
ReadError(#[from] std::io::Error),
#[error("Failed to parse configuration: {0}")]
ParseError(#[from] toml::de::Error),
#[error("Invalid configuration: {0}")]
InvalidConfig(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OptimizationConfig {
pub global: GlobalConfig,
pub network: NetworkOptimizations,
pub dag: DagOptimizations,
pub swarm: SwarmOptimizations,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GlobalConfig {
pub enable_optimizations: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkOptimizations {
pub message_chunking: MessageChunkingConfig,
pub adaptive_batching: AdaptiveBatchingConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MessageChunkingConfig {
pub enabled: bool,
pub max_chunk_size: usize,
pub max_chunks: usize,
pub chunk_timeout: u64,
pub enable_compression: bool,
pub compression_threshold: usize,
pub compression_level: i32,
pub cache_size: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdaptiveBatchingConfig {
pub enabled: bool,
pub max_batch_size: usize,
pub batch_timeout: u64,
pub algorithm: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DagOptimizations {
pub validation_cache: ValidationCacheConfig,
pub traversal_index: TraversalIndexConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationCacheConfig {
pub enabled: bool,
pub max_entries: usize,
pub ttl: u64,
pub enable_batch_validation: bool,
pub batch_size: usize,
pub cache_parent_validation: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TraversalIndexConfig {
pub enabled: bool,
pub common_ancestor_cache_size: usize,
pub path_cache_size: usize,
pub enable_graph_algorithms: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SwarmOptimizations {
pub async_coordination: AsyncCoordinationConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AsyncCoordinationConfig {
pub enabled: bool,
pub max_agents_per_coordinator: usize,
pub max_hierarchy_depth: usize,
pub communication_timeout: u64,
pub distribution_strategy: String,
pub enable_work_stealing: bool,
pub heartbeat_interval: u64,
}
impl OptimizationConfig {
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, ConfigError> {
let contents = std::fs::read_to_string(path)?;
let mut config: Self = toml::from_str(&contents)?;
config.apply_env_overrides();
Ok(config)
}
pub fn default() -> Self {
Self {
global: GlobalConfig {
enable_optimizations: true,
},
network: NetworkOptimizations {
message_chunking: MessageChunkingConfig {
enabled: true,
max_chunk_size: 65536,
max_chunks: 10000,
chunk_timeout: 30,
enable_compression: true,
compression_threshold: 1024,
compression_level: 3,
cache_size: 1000,
},
adaptive_batching: AdaptiveBatchingConfig {
enabled: true,
max_batch_size: 100,
batch_timeout: 50,
algorithm: "exponential_backoff".to_string(),
},
},
dag: DagOptimizations {
validation_cache: ValidationCacheConfig {
enabled: true,
max_entries: 100000,
ttl: 3600,
enable_batch_validation: true,
batch_size: 100,
cache_parent_validation: true,
},
traversal_index: TraversalIndexConfig {
enabled: true,
common_ancestor_cache_size: 10000,
path_cache_size: 1000,
enable_graph_algorithms: true,
},
},
swarm: SwarmOptimizations {
async_coordination: AsyncCoordinationConfig {
enabled: true,
max_agents_per_coordinator: 10,
max_hierarchy_depth: 3,
communication_timeout: 5,
distribution_strategy: "load_balanced".to_string(),
enable_work_stealing: true,
heartbeat_interval: 10,
},
},
}
}
fn apply_env_overrides(&mut self) {
if let Ok(val) = env::var("QUDAG_ENABLE_OPTIMIZATIONS") {
self.global.enable_optimizations = val.parse().unwrap_or(true);
}
if let Ok(val) = env::var("QUDAG_NETWORK_MESSAGE_CHUNKING_ENABLED") {
self.network.message_chunking.enabled = val.parse().unwrap_or(true);
}
if let Ok(val) = env::var("QUDAG_NETWORK_MESSAGE_CHUNKING_MAX_CHUNK_SIZE") {
if let Ok(size) = val.parse() {
self.network.message_chunking.max_chunk_size = size;
}
}
if let Ok(val) = env::var("QUDAG_DAG_VALIDATION_CACHE_ENABLED") {
self.dag.validation_cache.enabled = val.parse().unwrap_or(true);
}
if let Ok(val) = env::var("QUDAG_DAG_VALIDATION_CACHE_MAX_ENTRIES") {
if let Ok(entries) = val.parse() {
self.dag.validation_cache.max_entries = entries;
}
}
if let Ok(val) = env::var("QUDAG_SWARM_ASYNC_COORDINATION_ENABLED") {
self.swarm.async_coordination.enabled = val.parse().unwrap_or(true);
}
if let Ok(val) = env::var("QUDAG_SWARM_ASYNC_COORDINATION_MAX_AGENTS") {
if let Ok(agents) = val.parse() {
self.swarm.async_coordination.max_agents_per_coordinator = agents;
}
}
}
pub fn is_enabled(&self, optimization: &str) -> bool {
if !self.global.enable_optimizations {
return false;
}
match optimization {
"message_chunking" => self.network.message_chunking.enabled,
"adaptive_batching" => self.network.adaptive_batching.enabled,
"validation_cache" => self.dag.validation_cache.enabled,
"traversal_index" => self.dag.traversal_index.enabled,
"async_coordination" => self.swarm.async_coordination.enabled,
_ => false,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = OptimizationConfig::default();
assert!(config.global.enable_optimizations);
assert!(config.network.message_chunking.enabled);
assert_eq!(config.network.message_chunking.max_chunk_size, 65536);
}
#[test]
fn test_is_enabled() {
let config = OptimizationConfig::default();
assert!(config.is_enabled("message_chunking"));
assert!(config.is_enabled("validation_cache"));
assert!(!config.is_enabled("unknown_optimization"));
}
}