mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-29 17:15:38 +08:00
refactor: streamline config handling and logging mechanisms
This commit is contained in:
@@ -1,9 +1,6 @@
|
|||||||
use super::CmdResult;
|
use super::CmdResult;
|
||||||
use crate::{
|
use crate::{
|
||||||
cmd::StringifyErr as _,
|
cmd::StringifyErr as _, config::Config, core::CoreManager, logging_error, utils::logging::Type,
|
||||||
config::{Config, ConfigType},
|
|
||||||
core::CoreManager,
|
|
||||||
log_err,
|
|
||||||
};
|
};
|
||||||
use anyhow::{Context as _, anyhow};
|
use anyhow::{Context as _, anyhow};
|
||||||
use serde_yaml_ng::Mapping;
|
use serde_yaml_ng::Mapping;
|
||||||
@@ -104,14 +101,9 @@ pub async fn update_proxy_chain_config_in_runtime(
|
|||||||
{
|
{
|
||||||
let runtime = Config::runtime().await;
|
let runtime = Config::runtime().await;
|
||||||
runtime.edit_draft(|d| d.update_proxy_chain_config(proxy_chain_config));
|
runtime.edit_draft(|d| d.update_proxy_chain_config(proxy_chain_config));
|
||||||
runtime.apply();
|
// 我们需要在 CoreManager 中验证并应用配置,这里不应该直接调用 runtime.apply()
|
||||||
}
|
}
|
||||||
|
logging_error!(Type::Core, CoreManager::global().update_config().await);
|
||||||
// 生成新的运行配置文件并通知 Clash 核心重新加载
|
|
||||||
let run_path = Config::generate_file(ConfigType::Run)
|
|
||||||
.await
|
|
||||||
.stringify_err()?;
|
|
||||||
log_err!(CoreManager::global().put_configs_force(run_path).await);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,7 @@ pub mod bypass {
|
|||||||
pub mod timing {
|
pub mod timing {
|
||||||
use super::Duration;
|
use super::Duration;
|
||||||
|
|
||||||
pub const CONFIG_UPDATE_DEBOUNCE: Duration = Duration::from_millis(500);
|
pub const CONFIG_UPDATE_DEBOUNCE: Duration = Duration::from_millis(300);
|
||||||
pub const CONFIG_RELOAD_DELAY: Duration = Duration::from_millis(300);
|
|
||||||
pub const EVENT_EMIT_DELAY: Duration = Duration::from_millis(20);
|
pub const EVENT_EMIT_DELAY: Duration = Duration::from_millis(20);
|
||||||
pub const STARTUP_ERROR_DELAY: Duration = Duration::from_secs(2);
|
pub const STARTUP_ERROR_DELAY: Duration = Duration::from_secs(2);
|
||||||
pub const ERROR_BATCH_DELAY: Duration = Duration::from_millis(300);
|
pub const ERROR_BATCH_DELAY: Duration = Duration::from_millis(300);
|
||||||
@@ -58,15 +57,6 @@ pub mod files {
|
|||||||
pub const WINDOW_STATE: &str = "window_state.json";
|
pub const WINDOW_STATE: &str = "window_state.json";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod error_patterns {
|
|
||||||
pub const CONNECTION_ERRORS: &[&str] = &[
|
|
||||||
"Failed to create connection",
|
|
||||||
"The system cannot find the file specified",
|
|
||||||
"operation timed out",
|
|
||||||
"connection refused",
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod tun {
|
pub mod tun {
|
||||||
pub const DEFAULT_STACK: &str = "gvisor";
|
pub const DEFAULT_STACK: &str = "gvisor";
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ use anyhow::{Result, anyhow};
|
|||||||
use smartstring::alias::String;
|
use smartstring::alias::String;
|
||||||
use std::{path::PathBuf, time::Instant};
|
use std::{path::PathBuf, time::Instant};
|
||||||
use tauri_plugin_mihomo::Error as MihomoError;
|
use tauri_plugin_mihomo::Error as MihomoError;
|
||||||
use tokio::time::sleep;
|
|
||||||
|
|
||||||
impl CoreManager {
|
impl CoreManager {
|
||||||
pub async fn use_default_config(&self, error_key: &str, error_msg: &str) -> Result<()> {
|
pub async fn use_default_config(&self, error_key: &str, error_msg: &str) -> Result<()> {
|
||||||
@@ -37,25 +36,25 @@ impl CoreManager {
|
|||||||
return Ok((true, String::new()));
|
return Ok((true, String::new()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.should_update_config()? {
|
if !self.should_update_config() {
|
||||||
return Ok((true, String::new()));
|
return Ok((true, String::new()));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.perform_config_update().await
|
self.perform_config_update().await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_update_config(&self) -> Result<bool> {
|
fn should_update_config(&self) -> bool {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let last = self.get_last_update();
|
let last = self.get_last_update();
|
||||||
|
|
||||||
if let Some(last_time) = last
|
if let Some(last_time) = last
|
||||||
&& now.duration_since(*last_time) < timing::CONFIG_UPDATE_DEBOUNCE
|
&& now.duration_since(*last_time) < timing::CONFIG_UPDATE_DEBOUNCE
|
||||||
{
|
{
|
||||||
return Ok(false);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.set_last_update(now);
|
self.set_last_update(now);
|
||||||
Ok(true)
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn perform_config_update(&self) -> Result<(bool, String)> {
|
async fn perform_config_update(&self) -> Result<(bool, String)> {
|
||||||
@@ -78,22 +77,14 @@ impl CoreManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn put_configs_force(&self, path: PathBuf) -> Result<()> {
|
async fn apply_config(&self, path: PathBuf) -> Result<()> {
|
||||||
self.apply_config(path).await
|
let path = dirs::path_to_str(&path)?;
|
||||||
}
|
match self.reload_config(path).await {
|
||||||
|
|
||||||
pub(super) async fn apply_config(&self, path: PathBuf) -> Result<()> {
|
|
||||||
let path_str = dirs::path_to_str(&path)?;
|
|
||||||
|
|
||||||
match self.reload_config(path_str).await {
|
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
Config::runtime().await.apply();
|
Config::runtime().await.apply();
|
||||||
logging!(info, Type::Core, "Configuration applied");
|
logging!(info, Type::Core, "Configuration applied");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(err) if Self::should_restart_on_error(&err) => {
|
|
||||||
self.retry_with_restart(path_str).await
|
|
||||||
}
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
Config::runtime().await.discard();
|
Config::runtime().await.discard();
|
||||||
Err(anyhow!("Failed to apply config: {}", err))
|
Err(anyhow!("Failed to apply config: {}", err))
|
||||||
@@ -101,54 +92,10 @@ impl CoreManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn retry_with_restart(&self, config_path: &str) -> Result<()> {
|
|
||||||
if handle::Handle::global().is_exiting() {
|
|
||||||
return Err(anyhow!("Application exiting"));
|
|
||||||
}
|
|
||||||
|
|
||||||
logging!(warn, Type::Core, "Restarting core for config reload");
|
|
||||||
self.restart_core().await?;
|
|
||||||
sleep(timing::CONFIG_RELOAD_DELAY).await;
|
|
||||||
|
|
||||||
self.reload_config(config_path).await?;
|
|
||||||
Config::runtime().await.apply();
|
|
||||||
logging!(info, Type::Core, "Configuration applied after restart");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn reload_config(&self, path: &str) -> Result<(), MihomoError> {
|
async fn reload_config(&self, path: &str) -> Result<(), MihomoError> {
|
||||||
handle::Handle::mihomo()
|
handle::Handle::mihomo()
|
||||||
.await
|
.await
|
||||||
.reload_config(true, path)
|
.reload_config(true, path)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_restart_on_error(err: &MihomoError) -> bool {
|
|
||||||
match err {
|
|
||||||
MihomoError::ConnectionFailed | MihomoError::ConnectionLost => true,
|
|
||||||
MihomoError::Io(io_err) => Self::is_connection_io_error(io_err.kind()),
|
|
||||||
MihomoError::Reqwest(req_err) => {
|
|
||||||
req_err.is_connect()
|
|
||||||
|| req_err.is_timeout()
|
|
||||||
|| Self::contains_error_pattern(&req_err.to_string())
|
|
||||||
}
|
|
||||||
MihomoError::FailedResponse(msg) => Self::contains_error_pattern(msg),
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn is_connection_io_error(kind: std::io::ErrorKind) -> bool {
|
|
||||||
matches!(
|
|
||||||
kind,
|
|
||||||
std::io::ErrorKind::ConnectionAborted
|
|
||||||
| std::io::ErrorKind::ConnectionRefused
|
|
||||||
| std::io::ErrorKind::ConnectionReset
|
|
||||||
| std::io::ErrorKind::NotFound
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn contains_error_pattern(text: &str) -> bool {
|
|
||||||
use crate::constants::error_patterns::CONNECTION_ERRORS;
|
|
||||||
CONNECTION_ERRORS.iter().any(|p| text.contains(p))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use super::{CoreManager, RunningMode};
|
use super::{CoreManager, RunningMode};
|
||||||
use crate::config::{Config, ConfigType, IVerge};
|
use crate::cmd::StringifyErr as _;
|
||||||
|
use crate::config::{Config, IVerge};
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{
|
core::{
|
||||||
logger::CLASH_LOGGER,
|
logger::CLASH_LOGGER,
|
||||||
@@ -55,13 +56,8 @@ impl CoreManager {
|
|||||||
let verge_data = Config::verge().await.latest_arc();
|
let verge_data = Config::verge().await.latest_arc();
|
||||||
verge_data.save_file().await.map_err(|e| e.to_string())?;
|
verge_data.save_file().await.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
let run_path = Config::generate_file(ConfigType::Run)
|
self.update_config().await.stringify_err()?;
|
||||||
.await
|
Ok(())
|
||||||
.map_err(|e| e.to_string())?;
|
|
||||||
|
|
||||||
self.apply_config(run_path)
|
|
||||||
.await
|
|
||||||
.map_err(|e| e.to_string().into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn prepare_startup(&self) -> Result<()> {
|
async fn prepare_startup(&self) -> Result<()> {
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
config::Config,
|
config::Config,
|
||||||
core::{handle, timer::Timer, tray::Tray},
|
core::{handle, timer::Timer, tray::Tray},
|
||||||
log_err, logging,
|
logging,
|
||||||
process::AsyncHandler,
|
process::AsyncHandler,
|
||||||
utils::logging::Type,
|
utils::logging::Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
use crate::logging_error;
|
use crate::logging_error;
|
||||||
|
|
||||||
use crate::utils::window_manager::WindowManager;
|
use crate::utils::window_manager::WindowManager;
|
||||||
@@ -184,7 +183,7 @@ fn cancel_window_close_listener() {
|
|||||||
fn setup_webview_focus_listener() {
|
fn setup_webview_focus_listener() {
|
||||||
if let Some(window) = handle::Handle::get_window() {
|
if let Some(window) = handle::Handle::get_window() {
|
||||||
let handler_id = window.listen("tauri://focus", move |_event| {
|
let handler_id = window.listen("tauri://focus", move |_event| {
|
||||||
log_err!(cancel_light_weight_timer());
|
logging_error!(Type::Lightweight, cancel_light_weight_timer());
|
||||||
logging!(
|
logging!(
|
||||||
debug,
|
debug,
|
||||||
Type::Lightweight,
|
Type::Lightweight,
|
||||||
|
|||||||
@@ -65,21 +65,6 @@ macro_rules! error {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! log_err {
|
|
||||||
($result: expr) => {
|
|
||||||
if let Err(err) = $result {
|
|
||||||
log::error!(target: "app", "{err}");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
($result: expr, $err_str: expr) => {
|
|
||||||
if let Err(_) = $result {
|
|
||||||
log::error!(target: "app", "{}", $err_str);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// wrap the anyhow error
|
/// wrap the anyhow error
|
||||||
/// transform the error to String
|
/// transform the error to String
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
|||||||
Reference in New Issue
Block a user