mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-04 22:52:23 +08:00
Serialize Verge patches behind the active configuration writer so toggling the system proxy after TUN does not fail immediately on lock contention. CLose: #6613, #8481, #8357
57 lines
1.7 KiB
Rust
57 lines
1.7 KiB
Rust
use crate::config::{Config, IVerge};
|
|
use anyhow::Result;
|
|
use clash_verge_draft::SharedDraft;
|
|
use serde_yaml_ng::Mapping;
|
|
use tokio::sync::MutexGuard;
|
|
|
|
pub async fn patch_clash(patch: &Mapping) -> Result<()> {
|
|
let config_write = Config::try_lock_config_write()?;
|
|
super::executor::apply(
|
|
&config_write,
|
|
super::executor::Patch::Clash(patch),
|
|
super::effects::clash_effects(patch),
|
|
)
|
|
.await
|
|
}
|
|
|
|
/// Apply a patch, then reconcile TUN when its setting changes.
|
|
///
|
|
/// TUN patches do not always produce a Run State transition, so reconciliation is explicit.
|
|
pub async fn patch_verge(patch: &IVerge, not_save_file: bool) -> Result<()> {
|
|
apply_verge_patch(patch, not_save_file).await?;
|
|
if patch.enable_tun_mode.is_some() {
|
|
super::reconcile_tun_availability().await;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
/// Apply a patch without post-update reconciliation.
|
|
pub(super) async fn apply_verge_patch(patch: &IVerge, not_save_file: bool) -> Result<()> {
|
|
let config_write = Config::lock_config_write().await;
|
|
apply_verge_patch_locked(&config_write, patch, not_save_file).await
|
|
}
|
|
|
|
/// Apply a patch with the shared configuration write lock already held.
|
|
/// Callers must pass the guard returned by [`Config::lock_config_write`].
|
|
pub(super) async fn apply_verge_patch_locked(
|
|
_config_write: &MutexGuard<'_, ()>,
|
|
patch: &IVerge,
|
|
not_save_file: bool,
|
|
) -> Result<()> {
|
|
super::executor::apply(
|
|
_config_write,
|
|
super::executor::Patch::Verge {
|
|
patch,
|
|
persist: !not_save_file,
|
|
},
|
|
super::effects::verge_effects(patch),
|
|
)
|
|
.await
|
|
}
|
|
|
|
pub async fn fetch_verge_config() -> Result<SharedDraft<IVerge>> {
|
|
let draft = Config::verge().await;
|
|
let data = draft.data_arc();
|
|
Ok(data)
|
|
}
|