feat: Implement configuration caching mechanism and force-refresh feature**

 **New Features**:

* Added API and frontend support for forcibly refreshing Clash configuration cache
* Implemented a configuration cache TTL mechanism (60 seconds) to reduce redundant requests
* Introduced `ProxyRequestCache` system to manage backend data caching
* Automatically refresh frontend state after core operations to enhance user experience

🚀 **Performance Optimizations**:

* Increased Clash configuration refresh interval from 5 seconds to 60 seconds
* Force refresh cache after configuration updates to resolve data inconsistency
* Automatically trigger state refresh after core switch, start, stop, and restart actions

🔧 **Technical Improvements**:

* Removed unused dependencies: `ab_glyph`, `owned_ttf_parser`, `ttf-parser`
* Simplified WebSocket dependency management, unified `tungstenite` version
* Refactored configuration save validation process, improved merge file handling
* Improved error handling and overall user experience
This commit is contained in:
Tunglies
2025-07-24 01:56:18 +08:00
parent 27535c7bb7
commit 3048a2ae08
10 changed files with 83 additions and 99 deletions

85
src-tauri/Cargo.lock generated
View File

@@ -2,22 +2,6 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "ab_glyph"
version = "0.2.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e074464580a518d16a7126262fffaaa47af89d4099d4cb403f8ed938ba12ee7d"
dependencies = [
"ab_glyph_rasterizer",
"owned_ttf_parser",
]
[[package]]
name = "ab_glyph_rasterizer"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2187590a23ab1e3df8681afdf0987c48504d80291f002fcdb651f0ef5e25169"
[[package]]
name = "addr2line"
version = "0.24.2"
@@ -1125,7 +1109,6 @@ checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
name = "clash-verge"
version = "2.4.0"
dependencies = [
"ab_glyph",
"aes-gcm",
"anyhow",
"async-trait",
@@ -1185,8 +1168,6 @@ dependencies = [
"tauri-plugin-window-state",
"tempfile",
"tokio",
"tokio-tungstenite 0.24.0",
"tungstenite 0.27.0",
"users",
"warp",
"winapi",
@@ -4933,15 +4914,6 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "owned_ttf_parser"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22ec719bbf3b2a81c109a4e20b1f129b5566b7dce654bc3872f6a05abf82b2c4"
dependencies = [
"ttf-parser",
]
[[package]]
name = "pango"
version = "0.18.3"
@@ -7898,19 +7870,7 @@ dependencies = [
"futures-util",
"log",
"tokio",
"tungstenite 0.21.0",
]
[[package]]
name = "tokio-tungstenite"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9"
dependencies = [
"futures-util",
"log",
"tokio",
"tungstenite 0.24.0",
"tungstenite",
]
[[package]]
@@ -8274,12 +8234,6 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "ttf-parser"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31"
[[package]]
name = "tungstenite"
version = "0.21.0"
@@ -8299,41 +8253,6 @@ dependencies = [
"utf-8",
]
[[package]]
name = "tungstenite"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a"
dependencies = [
"byteorder",
"bytes",
"data-encoding",
"http 1.3.1",
"httparse",
"log",
"rand 0.8.5",
"sha1",
"thiserror 1.0.69",
"utf-8",
]
[[package]]
name = "tungstenite"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eadc29d668c91fcc564941132e17b28a7ceb2f3ebf0b9dae3e03fd7a6748eb0d"
dependencies = [
"bytes",
"data-encoding",
"http 1.3.1",
"httparse",
"log",
"rand 0.9.2",
"sha1",
"thiserror 2.0.12",
"utf-8",
]
[[package]]
name = "typeid"
version = "1.0.3"
@@ -8644,7 +8563,7 @@ dependencies = [
"serde_json",
"serde_urlencoded",
"tokio",
"tokio-tungstenite 0.21.0",
"tokio-tungstenite",
"tokio-util",
"tower-service",
"tracing",

View File

@@ -1,6 +1,12 @@
use super::CmdResult;
use crate::{config::*, core::*, feat, ipc::IpcManager, process::AsyncHandler, wrap_err};
use crate::{
config::*, core::*, feat, ipc::IpcManager, process::AsyncHandler,
state::proxy::ProxyRequestCache, wrap_err,
};
use serde_yaml::Mapping;
use std::time::Duration;
const CONFIG_REFRESH_INTERVAL: Duration = Duration::from_secs(60);
/// 复制Clash环境变量
#[tauri::command]
@@ -66,19 +72,31 @@ pub async fn change_clash_core(clash_core: String) -> CmdResult<Option<String>>
/// 启动核心
#[tauri::command]
pub async fn start_core() -> CmdResult {
wrap_err!(CoreManager::global().start_core().await)
let result = wrap_err!(CoreManager::global().start_core().await);
if result.is_ok() {
handle::Handle::refresh_clash();
}
result
}
/// 关闭核心
#[tauri::command]
pub async fn stop_core() -> CmdResult {
wrap_err!(CoreManager::global().stop_core().await)
let result = wrap_err!(CoreManager::global().stop_core().await);
if result.is_ok() {
handle::Handle::refresh_clash();
}
result
}
/// 重启核心
#[tauri::command]
pub async fn restart_core() -> CmdResult {
wrap_err!(CoreManager::global().restart_core().await)
let result = wrap_err!(CoreManager::global().restart_core().await);
if result.is_ok() {
handle::Handle::refresh_clash();
}
result
}
/// 获取代理延迟
@@ -277,7 +295,24 @@ pub async fn get_clash_version() -> CmdResult<serde_json::Value> {
/// 获取Clash配置
#[tauri::command]
pub async fn get_clash_config() -> CmdResult<serde_json::Value> {
wrap_err!(IpcManager::global().get_config().await)
let manager = IpcManager::global();
let cache = ProxyRequestCache::global();
let key = ProxyRequestCache::make_key("clash_config", "default");
let value = cache
.get_or_fetch(key, CONFIG_REFRESH_INTERVAL, || async {
manager.get_config().await.expect("fetch failed")
})
.await;
Ok((*value).clone())
}
/// 强制刷新Clash配置缓存
#[tauri::command]
pub async fn force_refresh_clash_config() -> CmdResult<serde_json::Value> {
let cache = ProxyRequestCache::global();
let key = ProxyRequestCache::make_key("clash_config", "default");
cache.map.remove(&key);
get_clash_config().await
}
/// 更新地理数据

View File

@@ -61,14 +61,20 @@ pub async fn save_profile_file(index: String, file_data: Option<String>) -> CmdR
"[cmd配置save] merge文件语法验证通过"
);
// 成功后尝试更新整体配置
if let Err(e) = CoreManager::global().update_config().await {
logging!(
warn,
Type::Config,
true,
"[cmd配置save] 更新整体配置时发生错误: {}",
e
);
match CoreManager::global().update_config().await {
Ok(_) => {
// 配置更新成功,刷新前端
handle::Handle::refresh_clash();
}
Err(e) => {
logging!(
warn,
Type::Config,
true,
"[cmd配置save] 更新整体配置时发生错误: {}",
e
);
}
}
return Ok(());
}

View File

@@ -274,6 +274,7 @@ pub fn run() {
cmd::validate_dns_config,
cmd::get_clash_version,
cmd::get_clash_config,
cmd::force_refresh_clash_config,
cmd::update_geo_data,
cmd::upgrade_clash_core,
cmd::get_clash_rules,