fix: prevent silent config fallback and data loss on startup

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).
This commit is contained in:
Jason
2025-11-03 22:33:10 +08:00
parent 36fd61b2a2
commit 4afa68eac6
5 changed files with 154 additions and 29 deletions

View File

@@ -2,6 +2,7 @@
use tauri::AppHandle;
use tauri_plugin_opener::OpenerExt;
use crate::init_status::{get_init_error, InitErrorPayload};
/// 打开外部链接
#[tauri::command]
@@ -43,3 +44,10 @@ pub async fn is_portable_mode() -> Result<bool, String> {
Ok(false)
}
}
/// 获取应用启动阶段的初始化错误(若有)。
/// 用于前端在早期主动拉取,避免事件订阅竞态导致的提示缺失。
#[tauri::command]
pub async fn get_init_error() -> Result<Option<InitErrorPayload>, String> {
Ok(get_init_error())
}