refactor: update draft handling and improve benchmark structure

This commit is contained in:
Tunglies
2025-10-31 23:31:04 +08:00
parent b672dd7055
commit 518875acde
8 changed files with 114 additions and 148 deletions

View File

@@ -168,11 +168,11 @@ impl Config {
pub async fn generate() -> Result<()> {
let (config, exists_keys, logs) = enhance::enhance().await;
*Config::runtime().await.draft_mut() = Box::new(IRuntime {
**Config::runtime().await.draft_mut() = IRuntime {
config: Some(config),
exists_keys,
chain_logs: logs,
});
};
Ok(())
}

View File

@@ -1,3 +1,4 @@
use crate::config::Config;
use crate::{
config::{DEFAULT_PAC, deserialize_encrypted, serialize_encrypted},
logging,
@@ -304,19 +305,17 @@ impl IVerge {
/// 配置修正后重新加载配置
async fn reload_config_after_fix(updated_config: IVerge) -> Result<()> {
use crate::config::Config;
let config_draft = Config::verge().await;
*config_draft.draft_mut() = Box::new(updated_config.clone());
config_draft.apply();
logging!(
info,
Type::Config,
"内存配置已强制更新新的clash_core: {:?}",
updated_config.clash_core
&updated_config.clash_core
);
let config_draft = Config::verge().await;
**config_draft.draft_mut() = updated_config;
config_draft.apply();
Ok(())
}

View File

@@ -19,11 +19,11 @@ impl CoreManager {
let runtime_path = dirs::app_home_dir()?.join(RUNTIME_CONFIG);
let clash_config = Config::clash().await.latest_ref().0.clone();
*Config::runtime().await.draft_mut() = Box::new(IRuntime {
**Config::runtime().await.draft_mut() = IRuntime {
config: Some(clash_config.clone()),
exists_keys: vec![],
chain_logs: Default::default(),
});
};
help::save_yaml(&runtime_path, &clash_config, Some("# Clash Verge Runtime")).await?;
handle::Handle::notice_message(error_key, error_msg);

View File

@@ -419,13 +419,15 @@ impl Timer {
};
// Get the profile updated timestamp - now safe to await
let config_profiles = Config::profiles().await;
let profiles = config_profiles.data_ref().clone();
let items = match profiles.get_items() {
Some(i) => i,
None => {
logging!(warn, Type::Timer, "获取配置列表失败");
return None;
let items = {
let profiles = Config::profiles().await;
let profiles_guard = profiles.latest_ref();
match profiles_guard.get_items() {
Some(i) => i.clone(),
None => {
logging!(warn, Type::Timer, "获取配置列表失败");
return None;
}
}
};

View File

@@ -102,7 +102,7 @@ async fn perform_profile_update(
let profile_name = item.name.clone().unwrap_or_else(|| uid.clone());
handle::Handle::notice_message("update_with_clash_proxy", profile_name);
let is_current = Some(uid.clone()) == profiles.data_ref().get_current();
let is_current = Some(uid.clone()) == profiles.latest_ref().get_current();
log::info!(target: "app", "[订阅更新] 是否为当前使用的订阅: {is_current}");
Ok(is_current)
}

View File

@@ -47,7 +47,7 @@ pub async fn clean_async() -> bool {
let tun_task = async {
let tun_enabled = Config::verge()
.await
.data_ref()
.latest_ref()
.enable_tun_mode
.unwrap_or(false);

View File

@@ -24,7 +24,6 @@ impl<T: Clone + ToOwned> From<T> for Draft<T> {
///
/// # Methods
/// - `data_mut`: Returns a mutable reference to the committed data.
/// - `data_ref`: Returns an immutable reference to the committed data.
/// - `draft_mut`: Creates or retrieves a mutable reference to the draft data, cloning the committed data if no draft exists.
/// - `latest_ref`: Returns an immutable reference to the draft data if it exists, otherwise to the committed data.
/// - `apply`: Commits the draft data, replacing the committed data and returning the old committed value if a draft existed.
@@ -35,11 +34,6 @@ impl<T: Clone + ToOwned> Draft<Box<T>> {
RwLockWriteGuard::map(self.inner.write(), |inner| &mut inner.0)
}
/// 返回正式数据的只读视图(不包含草稿)
pub fn data_ref(&self) -> MappedRwLockReadGuard<'_, Box<T>> {
RwLockReadGuard::map(self.inner.read(), |inner| &inner.0)
}
/// 创建或获取草稿并返回可写引用
pub fn draft_mut(&self) -> MappedRwLockWriteGuard<'_, Box<T>> {
let guard = self.inner.upgradable_read();
@@ -69,17 +63,21 @@ impl<T: Clone + ToOwned> Draft<Box<T>> {
}
/// 提交草稿,返回旧正式数据
pub fn apply(&self) -> Option<Box<T>> {
let mut inner = self.inner.write();
inner
.1
.take()
.map(|draft| std::mem::replace(&mut inner.0, draft))
pub fn apply(&self) {
let guard = self.inner.upgradable_read();
if guard.1.is_none() {
return;
}
let mut guard = RwLockUpgradableReadGuard::upgrade(guard);
if let Some(draft) = guard.1.take() {
guard.0 = draft;
}
}
/// 丢弃草稿,返回被丢弃的草稿
pub fn discard(&self) -> Option<Box<T>> {
self.inner.write().1.take()
pub fn discard(&self) {
self.inner.write().1.take();
}
/// 异步修改正式数据,闭包直接获得 Box<T> 所有权
@@ -152,8 +150,7 @@ fn test_draft_box() {
}
// 5. 提交草稿
assert!(draft.apply().is_some()); // 第一次提交应有返回
assert!(draft.apply().is_none()); // 第二次提交返回 None
draft.apply();
// 正式数据已更新
{
@@ -170,8 +167,7 @@ fn test_draft_box() {
assert_eq!(draft.draft_mut().enable_auto_launch, Some(true));
// 7. 丢弃草稿
assert!(draft.discard().is_some()); // 第一次丢弃返回 Some
assert!(draft.discard().is_none()); // 再次丢弃返回 None
draft.discard();
// 8. 草稿已被丢弃,新的 draft_mut() 会重新 clone
assert_eq!(draft.draft_mut().enable_auto_launch, Some(false));