mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-29 00:35:38 +08:00
perf: spawn clean task (#5595)
* perf: spawn task * perf: spawn task to save draft date * perf: store proxy client * chore: update * perf: reduce handle quit on macOS * chore: clippy * docs: update Changelog.md * chore: update
This commit is contained in:
@@ -9,6 +9,7 @@ use crate::{
|
||||
validate::CoreConfigValidator,
|
||||
},
|
||||
enhance,
|
||||
process::AsyncHandler,
|
||||
utils::{dirs, help},
|
||||
};
|
||||
use anyhow::{Result, anyhow};
|
||||
@@ -213,17 +214,27 @@ impl Config {
|
||||
// 升级草稿为正式数据,并写入文件。避免用户行为丢失。
|
||||
// 仅在应用退出、重启、关机监听事件启用
|
||||
pub async fn apply_all_and_save_file() {
|
||||
let clash = Self::clash().await;
|
||||
clash.apply();
|
||||
logging_error!(Type::Config, clash.data_arc().save_config().await);
|
||||
logging!(info, Type::Config, "save all draft data");
|
||||
let save_clash_task = AsyncHandler::spawn(|| async {
|
||||
let clash = Self::clash().await;
|
||||
clash.apply();
|
||||
logging_error!(Type::Config, clash.data_arc().save_config().await);
|
||||
});
|
||||
|
||||
let verge = Self::verge().await;
|
||||
verge.apply();
|
||||
logging_error!(Type::Config, verge.data_arc().save_file().await);
|
||||
let save_verge_task = AsyncHandler::spawn(|| async {
|
||||
let verge = Self::verge().await;
|
||||
verge.apply();
|
||||
logging_error!(Type::Config, verge.data_arc().save_file().await);
|
||||
});
|
||||
|
||||
let profiles = Self::profiles().await;
|
||||
profiles.apply();
|
||||
logging_error!(Type::Config, profiles.data_arc().save_file().await);
|
||||
let save_profiles_task = AsyncHandler::spawn(|| async {
|
||||
let profiles = Self::profiles().await;
|
||||
profiles.apply();
|
||||
logging_error!(Type::Config, profiles.data_arc().save_file().await);
|
||||
});
|
||||
|
||||
let _ = tokio::join!(save_clash_task, save_verge_task, save_profiles_task);
|
||||
logging!(info, Type::Config, "save all draft data finished");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ use crate::{
|
||||
};
|
||||
use anyhow::Result;
|
||||
use clash_verge_logging::{Type, logging, logging_error};
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
use parking_lot::Mutex;
|
||||
use parking_lot::RwLock;
|
||||
use scopeguard::defer;
|
||||
use smartstring::alias::String;
|
||||
@@ -23,6 +25,10 @@ use tauri_plugin_autostart::ManagerExt as _;
|
||||
pub struct Sysopt {
|
||||
update_sysproxy: AtomicBool,
|
||||
reset_sysproxy: AtomicBool,
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
sysproxy: Arc<Mutex<Sysproxy>>,
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
autoproxy: Arc<Mutex<Autoproxy>>,
|
||||
guard: Arc<RwLock<GuardMonitor>>,
|
||||
}
|
||||
|
||||
@@ -31,6 +37,10 @@ impl Default for Sysopt {
|
||||
Self {
|
||||
update_sysproxy: AtomicBool::new(false),
|
||||
reset_sysproxy: AtomicBool::new(false),
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
sysproxy: Arc::new(Mutex::new(Sysproxy::default())),
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
autoproxy: Arc::new(Mutex::new(Autoproxy::default())),
|
||||
guard: Arc::new(RwLock::new(GuardMonitor::new(
|
||||
GuardType::None,
|
||||
Duration::from_secs(30),
|
||||
@@ -185,23 +195,25 @@ impl Sysopt {
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
let mut sys = Sysproxy {
|
||||
enable: false,
|
||||
host: proxy_host.clone().into(),
|
||||
port,
|
||||
bypass: get_bypass().await.into(),
|
||||
};
|
||||
let mut auto = Autoproxy {
|
||||
enable: false,
|
||||
url: format!("http://{proxy_host}:{pac_port}/commands/pac"),
|
||||
};
|
||||
// 先 await, 避免持有锁导致的 Send 问题
|
||||
let bypass = get_bypass().await;
|
||||
|
||||
let mut sys = self.sysproxy.lock();
|
||||
sys.enable = false;
|
||||
sys.host = proxy_host.clone().into();
|
||||
sys.port = port;
|
||||
sys.bypass = bypass.into();
|
||||
|
||||
let mut auto = self.autoproxy.lock();
|
||||
auto.enable = false;
|
||||
auto.url = format!("http://{proxy_host}:{pac_port}/commands/pac");
|
||||
|
||||
if !sys_enable {
|
||||
sys.set_system_proxy()?;
|
||||
auto.set_auto_proxy()?;
|
||||
self.access_guard()
|
||||
.write()
|
||||
.set_guard_type(GuardType::Sysproxy(sys));
|
||||
.set_guard_type(GuardType::Sysproxy(sys.clone()));
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -212,7 +224,7 @@ impl Sysopt {
|
||||
auto.set_auto_proxy()?;
|
||||
self.access_guard()
|
||||
.write()
|
||||
.set_guard_type(GuardType::Autoproxy(auto));
|
||||
.set_guard_type(GuardType::Autoproxy(auto.clone()));
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -221,9 +233,11 @@ impl Sysopt {
|
||||
sys.enable = true;
|
||||
auto.set_auto_proxy()?;
|
||||
sys.set_system_proxy()?;
|
||||
drop(auto);
|
||||
self.access_guard()
|
||||
.write()
|
||||
.set_guard_type(GuardType::Sysproxy(sys));
|
||||
.set_guard_type(GuardType::Sysproxy(sys.clone()));
|
||||
drop(sys);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@@ -282,32 +296,13 @@ impl Sysopt {
|
||||
//直接关闭所有代理
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
{
|
||||
let mut sysproxy: Sysproxy = match Sysproxy::get_system_proxy() {
|
||||
Ok(sp) => sp,
|
||||
Err(e) => {
|
||||
logging!(
|
||||
warn,
|
||||
Type::Core,
|
||||
"Warning: 重置代理时获取系统代理配置失败: {e}, 使用默认配置"
|
||||
);
|
||||
Sysproxy::default()
|
||||
}
|
||||
};
|
||||
let mut autoproxy = match Autoproxy::get_auto_proxy() {
|
||||
Ok(ap) => ap,
|
||||
Err(e) => {
|
||||
logging!(
|
||||
warn,
|
||||
Type::Core,
|
||||
"Warning: 重置代理时获取自动代理配置失败: {e}, 使用默认配置"
|
||||
);
|
||||
Autoproxy::default()
|
||||
}
|
||||
};
|
||||
let mut sysproxy = self.sysproxy.lock();
|
||||
sysproxy.enable = false;
|
||||
sysproxy.set_system_proxy()?;
|
||||
drop(sysproxy);
|
||||
let mut autoproxy = self.autoproxy.lock();
|
||||
autoproxy.enable = false;
|
||||
autoproxy.set_auto_proxy()?;
|
||||
sysproxy.set_system_proxy()?;
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
|
||||
@@ -26,12 +26,12 @@ pub async fn restart_clash_core() {
|
||||
/// Restart the application
|
||||
pub async fn restart_app() {
|
||||
logging!(debug, Type::System, "启动重启应用流程");
|
||||
utils::server::shutdown_embedded_server();
|
||||
Config::apply_all_and_save_file().await;
|
||||
|
||||
// 设置退出标志
|
||||
handle::Handle::global().set_is_exiting();
|
||||
|
||||
utils::server::shutdown_embedded_server();
|
||||
Config::apply_all_and_save_file().await;
|
||||
|
||||
logging!(info, Type::System, "开始异步清理资源");
|
||||
let cleanup_result = clean_async().await;
|
||||
|
||||
|
||||
@@ -20,12 +20,12 @@ async fn open_or_close_dashboard_internal() {
|
||||
|
||||
pub async fn quit() {
|
||||
logging!(debug, Type::System, "启动退出流程");
|
||||
utils::server::shutdown_embedded_server();
|
||||
Config::apply_all_and_save_file().await;
|
||||
|
||||
// 设置退出标志
|
||||
handle::Handle::global().set_is_exiting();
|
||||
|
||||
utils::server::shutdown_embedded_server();
|
||||
Config::apply_all_and_save_file().await;
|
||||
|
||||
logging!(info, Type::System, "开始异步清理资源");
|
||||
let cleanup_result = clean_async().await;
|
||||
|
||||
@@ -43,51 +43,8 @@ pub async fn quit() {
|
||||
pub async fn clean_async() -> bool {
|
||||
logging!(info, Type::System, "开始执行异步清理操作...");
|
||||
|
||||
// 1. 处理TUN模式
|
||||
let tun_task = async {
|
||||
let tun_enabled = Config::verge()
|
||||
.await
|
||||
.data_arc()
|
||||
.enable_tun_mode
|
||||
.unwrap_or(false);
|
||||
|
||||
if !tun_enabled {
|
||||
return true;
|
||||
}
|
||||
|
||||
let disable_tun = serde_json::json!({ "tun": { "enable": false } });
|
||||
|
||||
logging!(info, Type::System, "send disable tun request to mihomo");
|
||||
match timeout(
|
||||
Duration::from_millis(1000),
|
||||
handle::Handle::mihomo()
|
||||
.await
|
||||
.patch_base_config(&disable_tun),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(Ok(_)) => {
|
||||
logging!(info, Type::Window, "TUN模式已禁用");
|
||||
true
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
logging!(warn, Type::Window, "Warning: 禁用TUN模式失败: {e}");
|
||||
// 超时不阻塞退出
|
||||
true
|
||||
}
|
||||
Err(_) => {
|
||||
logging!(
|
||||
warn,
|
||||
Type::Window,
|
||||
"Warning: 禁用TUN模式超时(可能系统正在关机),继续退出流程"
|
||||
);
|
||||
true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 2. 系统代理重置
|
||||
let proxy_task = async {
|
||||
// 重置系统代理
|
||||
let proxy_task = tokio::task::spawn(async {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
use sysproxy::{Autoproxy, Sysproxy};
|
||||
@@ -203,10 +160,44 @@ pub async fn clean_async() -> bool {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// 关闭 Tun 模式 + 停止核心服务
|
||||
let core_task = tokio::task::spawn(async {
|
||||
logging!(info, Type::System, "disable tun");
|
||||
let tun_enabled = Config::verge()
|
||||
.await
|
||||
.data_arc()
|
||||
.enable_tun_mode
|
||||
.unwrap_or(false);
|
||||
if tun_enabled {
|
||||
let disable_tun = serde_json::json!({ "tun": { "enable": false } });
|
||||
|
||||
logging!(info, Type::System, "send disable tun request to mihomo");
|
||||
match timeout(
|
||||
Duration::from_millis(1000),
|
||||
handle::Handle::mihomo()
|
||||
.await
|
||||
.patch_base_config(&disable_tun),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(Ok(_)) => {
|
||||
logging!(info, Type::Window, "TUN模式已禁用");
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
logging!(warn, Type::Window, "Warning: 禁用TUN模式失败: {e}");
|
||||
}
|
||||
Err(_) => {
|
||||
logging!(
|
||||
warn,
|
||||
Type::Window,
|
||||
"Warning: 禁用TUN模式超时(可能系统正在关机),继续退出流程"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 核心服务停止
|
||||
let core_task = async {
|
||||
#[cfg(target_os = "windows")]
|
||||
let stop_timeout = Duration::from_secs(2);
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
@@ -227,11 +218,11 @@ pub async fn clean_async() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// 4. DNS恢复(仅macOS)
|
||||
#[cfg(target_os = "macos")]
|
||||
let dns_task = async {
|
||||
// DNS恢复(仅macOS)
|
||||
let dns_task = tokio::task::spawn(async {
|
||||
#[cfg(target_os = "macos")]
|
||||
match timeout(
|
||||
Duration::from_millis(1000),
|
||||
crate::utils::resolve::dns::restore_public_dns(),
|
||||
@@ -247,22 +238,23 @@ pub async fn clean_async() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
};
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
true
|
||||
});
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let dns_task = async { true };
|
||||
|
||||
let tun_success = tun_task.await;
|
||||
// 并行执行清理任务
|
||||
let (proxy_success, core_success, dns_success) = tokio::join!(proxy_task, core_task, dns_task);
|
||||
let (proxy_result, core_result, dns_result) = tokio::join!(proxy_task, core_task, dns_task);
|
||||
|
||||
let all_success = tun_success && proxy_success && core_success && dns_success;
|
||||
let proxy_success = proxy_result.unwrap_or_default();
|
||||
let core_success = core_result.unwrap_or_default();
|
||||
let dns_success = dns_result.unwrap_or_default();
|
||||
|
||||
let all_success = proxy_success && core_success && dns_success;
|
||||
|
||||
logging!(
|
||||
info,
|
||||
Type::System,
|
||||
"异步关闭操作完成 - TUN: {}, 代理: {}, 核心: {}, DNS: {}, 总体: {}",
|
||||
tun_success,
|
||||
"异步关闭操作完成 - 代理: {}, 核心: {}, DNS: {}, 总体: {}",
|
||||
proxy_success,
|
||||
core_success,
|
||||
dns_success,
|
||||
|
||||
@@ -429,7 +429,9 @@ pub fn run() {
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
tauri::RunEvent::Exit => AsyncHandler::block_on(async {
|
||||
feat::quit().await;
|
||||
if !handle::Handle::global().is_exiting() {
|
||||
feat::quit().await;
|
||||
}
|
||||
}),
|
||||
tauri::RunEvent::ExitRequested { api, code, .. } => {
|
||||
AsyncHandler::block_on(async {
|
||||
|
||||
Reference in New Issue
Block a user