This commit introduces fail-fast error handling for config loading failures, replacing the previous silent fallback to default config which could cause data loss (e.g., all user providers disappearing). Key changes: Backend (Rust): - Replace AppState::new() with AppState::try_new() to explicitly propagate errors - Remove Default trait to prevent accidental empty state creation - Add init_status module as global error cache (OnceLock + RwLock) - Implement dual-channel error notification: 1. Event emission (low-latency, may race with frontend subscription) 2. Command-based polling (reliable, guaranteed delivery) - Remove unconditional save on startup to prevent overwriting corrupted config Frontend (TypeScript): - Add event listener for "configLoadError" (fast path) - Add bootstrap-time polling via get_init_error command (reliable path) - Display detailed error dialog with recovery instructions - Prompt user to exit for manual repair Impact: - First-time users: No change (load() returns Ok(default) when file missing) - Corrupted config: Application shows error and exits gracefully - Prevents accidental config overwrite during initialization Fixes the only critical issue identified in previous code review (silent fallback causing data loss).
27 lines
666 B
Rust
27 lines
666 B
Rust
use crate::app_config::MultiAppConfig;
|
|
use crate::error::AppError;
|
|
use std::sync::RwLock;
|
|
|
|
/// 全局应用状态
|
|
pub struct AppState {
|
|
pub config: RwLock<MultiAppConfig>,
|
|
}
|
|
|
|
impl AppState {
|
|
/// 创建新的应用状态
|
|
/// 注意:仅在配置成功加载时返回;不会在失败时回退默认值。
|
|
pub fn try_new() -> Result<Self, AppError> {
|
|
let config = MultiAppConfig::load()?;
|
|
Ok(Self {
|
|
config: RwLock::new(config),
|
|
})
|
|
}
|
|
|
|
/// 保存配置到文件
|
|
pub fn save(&self) -> Result<(), AppError> {
|
|
let config = self.config.read().map_err(AppError::from)?;
|
|
|
|
config.save()
|
|
}
|
|
}
|