diff --git a/UPDATELOG.md b/UPDATELOG.md index 001c1f12b..65e87d49a 100644 --- a/UPDATELOG.md +++ b/UPDATELOG.md @@ -5,6 +5,7 @@ - **核心架构升级**:与内核 Mihomo 采用 IPC 通信,不再依赖 Restful API 通信,提升性能和稳定性 - **流量监控系统重构**:前端实现全新的增强流量监控系统,支持数据压缩、采样和智能缓存 - **数据验证机制**:引入类型安全的数据验证器,确保 API 响应数据的一致性和可靠性 +- **配置缓存架构**:实现智能配置缓存系统,支持后端数据缓存和强制刷新机制 ### ✨ 新增功能 @@ -14,6 +15,8 @@ - 引用计数管理器智能收集数据 - 新增流量监控诊断工具与错误边界组件 - 多版本画布流量图表,丰富可视化选项 +- 新增强制刷新 Clash 配置/节点缓存功能,提升更新响应速度 +- 增加代理请求缓存机制,减少重复 API 调用 ### 🚀 性能优化 @@ -22,6 +25,8 @@ - 引用计数机制避免不必要的数据收集,提升整体性能 - 优化流量图表渲染性能,支持大数据量展示 - 改进前端数据获取和缓存策略 +- 实现配置/节点缓存 TTL 机制,减少不必要的配置/节点请求 +- 改进 Clash 配置/节点刷新间隔,从5秒优化到60秒,减少系统资源消耗 ### 🐞 修复问题 @@ -30,6 +35,8 @@ - 增强代理更新的错误处理机制 - 修复 JSON 解析错误处理 - 优化调试日志输出,减少噪音 +- 修复配置修改后前端缓存不同步问题 +- 改进核心启动/停止/重启后的状态刷新机制 ### 🔧 技术改进 diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 3940b08b2..06df24402 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -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", diff --git a/src-tauri/src/cmd/clash.rs b/src-tauri/src/cmd/clash.rs index 499aeec30..ce7f79fd6 100644 --- a/src-tauri/src/cmd/clash.rs +++ b/src-tauri/src/cmd/clash.rs @@ -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> /// 启动核心 #[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 { /// 获取Clash配置 #[tauri::command] pub async fn get_clash_config() -> CmdResult { - 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 { + let cache = ProxyRequestCache::global(); + let key = ProxyRequestCache::make_key("clash_config", "default"); + cache.map.remove(&key); + get_clash_config().await } /// 更新地理数据 diff --git a/src-tauri/src/cmd/save_profile.rs b/src-tauri/src/cmd/save_profile.rs index 50fa1a8ea..9d9bdfa01 100644 --- a/src-tauri/src/cmd/save_profile.rs +++ b/src-tauri/src/cmd/save_profile.rs @@ -61,14 +61,20 @@ pub async fn save_profile_file(index: String, file_data: Option) -> 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(()); } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index d71526191..213795d43 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -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, diff --git a/src/components/setting/mods/clash-core-viewer.tsx b/src/components/setting/mods/clash-core-viewer.tsx index 1175d8132..1b44236f5 100644 --- a/src/components/setting/mods/clash-core-viewer.tsx +++ b/src/components/setting/mods/clash-core-viewer.tsx @@ -18,7 +18,11 @@ import { ListItemText, } from "@mui/material"; import { changeClashCore, restartCore } from "@/services/cmds"; -import { closeAllConnections, upgradeCore } from "@/services/cmds"; +import { + closeAllConnections, + upgradeCore, + forceRefreshClashConfig, +} from "@/services/cmds"; import { showNotice } from "@/services/noticeService"; const VALID_CORE = [ @@ -58,7 +62,9 @@ export const ClashCoreViewer = forwardRef((props, ref) => { } mutateVerge(); - setTimeout(() => { + setTimeout(async () => { + // 核心切换后强制刷新配置缓存 + await forceRefreshClashConfig(); mutate("getClashConfig"); mutate("getVersion"); setChangingCore(null); diff --git a/src/hooks/use-clash.ts b/src/hooks/use-clash.ts index b9b9cd3f9..cffce52a7 100644 --- a/src/hooks/use-clash.ts +++ b/src/hooks/use-clash.ts @@ -5,6 +5,7 @@ import { getClashInfo, patchClashConfig, getRuntimeConfig, + forceRefreshClashConfig, } from "@/services/cmds"; export const useClash = () => { @@ -121,6 +122,8 @@ export const useClashInfo = () => { await patchClashConfig(patch); mutateInfo(); + // 配置修改后强制刷新缓存 + await forceRefreshClashConfig(); mutate("getClashConfig"); // IPC调用不需要刷新axios实例 }; diff --git a/src/pages/_layout.tsx b/src/pages/_layout.tsx index 50657fc2d..aca5f26b9 100644 --- a/src/pages/_layout.tsx +++ b/src/pages/_layout.tsx @@ -9,6 +9,7 @@ import { List, Paper, ThemeProvider, SvgIcon } from "@mui/material"; import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow"; import { routers } from "./_routers"; import { getAxios } from "@/services/api"; +import { forceRefreshClashConfig } from "@/services/cmds"; import { useVerge } from "@/hooks/use-verge"; import LogoSvg from "@/assets/image/logo.svg?react"; import iconLight from "@/assets/image/icon_light.svg?react"; @@ -192,6 +193,8 @@ const Layout = () => { const listeners = [ addListener("verge://refresh-clash-config", async () => { await getAxios(true); + // 后端配置变更事件触发,强制刷新配置缓存 + await forceRefreshClashConfig(); mutate("getProxies"); mutate("getVersion"); mutate("getClashConfig"); diff --git a/src/providers/app-data-provider.tsx b/src/providers/app-data-provider.tsx index dd1958849..fca06f0c7 100644 --- a/src/providers/app-data-provider.tsx +++ b/src/providers/app-data-provider.tsx @@ -185,7 +185,7 @@ export const AppDataProvider = ({ "getClashConfig", getClashConfig, { - refreshInterval: 5000, + refreshInterval: 60000, // 60秒刷新间隔,减少频繁请求 revalidateOnFocus: false, suspense: false, errorRetryCount: 3, diff --git a/src/services/cmds.ts b/src/services/cmds.ts index 80bf0221c..b3a5b5940 100644 --- a/src/services/cmds.ts +++ b/src/services/cmds.ts @@ -107,6 +107,10 @@ export async function getClashConfig() { return invoke("get_clash_config"); } +export async function forceRefreshClashConfig() { + return invoke("force_refresh_clash_config"); +} + export async function updateGeoData() { return invoke("update_geo_data"); }