mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-24 04:22:58 +08:00
fix(db): pre-check too-new DB before schema writes; exit on close in recovery mode
Addresses review feedback on the too-new-DB recovery flow. - P1: stored_user_version_exceeds_supported() is now checked BEFORE Database::init(), so create_tables()'s DDL (incl. the unconditional DROP INDEX/DROP TABLE IF EXISTS failover_queue) never runs against a database whose user_version we cannot understand. The earlier post-init-failure recovery branch is removed; the pre-check is the single authoritative guard, so "don't write to a DB we can't read" now holds from the very first DB access. - P2: the window CloseRequested handler now detects recovery mode (init_error kind = db_version_too_new) and exits the app instead of honoring minimize_to_tray_on_close. Recovery mode returns before the tray is created, so hiding the window would leave the app running with no tray to bring it back; native-close now quits cleanly. Verified: cargo fmt --check clean; cross-model Rust review of both fixes (compile-correctness + no normal-startup/close regression).
This commit is contained in:
+39
-27
@@ -270,6 +270,16 @@ pub fn run() {
|
||||
// 拦截窗口关闭:根据设置决定是否最小化到托盘
|
||||
.on_window_event(|window, event| {
|
||||
if let tauri::WindowEvent::CloseRequested { api, .. } = event {
|
||||
// 数据库版本过新的恢复模式下没有托盘可唤回,关闭即退出,避免应用隐身后台
|
||||
let in_db_recovery = crate::init_status::get_init_error()
|
||||
.map(|p| p.kind.as_deref() == Some("db_version_too_new"))
|
||||
.unwrap_or(false);
|
||||
if in_db_recovery {
|
||||
api.prevent_close();
|
||||
window.app_handle().exit(0);
|
||||
return;
|
||||
}
|
||||
|
||||
let settings = crate::settings::get_settings();
|
||||
|
||||
if settings.minimize_to_tray_on_close {
|
||||
@@ -403,39 +413,41 @@ pub fn run() {
|
||||
// 说明:从 v3.8.* 升级的用户通常会走到这里的 SQLite schema 迁移,
|
||||
// 若迁移失败(数据库损坏/权限不足/user_version 过新等),需要给用户明确提示,
|
||||
// 否则表现可能只是“应用打不开/闪退”。
|
||||
//
|
||||
// 预检:数据库版本过新时,必须先于任何 schema 写操作(create_tables 内含
|
||||
// DROP/ALTER 等 DDL)进入恢复界面,避免旧应用对读不懂的更新版 DB 落写。
|
||||
match crate::database::Database::stored_user_version_exceeds_supported(&db_path) {
|
||||
Ok(Some(version)) => {
|
||||
log::warn!("数据库版本过新(v{version}),引导用户在应用内升级应用");
|
||||
crate::init_status::set_init_error(crate::init_status::InitErrorPayload {
|
||||
path: db_path.display().to_string(),
|
||||
error: format!(
|
||||
"数据库版本过新({version}),当前应用仅支持 {},请升级应用后再尝试。",
|
||||
crate::database::SCHEMA_VERSION
|
||||
),
|
||||
kind: Some("db_version_too_new".to_string()),
|
||||
db_version: Some(version),
|
||||
supported_version: Some(crate::database::SCHEMA_VERSION),
|
||||
});
|
||||
// 主窗口默认 visible:false,恢复界面必须强制显示
|
||||
if let Some(window) = app.get_webview_window("main") {
|
||||
let _ = window.show();
|
||||
let _ = window.set_focus();
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
Ok(None) => {}
|
||||
Err(e) => {
|
||||
log::warn!("预检数据库版本失败,继续正常初始化流程: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
let db = loop {
|
||||
match crate::database::Database::init() {
|
||||
Ok(db) => break Arc::new(db),
|
||||
Err(e) => {
|
||||
log::error!("Failed to init database: {e}");
|
||||
|
||||
// 数据库版本过新(应用过旧):无法向下迁移,反复重试也无效。
|
||||
// 记录可恢复错误并进入应用内「升级应用」恢复界面,而不是死循环弹窗。
|
||||
if let Ok(Some(version)) =
|
||||
crate::database::Database::stored_user_version_exceeds_supported(
|
||||
&db_path,
|
||||
)
|
||||
{
|
||||
log::warn!("数据库版本过新(v{version}),引导用户在应用内升级应用");
|
||||
crate::init_status::set_init_error(
|
||||
crate::init_status::InitErrorPayload {
|
||||
path: db_path.display().to_string(),
|
||||
error: e.to_string(),
|
||||
kind: Some("db_version_too_new".to_string()),
|
||||
db_version: Some(version),
|
||||
supported_version: Some(
|
||||
crate::database::SCHEMA_VERSION,
|
||||
),
|
||||
},
|
||||
);
|
||||
// 主窗口默认 visible:false,恢复界面必须强制显示
|
||||
if let Some(window) = app.get_webview_window("main") {
|
||||
let _ = window.show();
|
||||
let _ = window.set_focus();
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if !show_database_init_error_dialog(app.handle(), &db_path, &e.to_string())
|
||||
{
|
||||
log::info!("用户选择退出程序");
|
||||
|
||||
Reference in New Issue
Block a user