//! 配置管理服务 //! 统一管理应用配置,支持配置验证和环境适配 use anyhow::{Result, anyhow}; use std::sync::Arc; use tokio::sync::RwLock; use tracing::{info, warn, error, debug}; use crate::config::{AppConfig, ComfyUISettings}; use crate::data::models::comfyui::{ComfyUIConfig, ValidationResult}; /// 环境类型 #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub enum Environment { /// 开发环境 Development, /// 测试环境 Testing, /// 生产环境 Production, } impl Environment { /// 从环境变量获取环境类型 pub fn from_env() -> Self { match std::env::var("MIXVIDEO_ENV").as_deref() { Ok("production") | Ok("prod") => Environment::Production, Ok("testing") | Ok("test") => Environment::Testing, _ => Environment::Development, } } /// 获取环境名称 pub fn name(&self) -> &'static str { match self { Environment::Development => "development", Environment::Testing => "testing", Environment::Production => "production", } } } /// 配置管理器 pub struct ConfigManager { /// 应用配置 app_config: Arc>, /// 当前环境 environment: Environment, /// 配置文件路径 config_path: Option, } impl ConfigManager { /// 创建新的配置管理器 pub fn new(app_config: AppConfig, config_path: Option) -> Self { let environment = Environment::from_env(); info!("配置管理器初始化,环境: {}", environment.name()); Self { app_config: Arc::new(RwLock::new(app_config)), environment, config_path, } } /// 获取当前环境 pub fn get_environment(&self) -> &Environment { &self.environment } /// 获取应用配置 pub async fn get_app_config(&self) -> AppConfig { self.app_config.read().await.clone() } /// 更新应用配置 pub async fn update_app_config(&self, config: AppConfig) -> Result<()> { // 验证配置 let validation = self.validate_app_config(&config).await?; if !validation.valid { return Err(anyhow!("配置验证失败: {:?}", validation.errors)); } // 更新配置 *self.app_config.write().await = config; // 保存到文件 self.save_config().await?; info!("应用配置已更新"); Ok(()) } /// 获取 ComfyUI 配置 pub async fn get_comfyui_config(&self) -> ComfyUIConfig { let app_config = self.app_config.read().await; let mut config = app_config.comfyui_settings.to_comfyui_config(); // 根据环境调整配置 self.apply_environment_config(&mut config); config } /// 更新 ComfyUI 配置 pub async fn update_comfyui_config(&self, config: ComfyUIConfig) -> Result<()> { // 验证配置 let validation = config.validate(); if !validation.valid { return Err(anyhow!("ComfyUI 配置验证失败: {:?}", validation.errors)); } // 更新应用配置中的 ComfyUI 设置 { let mut app_config = self.app_config.write().await; app_config.comfyui_settings.update_from_comfyui_config(&config); } // 保存到文件 self.save_config().await?; info!("ComfyUI 配置已更新"); Ok(()) } /// 获取 ComfyUI 设置 pub async fn get_comfyui_settings(&self) -> ComfyUISettings { let app_config = self.app_config.read().await; app_config.comfyui_settings.clone() } /// 更新 ComfyUI 设置 pub async fn update_comfyui_settings(&self, settings: ComfyUISettings) -> Result<()> { // 验证设置 let validation = settings.validate(); if !validation.valid { return Err(anyhow!("ComfyUI 设置验证失败: {:?}", validation.errors)); } // 更新配置 { let mut app_config = self.app_config.write().await; app_config.comfyui_settings = settings; } // 保存到文件 self.save_config().await?; info!("ComfyUI 设置已更新"); Ok(()) } /// 重置 ComfyUI 配置为默认值 pub async fn reset_comfyui_config(&self) -> Result<()> { let default_settings = ComfyUISettings::default(); self.update_comfyui_settings(default_settings).await } /// 验证应用配置 async fn validate_app_config(&self, config: &AppConfig) -> Result { use crate::data::models::comfyui::{ValidationResult, SDKValidationError as ValidationError}; let mut result = ValidationResult::success(); // 验证主题 if !["light", "dark", "auto"].contains(&config.theme.as_str()) { result.add_error(ValidationError::new("theme", "无效的主题设置")); } // 验证语言 if !["zh-CN", "en-US"].contains(&config.language.as_str()) { result.add_error(ValidationError::new("language", "无效的语言设置")); } // 验证窗口大小 if config.window_size.width <= 0.0 || config.window_size.height <= 0.0 { result.add_error(ValidationError::new("window_size", "窗口大小必须大于 0")); } // 验证 ComfyUI 设置 let comfyui_validation = config.comfyui_settings.validate(); for error in comfyui_validation.errors { result.add_error(error); } Ok(result) } /// 根据环境调整配置 fn apply_environment_config(&self, config: &mut ComfyUIConfig) { match self.environment { Environment::Development => { // 开发环境:启用详细日志,较短超时 config.timeout_seconds = std::cmp::min(config.timeout_seconds, 120); config.retry_attempts = std::cmp::min(config.retry_attempts, 2); debug!("应用开发环境配置"); } Environment::Testing => { // 测试环境:中等超时,适中重试 config.timeout_seconds = std::cmp::min(config.timeout_seconds, 180); config.retry_attempts = std::cmp::min(config.retry_attempts, 3); debug!("应用测试环境配置"); } Environment::Production => { // 生产环境:较长超时,更多重试 config.timeout_seconds = std::cmp::max(config.timeout_seconds, 300); config.retry_attempts = std::cmp::max(config.retry_attempts, 3); debug!("应用生产环境配置"); } } } /// 保存配置到文件 async fn save_config(&self) -> Result<()> { if let Some(config_path) = &self.config_path { let app_config = self.app_config.read().await; let config_json = serde_json::to_string_pretty(&*app_config)?; tokio::fs::write(config_path, config_json).await .map_err(|e| anyhow!("保存配置文件失败: {}", e))?; debug!("配置已保存到: {}", config_path); } Ok(()) } /// 从文件加载配置 pub async fn load_config(config_path: &str) -> Result { match tokio::fs::read_to_string(config_path).await { Ok(content) => { let config: AppConfig = serde_json::from_str(&content) .map_err(|e| anyhow!("解析配置文件失败: {}", e))?; info!("从文件加载配置: {}", config_path); Ok(config) } Err(_) => { warn!("配置文件不存在,使用默认配置: {}", config_path); Ok(AppConfig::default()) } } } /// 导出配置 pub async fn export_config(&self) -> Result { let app_config = self.app_config.read().await; serde_json::to_string_pretty(&*app_config) .map_err(|e| anyhow!("导出配置失败: {}", e)) } /// 导入配置 pub async fn import_config(&self, config_json: &str) -> Result<()> { let config: AppConfig = serde_json::from_str(config_json) .map_err(|e| anyhow!("解析配置失败: {}", e))?; self.update_app_config(config).await } /// 获取配置统计信息 pub async fn get_config_stats(&self) -> ConfigStats { let app_config = self.app_config.read().await; ConfigStats { environment: self.environment.clone(), config_path: self.config_path.clone(), comfyui_enabled: app_config.comfyui_settings.enabled, sdk_enabled: app_config.comfyui_settings.is_sdk_enabled(), recent_projects_count: app_config.recent_projects.len(), } } /// 检查配置健康状态 pub async fn health_check(&self) -> Result { let app_config = self.app_config.read().await; let validation = self.validate_app_config(&*app_config).await?; let status = if validation.valid { ConfigHealthStatus::Healthy } else { ConfigHealthStatus::Unhealthy(validation.errors) }; Ok(status) } } /// 配置统计信息 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct ConfigStats { pub environment: Environment, pub config_path: Option, pub comfyui_enabled: bool, pub sdk_enabled: bool, pub recent_projects_count: usize, } /// 配置健康状态 #[derive(Debug, Clone)] pub enum ConfigHealthStatus { /// 健康 Healthy, /// 不健康 Unhealthy(Vec), } impl std::fmt::Display for ConfigHealthStatus { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { ConfigHealthStatus::Healthy => write!(f, "健康"), ConfigHealthStatus::Unhealthy(errors) => { write!(f, "不健康 ({} 个错误)", errors.len()) } } } }