316 lines
10 KiB
Rust
316 lines
10 KiB
Rust
//! 配置管理服务
|
|
//! 统一管理应用配置,支持配置验证和环境适配
|
|
|
|
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<RwLock<AppConfig>>,
|
|
/// 当前环境
|
|
environment: Environment,
|
|
/// 配置文件路径
|
|
config_path: Option<String>,
|
|
}
|
|
|
|
impl ConfigManager {
|
|
/// 创建新的配置管理器
|
|
pub fn new(app_config: AppConfig, config_path: Option<String>) -> 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<ValidationResult> {
|
|
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<AppConfig> {
|
|
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<String> {
|
|
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<ConfigHealthStatus> {
|
|
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<String>,
|
|
pub comfyui_enabled: bool,
|
|
pub sdk_enabled: bool,
|
|
pub recent_projects_count: usize,
|
|
}
|
|
|
|
/// 配置健康状态
|
|
#[derive(Debug, Clone)]
|
|
pub enum ConfigHealthStatus {
|
|
/// 健康
|
|
Healthy,
|
|
/// 不健康
|
|
Unhealthy(Vec<crate::data::models::comfyui::ValidationError>),
|
|
}
|
|
|
|
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())
|
|
}
|
|
}
|
|
}
|
|
}
|