mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-09 11:52:08 +08:00
refactor(backend): declarative effects (#8128)
* refactor(core): type notice statuses behind the frozen wire contract * refactor(utils): unified retry and strategy-list helpers * refactor(feat): declarative effect registry for verge and clash patches * refactor(core): derive refresh announcements from transaction commit * refactor(core): fold tray, hotkey, autostart updates into effect ensures * refactor(utils): migrate remaining bounded retry loops * docs: add src-tauri architecture guardrails * refactor(core): coalesce burst refresh announcements * refactor(core): complete bounded service retry migration * ci(backend): add architecture ban gates * test(feat): freeze representative effect registry mappings * docs(backend): record dead wire contract entries * chore(core): document watcher exit conditions * fix(backend): preserve applied state across later failures * fix(config): retain runtime after an applied core replacement * refactor(backend): flatten refresh publication and retry policies * docs(backend): focus guardrails on architecture ownership * refactor(effects): use one execution order * fix(config): publish retained runtime and reconcile proxy settings
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use super::{CmdResult, CommandFailure, WithErrorCode as _, proxy_aware_coded_error, proxy_aware_error};
|
||||
use crate::core::notify::NoticeStatus;
|
||||
use crate::feat;
|
||||
use crate::utils::{dirs, yaml_emitter};
|
||||
use crate::{
|
||||
@@ -56,14 +57,14 @@ pub async fn change_clash_core(clash_core: String) -> CmdResult<Option<CommandFa
|
||||
|
||||
match CoreManager::global().restart_core().await {
|
||||
Ok(_) => {
|
||||
handle::Handle::notice_message("config_core::change_success", clash_core);
|
||||
handle::Handle::notice(NoticeStatus::ConfigCoreChangeSuccess, clash_core.as_str());
|
||||
handle::Handle::refresh_clash();
|
||||
Ok(None)
|
||||
}
|
||||
Err(err) => {
|
||||
let failed = err.context("core changed but failed to restart");
|
||||
let error_msg: String = format!("{failed:#}").into();
|
||||
handle::Handle::notice_message("config_core::change_error", error_msg.clone());
|
||||
handle::Handle::notice(NoticeStatus::ConfigCoreChangeError, error_msg.as_str());
|
||||
logging!(error, Type::Core, "core changed but failed to restart: {error_msg}");
|
||||
Ok(Some(proxy_aware_coded_error(&failed, "CORE_CHANGE_FAILED")))
|
||||
}
|
||||
@@ -72,7 +73,7 @@ pub async fn change_clash_core(clash_core: String) -> CmdResult<Option<CommandFa
|
||||
Err(err) => {
|
||||
let error_msg: String = format!("{err:#}").into();
|
||||
logging!(error, Type::Core, "failed to change core: {error_msg}");
|
||||
handle::Handle::notice_message("config_core::change_error", error_msg);
|
||||
handle::Handle::notice(NoticeStatus::ConfigCoreChangeError, error_msg.as_str());
|
||||
Ok(Some(proxy_aware_coded_error(&err, "CORE_CHANGE_FAILED")))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::module::lightweight;
|
||||
use crate::core::lightweight;
|
||||
|
||||
use super::CmdResult;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use super::{CmdResult, StringifyErr as _, WithErrorCode as _, coded_error};
|
||||
use crate::cmd::validate::{ValidationNoticeTarget, handle_validation_notice};
|
||||
use crate::config::profiles;
|
||||
use crate::core::notify::NoticeStatus;
|
||||
use crate::utils::window_manager::WindowManager;
|
||||
use crate::{
|
||||
config::{
|
||||
@@ -282,7 +283,7 @@ async fn handle_update_error<E: std::fmt::Display>(
|
||||
logging!(warn, Type::Cmd, "更新过程发生错误: {}", e,);
|
||||
discard_and_restore(current_profile).await?;
|
||||
let message: String = e.to_string().into();
|
||||
handle::Handle::notice_message("config_validate::boot_error", message.clone());
|
||||
handle::Handle::notice(NoticeStatus::ConfigValidateBootError, message.as_str());
|
||||
Ok(ValidationOutcome::invalid_from_message(message))
|
||||
}
|
||||
|
||||
|
||||
@@ -139,6 +139,7 @@ pub async fn sync_tray_proxy_selection() -> CmdResult<()> {
|
||||
}
|
||||
|
||||
async fn run_tray_sync_loop() {
|
||||
// Permanent watcher: keeps syncing until a pass finds no pending sync request.
|
||||
loop {
|
||||
match Tray::global().update_menu().await {
|
||||
Ok(_) => {
|
||||
|
||||
@@ -3,11 +3,11 @@ use crate::{
|
||||
cmd::StringifyErr as _,
|
||||
cmd::validate::{ValidationNoticeTarget, handle_validation_notice},
|
||||
config::{Config, IProfiles, PrfItem},
|
||||
core::auto_backup::{AutoBackupManager, AutoBackupTrigger},
|
||||
core::{
|
||||
CoreManager, handle,
|
||||
validate::{CoreConfigValidator, ValidationOutcome},
|
||||
},
|
||||
module::auto_backup::{AutoBackupManager, AutoBackupTrigger},
|
||||
utils::dirs,
|
||||
};
|
||||
use clash_verge_logging::{Type, logging, logging_error};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::core::notify::NoticeStatus;
|
||||
use crate::core::{
|
||||
handle,
|
||||
validate::{ValidationErrorKind, ValidationOutcome},
|
||||
@@ -11,27 +12,27 @@ pub enum ValidationNoticeTarget {
|
||||
Script,
|
||||
}
|
||||
|
||||
const fn notice_key(kind: ValidationErrorKind, target: ValidationNoticeTarget) -> &'static str {
|
||||
const fn notice_key(kind: ValidationErrorKind, target: ValidationNoticeTarget) -> NoticeStatus {
|
||||
match kind {
|
||||
ValidationErrorKind::FileMissing => "config_validate::file_not_found",
|
||||
ValidationErrorKind::FileMissing => NoticeStatus::ConfigValidateFileNotFound,
|
||||
ValidationErrorKind::FileRead => match target {
|
||||
ValidationNoticeTarget::Script => "config_validate::script_error",
|
||||
_ => "config_validate::yaml_read_error",
|
||||
ValidationNoticeTarget::Script => NoticeStatus::ConfigValidateScriptError,
|
||||
_ => NoticeStatus::ConfigValidateYamlReadError,
|
||||
},
|
||||
ValidationErrorKind::YamlSyntax => match target {
|
||||
ValidationNoticeTarget::Merge => "config_validate::merge_syntax_error",
|
||||
ValidationNoticeTarget::Script => "config_validate::script_error",
|
||||
ValidationNoticeTarget::Runtime => "config_validate::yaml_syntax_error",
|
||||
ValidationNoticeTarget::Merge => NoticeStatus::ConfigValidateMergeSyntaxError,
|
||||
ValidationNoticeTarget::Script => NoticeStatus::ConfigValidateScriptError,
|
||||
ValidationNoticeTarget::Runtime => NoticeStatus::ConfigValidateYamlSyntaxError,
|
||||
},
|
||||
ValidationErrorKind::YamlMapping => match target {
|
||||
ValidationNoticeTarget::Merge => "config_validate::merge_mapping_error",
|
||||
ValidationNoticeTarget::Script => "config_validate::script_error",
|
||||
ValidationNoticeTarget::Runtime => "config_validate::yaml_mapping_error",
|
||||
ValidationNoticeTarget::Merge => NoticeStatus::ConfigValidateMergeMappingError,
|
||||
ValidationNoticeTarget::Script => NoticeStatus::ConfigValidateScriptError,
|
||||
ValidationNoticeTarget::Runtime => NoticeStatus::ConfigValidateYamlMappingError,
|
||||
},
|
||||
ValidationErrorKind::ScriptSyntax => "config_validate::script_syntax_error",
|
||||
ValidationErrorKind::ScriptMissingMain => "config_validate::script_missing_main",
|
||||
ValidationErrorKind::ProcessTerminated => "config_validate::process_terminated",
|
||||
ValidationErrorKind::CoreRejected | ValidationErrorKind::Timeout => "config_validate::error",
|
||||
ValidationErrorKind::ScriptSyntax => NoticeStatus::ConfigValidateScriptSyntaxError,
|
||||
ValidationErrorKind::ScriptMissingMain => NoticeStatus::ConfigValidateScriptMissingMain,
|
||||
ValidationErrorKind::ProcessTerminated => NoticeStatus::ConfigValidateProcessTerminated,
|
||||
ValidationErrorKind::CoreRejected | ValidationErrorKind::Timeout => NoticeStatus::ConfigValidateError,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,12 +41,12 @@ pub fn handle_validation_notice(outcome: &ValidationOutcome, target: ValidationN
|
||||
ValidationOutcome::Invalid { kind, message } => {
|
||||
let status = notice_key(*kind, target);
|
||||
logging!(warn, Type::Config, "{} 验证失败: {}", file_type, message);
|
||||
handle::Handle::notice_message(status, message.to_owned());
|
||||
handle::Handle::notice(status, message.as_str());
|
||||
}
|
||||
ValidationOutcome::Busy | ValidationOutcome::Skipped { .. } => {
|
||||
let message = outcome.to_string();
|
||||
logging!(warn, Type::Config, "{} 验证跳过: {}", file_type, message);
|
||||
handle::Handle::notice_message("config_validate::error", message);
|
||||
handle::Handle::notice(NoticeStatus::ConfigValidateError, message.as_str());
|
||||
}
|
||||
ValidationOutcome::Valid => {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user