mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-22 19:52:14 +08:00
fix(core): serialize runtime config updates
This commit is contained in:
@@ -94,12 +94,10 @@ pub async fn get_runtime_proxy_chain_config(proxy_chain_exit_node: String) -> Cm
|
||||
/// 更新运行时链式代理配置
|
||||
#[tauri::command]
|
||||
pub async fn update_proxy_chain_config_in_runtime(proxy_chain_config: Option<serde_yaml_ng::Value>) -> CmdResult<()> {
|
||||
match CoreManager::global()
|
||||
.update_runtime_config(|d| d.update_proxy_chain_config(proxy_chain_config))
|
||||
.await
|
||||
{
|
||||
let runtime = Config::runtime().await;
|
||||
runtime.edit_draft(|d| d.update_proxy_chain_config(proxy_chain_config));
|
||||
// 我们需要在 CoreManager 中验证并应用配置,这里不应该直接调用 runtime.apply()
|
||||
}
|
||||
match CoreManager::global().apply_generate_config().await {
|
||||
Ok(outcome) if outcome.is_valid() => {}
|
||||
Ok(outcome) => logging!(
|
||||
warn,
|
||||
|
||||
@@ -10,6 +10,7 @@ use crate::{
|
||||
};
|
||||
use anyhow::{Result, anyhow};
|
||||
use clash_verge_logging::{Type, logging};
|
||||
use scopeguard::defer;
|
||||
use smartstring::alias::String;
|
||||
use std::{collections::HashSet, path::PathBuf, time::Instant};
|
||||
use tauri_plugin_mihomo::Error as MihomoError;
|
||||
@@ -45,6 +46,14 @@ impl CoreManager {
|
||||
});
|
||||
}
|
||||
|
||||
if !self.try_start_config_update() {
|
||||
logging!(info, Type::Core, "Configuration update is already running");
|
||||
return Ok(ValidationOutcome::Busy);
|
||||
}
|
||||
defer! {
|
||||
self.finish_config_update();
|
||||
}
|
||||
|
||||
if !force && !self.should_update_config() {
|
||||
logging!(debug, Type::Core, "Skipping config update due to debounce");
|
||||
return Ok(ValidationOutcome::Skipped {
|
||||
@@ -89,10 +98,26 @@ impl CoreManager {
|
||||
return Ok(ValidationOutcome::invalid_from_message(message));
|
||||
}
|
||||
|
||||
self.apply_generate_config().await
|
||||
self.apply_generate_config_inner().await
|
||||
}
|
||||
|
||||
pub async fn apply_generate_config(&self) -> Result<ValidationOutcome> {
|
||||
pub(crate) async fn update_runtime_config<F>(&self, f: F) -> Result<ValidationOutcome>
|
||||
where
|
||||
F: FnOnce(&mut IRuntime),
|
||||
{
|
||||
if !self.try_start_config_update() {
|
||||
logging!(info, Type::Core, "Configuration update is already running");
|
||||
return Ok(ValidationOutcome::Busy);
|
||||
}
|
||||
defer! {
|
||||
self.finish_config_update();
|
||||
}
|
||||
|
||||
Config::runtime().await.edit_draft(f);
|
||||
self.apply_generate_config_inner().await
|
||||
}
|
||||
|
||||
async fn apply_generate_config_inner(&self) -> Result<ValidationOutcome> {
|
||||
match CoreConfigValidator::global().validate_config_outcome().await {
|
||||
Ok(outcome) if outcome.is_valid() => {
|
||||
let run_path = Config::generate_file(ConfigType::Run).await?;
|
||||
|
||||
@@ -6,7 +6,14 @@ use anyhow::Result;
|
||||
use arc_swap::{ArcSwap, ArcSwapOption};
|
||||
use clash_verge_logger::AsyncLogger;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::{fmt, sync::Arc, time::Instant};
|
||||
use std::{
|
||||
fmt,
|
||||
sync::{
|
||||
Arc,
|
||||
atomic::{AtomicBool, Ordering},
|
||||
},
|
||||
time::Instant,
|
||||
};
|
||||
use tauri_plugin_shell::process::CommandChild;
|
||||
|
||||
use crate::singleton;
|
||||
@@ -34,6 +41,7 @@ impl fmt::Display for RunningMode {
|
||||
pub struct CoreManager {
|
||||
state: ArcSwap<State>,
|
||||
last_update: ArcSwapOption<Instant>,
|
||||
config_update_in_progress: AtomicBool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -56,6 +64,7 @@ impl Default for CoreManager {
|
||||
Self {
|
||||
state: ArcSwap::new(Arc::new(State::default())),
|
||||
last_update: ArcSwapOption::new(None),
|
||||
config_update_in_progress: AtomicBool::new(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,6 +104,14 @@ impl CoreManager {
|
||||
self.last_update.store(Some(Arc::new(time)));
|
||||
}
|
||||
|
||||
fn try_start_config_update(&self) -> bool {
|
||||
!self.config_update_in_progress.swap(true, Ordering::AcqRel)
|
||||
}
|
||||
|
||||
fn finish_config_update(&self) {
|
||||
self.config_update_in_progress.store(false, Ordering::Release);
|
||||
}
|
||||
|
||||
pub async fn init(&self) -> Result<()> {
|
||||
self.start_core().await?;
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user