mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-27 08:14:33 +08:00
fix: prevent common config loss during proxy takeover and stabilize snippet lifecycle
- Make sync_current_provider_for_app takeover-aware: update restore backup instead of overwriting live config when proxy is active - Introduce explicit "cleared" flag for common config snippets to prevent auto-extraction from resurrecting user-cleared snippets - Reorder startup: extract snippets from clean live files before restoring proxy takeover state - Add one-time migration flag to skip legacy commonConfigEnabled migration on subsequent startups - Add regression tests for takeover backup preservation, explicit clear semantics, and migration flag roundtrip
This commit is contained in:
@@ -7,6 +7,12 @@ use crate::error::AppError;
|
||||
use rusqlite::params;
|
||||
|
||||
impl Database {
|
||||
const LEGACY_COMMON_CONFIG_MIGRATED_KEY: &'static str = "common_config_legacy_migrated_v1";
|
||||
|
||||
fn config_snippet_cleared_key(app_type: &str) -> String {
|
||||
format!("common_config_{app_type}_cleared")
|
||||
}
|
||||
|
||||
/// 获取设置值
|
||||
pub fn get_setting(&self, key: &str) -> Result<Option<String>, AppError> {
|
||||
let conn = lock_conn!(self.conn);
|
||||
@@ -45,6 +51,60 @@ impl Database {
|
||||
self.get_setting(&format!("common_config_{app_type}"))
|
||||
}
|
||||
|
||||
/// 检查通用配置片段是否被用户显式清空
|
||||
pub fn is_config_snippet_cleared(&self, app_type: &str) -> Result<bool, AppError> {
|
||||
Ok(self
|
||||
.get_setting(&Self::config_snippet_cleared_key(app_type))?
|
||||
.as_deref()
|
||||
== Some("true"))
|
||||
}
|
||||
|
||||
/// 设置通用配置片段是否被显式清空
|
||||
pub fn set_config_snippet_cleared(
|
||||
&self,
|
||||
app_type: &str,
|
||||
cleared: bool,
|
||||
) -> Result<(), AppError> {
|
||||
let key = Self::config_snippet_cleared_key(app_type);
|
||||
if cleared {
|
||||
self.set_setting(&key, "true")
|
||||
} else {
|
||||
let conn = lock_conn!(self.conn);
|
||||
conn.execute("DELETE FROM settings WHERE key = ?1", params![key])
|
||||
.map_err(|e| AppError::Database(e.to_string()))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// 当前是否允许从 live 配置自动抽取通用配置片段
|
||||
pub fn should_auto_extract_config_snippet(&self, app_type: &str) -> Result<bool, AppError> {
|
||||
Ok(self.get_config_snippet(app_type)?.is_none()
|
||||
&& !self.is_config_snippet_cleared(app_type)?)
|
||||
}
|
||||
|
||||
/// 检查历史通用配置迁移是否已经执行过
|
||||
pub fn is_legacy_common_config_migrated(&self) -> Result<bool, AppError> {
|
||||
Ok(self
|
||||
.get_setting(Self::LEGACY_COMMON_CONFIG_MIGRATED_KEY)?
|
||||
.as_deref()
|
||||
== Some("true"))
|
||||
}
|
||||
|
||||
/// 标记历史通用配置迁移已经执行完成
|
||||
pub fn set_legacy_common_config_migrated(&self, migrated: bool) -> Result<(), AppError> {
|
||||
if migrated {
|
||||
self.set_setting(Self::LEGACY_COMMON_CONFIG_MIGRATED_KEY, "true")
|
||||
} else {
|
||||
let conn = lock_conn!(self.conn);
|
||||
conn.execute(
|
||||
"DELETE FROM settings WHERE key = ?1",
|
||||
params![Self::LEGACY_COMMON_CONFIG_MIGRATED_KEY],
|
||||
)
|
||||
.map_err(|e| AppError::Database(e.to_string()))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// 设置通用配置片段
|
||||
pub fn set_config_snippet(
|
||||
&self,
|
||||
|
||||
Reference in New Issue
Block a user