feat(limiter): integrate Limiter into tray and window management for rate limiting

This commit is contained in:
Tunglies
2026-01-31 16:39:11 +08:00
parent feec05576d
commit 203935b96a
6 changed files with 22 additions and 94 deletions
Generated
+1 -69
View File
@@ -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"
+3 -1
View File
@@ -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" }
+3 -1
View File
@@ -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<SystemClock>;
pub trait Clock: Send + Sync {
fn now_ms(&self) -> u64;
}
@@ -36,7 +38,7 @@ pub struct Limiter<C: Clock = SystemClock> {
}
impl<C: Clock> Limiter<C> {
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,
+1 -1
View File
@@ -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 }
+6 -11
View File
@@ -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
}
}
+8 -11
View File
@@ -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<DefaultDirectRateLimiter> = 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<Limiter> = 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
}
/// 统一的窗口管理器