From 203935b96a3873a1efabc5a3a5fa9cb5475c55be Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Sat, 31 Jan 2026 16:18:27 +0800 Subject: [PATCH] feat(limiter): integrate Limiter into tray and window management for rate limiting --- Cargo.lock | 70 +-------------------------- Cargo.toml | 4 +- crates/clash-verge-limiter/src/lib.rs | 4 +- src-tauri/Cargo.toml | 2 +- src-tauri/src/core/tray/mod.rs | 17 +++---- src-tauri/src/utils/window_manager.rs | 19 +++----- 6 files changed, 22 insertions(+), 94 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5bbcfe6df..4f4c730ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1122,6 +1122,7 @@ dependencies = [ "chrono", "clash-verge-draft", "clash-verge-i18n", + "clash-verge-limiter", "clash-verge-logging", "clash-verge-signal", "clash_verge_logger", @@ -1137,7 +1138,6 @@ dependencies = [ "futures", "gethostname", "getrandom 0.3.4", - "governor", "log", "nanoid", "network-interface", @@ -2644,12 +2644,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" -[[package]] -name = "futures-timer" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" - [[package]] name = "futures-util" version = "0.3.31" @@ -2982,29 +2976,6 @@ dependencies = [ "system-deps", ] -[[package]] -name = "governor" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9efcab3c1958580ff1f25a2a41be1668f7603d849bb63af523b208a3cc1223b8" -dependencies = [ - "cfg-if", - "dashmap 6.1.0", - "futures-sink", - "futures-timer", - "futures-util", - "getrandom 0.3.4", - "hashbrown 0.16.1", - "nonzero_ext", - "parking_lot", - "portable-atomic", - "quanta", - "rand 0.9.2", - "smallvec", - "spinning_top", - "web-time", -] - [[package]] name = "gtk" version = "0.18.2" @@ -4412,12 +4383,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "nonzero_ext" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" - [[package]] name = "normpath" version = "1.5.0" @@ -5584,21 +5549,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "quanta" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7" -dependencies = [ - "crossbeam-utils", - "libc", - "once_cell", - "raw-cpuid", - "wasi 0.11.1+wasi-snapshot-preview1", - "web-sys", - "winapi", -] - [[package]] name = "quick-error" version = "2.0.1" @@ -5813,15 +5763,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "raw-cpuid" -version = "11.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" -dependencies = [ - "bitflags 2.10.0", -] - [[package]] name = "raw-window-handle" version = "0.6.2" @@ -7024,15 +6965,6 @@ dependencies = [ "system-deps", ] -[[package]] -name = "spinning_top" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" -dependencies = [ - "lock_api", -] - [[package]] name = "stable_deref_trait" version = "1.2.1" diff --git a/Cargo.toml b/Cargo.toml index 2164a0c3e..a5c87e9a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,8 @@ members = [ "crates/clash-verge-logging", "crates/clash-verge-signal", "crates/tauri-plugin-clash-verge-sysinfo", - "crates/clash-verge-i18n", "crates/clash-verge-limiter", + "crates/clash-verge-i18n", + "crates/clash-verge-limiter", ] resolver = "2" @@ -44,6 +45,7 @@ clash-verge-draft = { path = "crates/clash-verge-draft" } clash-verge-logging = { path = "crates/clash-verge-logging" } clash-verge-signal = { path = "crates/clash-verge-signal" } clash-verge-i18n = { path = "crates/clash-verge-i18n" } +clash-verge-limiter = { path = "crates/clash-verge-limiter" } tauri-plugin-clash-verge-sysinfo = { path = "crates/tauri-plugin-clash-verge-sysinfo" } tauri = { version = "2.9.5" } diff --git a/crates/clash-verge-limiter/src/lib.rs b/crates/clash-verge-limiter/src/lib.rs index a2464c9fb..263771f08 100644 --- a/crates/clash-verge-limiter/src/lib.rs +++ b/crates/clash-verge-limiter/src/lib.rs @@ -2,6 +2,8 @@ use std::sync::Arc; use std::sync::atomic::{AtomicU64, Ordering}; use std::time::{Duration, SystemTime, UNIX_EPOCH}; +pub type SystemLimiter = Limiter; + pub trait Clock: Send + Sync { fn now_ms(&self) -> u64; } @@ -36,7 +38,7 @@ pub struct Limiter { } impl Limiter { - pub fn new(period: Duration, clock: C) -> Self { + pub const fn new(period: Duration, clock: C) -> Self { Self { last_run_ms: AtomicU64::new(0), period_ms: period.as_millis() as u64, diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 5a71935bd..d11dae555 100755 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -35,6 +35,7 @@ clash-verge-draft = { workspace = true } clash-verge-logging = { workspace = true } clash-verge-signal = { workspace = true } clash-verge-i18n = { workspace = true } +clash-verge-limiter = { workspace = true } tauri-plugin-clash-verge-sysinfo = { workspace = true } tauri-plugin-clipboard-manager = { workspace = true } tauri = { workspace = true, features = [ @@ -105,7 +106,6 @@ arc-swap = "1.8.0" rust_iso3166 = "0.1.14" # Use the git repo until the next release after v2.0.0. dark-light = { git = "https://github.com/rust-dark-light/dark-light" } -governor = "0.10.4" [target.'cfg(windows)'.dependencies] deelevate = { workspace = true } diff --git a/src-tauri/src/core/tray/mod.rs b/src-tauri/src/core/tray/mod.rs index aa8fbed00..c27a8f26a 100644 --- a/src-tauri/src/core/tray/mod.rs +++ b/src-tauri/src/core/tray/mod.rs @@ -9,7 +9,7 @@ use crate::{ Type, cmd, config::Config, feat, logging, module::lightweight::is_in_lightweight_mode, utils::dirs::find_target_icons, }; -use governor::{DefaultDirectRateLimiter, Quota, RateLimiter}; +use clash_verge_limiter::{Limiter, SystemClock, SystemLimiter}; use tauri::tray::TrayIconBuilder; use tauri_plugin_clash_verge_sysinfo::is_current_app_handle_admin; use tauri_plugin_mihomo::models::Proxies; @@ -19,7 +19,6 @@ use super::handle; use anyhow::Result; use smartstring::alias::String; use std::collections::HashMap; -use std::num::NonZeroU32; use std::time::Duration; use tauri::{ AppHandle, Wry, @@ -39,7 +38,7 @@ const TRAY_CLICK_DEBOUNCE_MS: u64 = 1_275; struct TrayState {} pub struct Tray { - limiter: DefaultDirectRateLimiter, + limiter: SystemLimiter, } impl TrayState { @@ -136,11 +135,7 @@ impl Default for Tray { #[allow(clippy::unwrap_used)] fn default() -> Self { Self { - limiter: RateLimiter::direct( - Quota::with_period(Duration::from_millis(TRAY_CLICK_DEBOUNCE_MS)) - .unwrap() - .allow_burst(NonZeroU32::new(1).unwrap()), - ), + limiter: Limiter::new(Duration::from_millis(TRAY_CLICK_DEBOUNCE_MS), SystemClock), } } } @@ -462,11 +457,11 @@ impl Tray { } fn should_handle_tray_click(&self) -> bool { - let res = self.limiter.check().is_ok(); - if !res { + let allow = self.limiter.check(); + if !allow { logging!(debug, Type::Tray, "tray click rate limited"); } - res + allow } } diff --git a/src-tauri/src/utils/window_manager.rs b/src-tauri/src/utils/window_manager.rs index aa9081f62..00e408a72 100644 --- a/src-tauri/src/utils/window_manager.rs +++ b/src-tauri/src/utils/window_manager.rs @@ -1,8 +1,7 @@ use crate::{core::handle, utils::resolve::window::build_new_window}; +use clash_verge_limiter::Limiter; use clash_verge_logging::{Type, logging}; -use governor::{DefaultDirectRateLimiter, Quota, RateLimiter}; use once_cell::sync::Lazy; -use std::num::NonZeroU32; use std::pin::Pin; use std::time::Duration; use tauri::{Manager as _, WebviewWindow, Wry}; @@ -41,21 +40,19 @@ pub enum WindowState { // 窗口操作防抖机制 const WINDOW_OPERATION_DEBOUNCE_MS: u64 = 1_275; -static WINDOW_OPERATION_LIMITER: Lazy = Lazy::new(|| { - #[allow(clippy::unwrap_used)] - RateLimiter::direct( - Quota::with_period(Duration::from_millis(WINDOW_OPERATION_DEBOUNCE_MS)) - .unwrap() - .allow_burst(NonZeroU32::new(1).unwrap()), +static WINDOW_OPERATION_LIMITER: Lazy = Lazy::new(|| { + Limiter::new( + Duration::from_millis(WINDOW_OPERATION_DEBOUNCE_MS), + clash_verge_limiter::SystemClock, ) }); fn should_handle_window_operation() -> bool { - let res = WINDOW_OPERATION_LIMITER.check().is_ok(); - if !res { + let allow = WINDOW_OPERATION_LIMITER.check(); + if !allow { logging!(debug, Type::Window, "window operation rate limited"); } - res + allow } /// 统一的窗口管理器