refactor: logic optimization

This commit is contained in:
huzibaca 2024-09-27 00:24:05 +08:00
parent ce7818c436
commit c3cba03ac6
4 changed files with 86 additions and 134 deletions

View File

@ -185,7 +185,7 @@ pub async fn change_clash_core(clash_core: Option<String>) -> CmdResult {
/// restart the sidecar /// restart the sidecar
#[tauri::command] #[tauri::command]
pub async fn restart_sidecar() -> CmdResult { pub async fn restart_sidecar() -> CmdResult {
wrap_err!(CoreManager::global().run_core().await) wrap_err!(CoreManager::global().restart_core().await)
} }
/// get the system proxy /// get the system proxy

View File

@ -4,20 +4,18 @@ use crate::log_err;
use crate::utils::dirs; use crate::utils::dirs;
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use parking_lot::Mutex;
use serde_yaml::Mapping; use serde_yaml::Mapping;
use std::{sync::Arc, time::Duration}; use std::{sync::Arc, time::Duration};
use sysinfo::{ProcessRefreshKind, RefreshKind, System}; use sysinfo::{ProcessRefreshKind, RefreshKind, System};
use tauri_plugin_shell::process::{CommandChild, CommandEvent}; use tauri_plugin_shell::process::CommandEvent;
use tauri_plugin_shell::ShellExt; use tauri_plugin_shell::ShellExt;
use tokio::sync::Mutex;
use tokio::time::sleep; use tokio::time::sleep;
#[derive(Debug)] #[derive(Debug)]
pub struct CoreManager { pub struct CoreManager {
sidecar: Arc<Mutex<Option<CommandChild>>>, running: Arc<Mutex<bool>>,
#[allow(unused)]
use_service_mode: Arc<Mutex<bool>>,
} }
impl CoreManager { impl CoreManager {
@ -25,19 +23,15 @@ impl CoreManager {
static CORE_MANAGER: OnceCell<CoreManager> = OnceCell::new(); static CORE_MANAGER: OnceCell<CoreManager> = OnceCell::new();
CORE_MANAGER.get_or_init(|| CoreManager { CORE_MANAGER.get_or_init(|| CoreManager {
sidecar: Arc::new(Mutex::new(None)), running: Arc::new(Mutex::new(false)),
use_service_mode: Arc::new(Mutex::new(false)),
}) })
} }
pub fn init(&self) -> Result<()> { pub async fn init(&self) -> Result<()> {
tauri::async_runtime::spawn(async { log::trace!("run core start");
log::trace!("run core start"); // 启动clash
// 启动clash log_err!(Self::global().start_core().await);
log_err!(Self::global().run_core().await); log::trace!("run core end");
log::trace!("run core end");
});
Ok(()) Ok(())
} }
@ -47,21 +41,7 @@ impl CoreManager {
let config_path = dirs::path_to_str(&config_path)?; let config_path = dirs::path_to_str(&config_path)?;
let clash_core = { Config::verge().latest().clash_core.clone() }; let clash_core = { Config::verge().latest().clash_core.clone() };
let mut clash_core = clash_core.unwrap_or("verge-mihomo".into()); let clash_core = clash_core.unwrap_or("verge-mihomo".into());
// compatibility
if clash_core.contains("clash") {
clash_core = "verge-mihomo".to_string();
Config::verge().draft().patch_config(IVerge {
clash_core: Some("verge-mihomo".to_string()),
..IVerge::default()
});
Config::verge().apply();
match Config::verge().data().save_file() {
Ok(_) => handle::Handle::refresh_verge(),
Err(err) => log::error!(target: "app", "{err}"),
}
}
let test_dir = dirs::app_home_dir()?.join("test"); let test_dir = dirs::app_home_dir()?.join("test");
let test_dir = dirs::path_to_str(&test_dir)?; let test_dir = dirs::path_to_str(&test_dir)?;
@ -88,40 +68,54 @@ impl CoreManager {
Ok(()) Ok(())
} }
/// 启动核心 /// 停止核心运行
pub async fn run_core(&self) -> Result<()> { pub async fn stop_core(&self) -> Result<()> {
let config_path = Config::generate_file(ConfigType::Run)?; let mut running = self.running.lock().await;
if !*running {
log::debug!("core is not running");
return Ok(());
}
let clash_core = { Config::verge().latest().clash_core.clone() };
let clash_core = clash_core.unwrap_or("verge-mihomo".into());
// 关闭tun模式 // 关闭tun模式
let mut disable = Mapping::new(); let mut disable = Mapping::new();
let mut tun = Mapping::new(); let mut tun = Mapping::new();
tun.insert("enable".into(), false.into()); tun.insert("enable".into(), false.into());
disable.insert("tun".into(), tun.into()); disable.insert("tun".into(), tun.into());
log::debug!(target: "app", "disable tun mode"); log::debug!(target: "app", "disable tun mode");
let _ = clash_api::patch_configs(&disable).await; log_err!(clash_api::patch_configs(&disable).await);
if *self.use_service_mode.lock() {
log::debug!(target: "app", "stop the core by service");
log_err!(service::stop_core_by_service().await);
} else {
let system = System::new_with_specifics(
RefreshKind::new().with_processes(ProcessRefreshKind::everything()),
);
let procs = system.processes_by_name("verge-mihomo");
for proc in procs {
log::debug!(target: "app", "kill all clash process");
proc.kill();
}
}
// 服务模式 // 服务模式
let enable = { Config::verge().latest().enable_service_mode }; let service_enable = { Config::verge().latest().enable_service_mode };
let enable = enable.unwrap_or(false); let service_enable = service_enable.unwrap_or(false);
if service_enable {
log::debug!(target: "app", "stop the core by service");
log_err!(service::stop_core_by_service().await);
return Ok(());
}
kill_processes_by_name(clash_core.as_str());
*running = false;
*self.use_service_mode.lock() = enable; Ok(())
}
if enable { /// 启动核心
pub async fn start_core(&self) -> Result<()> {
let mut running = self.running.lock().await;
if *running {
log::debug!("core is running");
return Ok(());
}
let config_path = Config::generate_file(ConfigType::Run)?;
let clash_core = { Config::verge().latest().clash_core.clone() };
let clash_core = clash_core.unwrap_or("verge-mihomo".into());
// 服务模式
let service_enable = { Config::verge().latest().enable_service_mode };
let service_enable = service_enable.unwrap_or(false);
if service_enable {
// 服务模式启动失败就直接运行sidecar // 服务模式启动失败就直接运行sidecar
log::debug!(target: "app", "try to run core in service mode"); log::debug!(target: "app", "try to run core in service mode");
@ -131,27 +125,23 @@ impl CoreManager {
} }
.await; .await;
match res { match res {
Ok(_) => return Ok(()), Ok(_) => {
return {
*running = true;
Ok(())
}
}
Err(err) => { Err(err) => {
// 修改这个值免得stop出错 log::error!(target: "app start service err", "{err}");
*self.use_service_mode.lock() = false;
log::error!(target: "app", "{err}");
} }
} }
} }
let app_dir = dirs::app_home_dir()?; let app_dir = dirs::app_home_dir()?;
let app_dir = dirs::path_to_str(&app_dir)?; let app_dir = dirs::path_to_str(&app_dir)?;
let clash_core = { Config::verge().latest().clash_core.clone() };
let clash_core = clash_core.unwrap_or("verge-mihomo".into());
let config_path = dirs::path_to_str(&config_path)?; let config_path = dirs::path_to_str(&config_path)?;
let args = vec!["-d", app_dir, "-f", config_path]; let args = vec!["-d", app_dir, "-f", config_path];
let app_handle = handle::Handle::global().app_handle().unwrap(); let app_handle = handle::Handle::global().app_handle().unwrap();
let cmd = app_handle.shell().sidecar(clash_core)?; let cmd = app_handle.shell().sidecar(clash_core)?;
let (mut rx, _) = cmd.args(args).spawn()?; let (mut rx, _) = cmd.args(args).spawn()?;
@ -174,75 +164,21 @@ impl CoreManager {
} }
CommandEvent::Terminated(_) => { CommandEvent::Terminated(_) => {
log::info!(target: "app", "mihomo core terminated"); log::info!(target: "app", "mihomo core terminated");
let _ = CoreManager::global().recover_core();
break; break;
} }
_ => {} _ => {}
} }
} }
}); });
*running = true;
Ok(()) Ok(())
} }
/// 重启内核 /// 重启内核
pub fn recover_core(&'static self) -> Result<()> { pub async fn restart_core(&self) -> Result<()> {
// 服务模式不管 // 重新启动app
if *self.use_service_mode.lock() { self.stop_core().await?;
return Ok(()); self.start_core().await?;
}
// 清空原来的sidecar值
let _ = self.sidecar.lock().take();
tauri::async_runtime::spawn(async move {
// 6秒之后再查看服务是否正常 (时间随便搞的)
// terminated 可能是切换内核 (切换内核已经有500ms的延迟)
sleep(Duration::from_millis(6666)).await;
if self.sidecar.lock().is_none() {
log::info!(target: "app", "recover clash core");
// 重新启动app
if let Err(err) = self.run_core().await {
log::error!(target: "app", "failed to recover clash core");
log::error!(target: "app", "{err}");
let _ = self.recover_core();
}
}
});
Ok(())
}
/// 停止核心运行
pub async fn stop_core(&self) -> Result<()> {
// 关闭tun模式
let mut disable = Mapping::new();
let mut tun = Mapping::new();
tun.insert("enable".into(), false.into());
disable.insert("tun".into(), tun.into());
log::debug!(target: "app", "disable tun mode");
let _ = clash_api::patch_configs(&disable).await;
if *self.use_service_mode.lock() {
log::debug!(target: "app", "stop the core by service");
log_err!(service::stop_core_by_service().await);
return Ok(());
}
let mut sidecar = self.sidecar.lock();
let _ = sidecar.take();
let system = System::new_with_specifics(
RefreshKind::new().with_processes(ProcessRefreshKind::everything()),
);
let procs = system.processes_by_name("verge-mihomo");
for proc in procs {
log::debug!(target: "app", "kill all clash process");
proc.kill();
}
Ok(()) Ok(())
} }
@ -267,7 +203,7 @@ impl CoreManager {
// 清掉旧日志 // 清掉旧日志
Logger::global().clear_log(); Logger::global().clear_log();
match self.run_core().await { match self.restart_core().await {
Ok(_) => { Ok(_) => {
Config::verge().apply(); Config::verge().apply();
Config::runtime().apply(); Config::runtime().apply();
@ -313,3 +249,16 @@ impl CoreManager {
Ok(()) Ok(())
} }
} }
fn kill_processes_by_name(process_name: &str) {
let mut system = System::new_with_specifics(
RefreshKind::new().with_processes(ProcessRefreshKind::everything()),
);
system.refresh_processes();
let procs = system.processes_by_name(process_name);
for proc in procs {
log::debug!(target: "app", "Killing process: {}", proc.name());
proc.kill();
}
}

View File

@ -26,7 +26,7 @@ pub fn open_or_close_dashboard() {
// 重启clash // 重启clash
pub fn restart_clash_core() { pub fn restart_clash_core() {
tauri::async_runtime::spawn(async { tauri::async_runtime::spawn(async {
match CoreManager::global().run_core().await { match CoreManager::global().restart_core().await {
Ok(_) => { Ok(_) => {
handle::Handle::refresh_clash(); handle::Handle::refresh_clash();
handle::Handle::notice_message("set_config::ok", "ok"); handle::Handle::notice_message("set_config::ok", "ok");
@ -112,7 +112,7 @@ pub async fn patch_clash(patch: Mapping) -> Result<()> {
// 激活订阅 // 激活订阅
if patch.get("secret").is_some() || patch.get("external-controller").is_some() { if patch.get("secret").is_some() || patch.get("external-controller").is_some() {
Config::generate().await?; Config::generate().await?;
CoreManager::global().run_core().await?; CoreManager::global().restart_core().await?;
handle::Handle::refresh_clash(); handle::Handle::refresh_clash();
} }
@ -141,6 +141,7 @@ pub async fn patch_clash(patch: Mapping) -> Result<()> {
/// 一般都是一个个的修改 /// 一般都是一个个的修改
pub async fn patch_verge(patch: IVerge) -> Result<()> { pub async fn patch_verge(patch: IVerge) -> Result<()> {
Config::verge().draft().patch_config(patch.clone()); Config::verge().draft().patch_config(patch.clone());
let tun_mode = patch.enable_tun_mode; let tun_mode = patch.enable_tun_mode;
let auto_launch = patch.enable_auto_launch; let auto_launch = patch.enable_auto_launch;
let system_proxy = patch.enable_system_proxy; let system_proxy = patch.enable_system_proxy;
@ -168,6 +169,7 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> {
let socks_port = patch.verge_socks_port; let socks_port = patch.verge_socks_port;
let http_enabled = patch.verge_http_enabled; let http_enabled = patch.verge_http_enabled;
let http_port = patch.verge_port; let http_port = patch.verge_port;
let res = { let res = {
let service_mode = patch.enable_service_mode; let service_mode = patch.enable_service_mode;
let mut generated = false; let mut generated = false;
@ -175,7 +177,7 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> {
log::debug!(target: "app", "change service mode to {}", service_mode.unwrap()); log::debug!(target: "app", "change service mode to {}", service_mode.unwrap());
if !generated { if !generated {
Config::generate().await?; Config::generate().await?;
CoreManager::global().run_core().await?; CoreManager::global().restart_core().await?;
generated = true; generated = true;
} }
} else if tun_mode.is_some() { } else if tun_mode.is_some() {
@ -184,14 +186,15 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> {
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
if (redir_enabled.is_some() || redir_port.is_some()) && !generated { if (redir_enabled.is_some() || redir_port.is_some()) && !generated {
Config::generate().await?; Config::generate().await?;
CoreManager::global().run_core().await?; CoreManager::global().restart_core().await?;
generated = true; generated = true;
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
if tproxy_enabled.is_some() || tproxy_port.is_some() { if tproxy_enabled.is_some() || tproxy_port.is_some() {
if !generated { if !generated {
Config::generate().await?; Config::generate().await?;
CoreManager::global().run_core().await?; CoreManager::global().restart_core().await?;
generated = true; generated = true;
} }
} }
@ -203,7 +206,7 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> {
&& !generated && !generated
{ {
Config::generate().await?; Config::generate().await?;
CoreManager::global().run_core().await?; CoreManager::global().restart_core().await?;
} }
if auto_launch.is_some() { if auto_launch.is_some() {
sysopt::Sysopt::global().update_launch()?; sysopt::Sysopt::global().update_launch()?;
@ -243,11 +246,11 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> {
Ok(()) => { Ok(()) => {
Config::verge().apply(); Config::verge().apply();
Config::verge().data().save_file()?; Config::verge().data().save_file()?;
Ok(()) return Ok(());
} }
Err(err) => { Err(err) => {
Config::verge().discard(); Config::verge().discard();
Err(err) return Err(err);
} }
} }
} }

View File

@ -79,7 +79,7 @@ pub async fn resolve_setup(app: &mut App) {
log_err!(Config::init_config().await); log_err!(Config::init_config().await);
log::trace!("launch core"); log::trace!("launch core");
log_err!(CoreManager::global().init()); log_err!(CoreManager::global().init().await);
// setup a simple http server for singleton // setup a simple http server for singleton
log::trace!("launch embed server"); log::trace!("launch embed server");