From 5e9d3520111244cded11bca005c51dbf85e68d5e Mon Sep 17 00:00:00 2001 From: Beast Date: Thu, 26 Mar 2026 16:15:13 +0800 Subject: [PATCH 1/2] hot_fix: looping hot-reload flag config --- src/services/wallet_feature_flags_service.rs | 76 ++++++++++++++++---- 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/src/services/wallet_feature_flags_service.rs b/src/services/wallet_feature_flags_service.rs index 1502b33..99b2530 100644 --- a/src/services/wallet_feature_flags_service.rs +++ b/src/services/wallet_feature_flags_service.rs @@ -1,10 +1,11 @@ -use notify::{Config as NotifyConfig, RecommendedWatcher, RecursiveMode, Watcher}; +use notify::{event::ModifyKind, Config as NotifyConfig, EventKind, RecommendedWatcher, RecursiveMode, Watcher}; use serde_json::Value; use std::{ path::{Path, PathBuf}, sync::{Arc, RwLock}, + time::Duration, }; -use tokio::{sync::mpsc, task::JoinHandle}; +use tokio::{sync::mpsc, task::JoinHandle, time}; #[derive(Debug, thiserror::Error)] pub enum WalletFeatureFlagsError { @@ -28,6 +29,16 @@ pub struct WalletFeatureFlagsService { } impl WalletFeatureFlagsService { + fn is_reload_event_kind(kind: &EventKind) -> bool { + match kind { + EventKind::Create(_) | EventKind::Modify(ModifyKind::Name(_)) => true, + EventKind::Modify(modify_kind) => { + !matches!(modify_kind, ModifyKind::Metadata(_) | ModifyKind::Other) + } + _ => false, + } + } + pub fn new(file_path: impl Into) -> Result { let file_path = file_path.into(); @@ -50,23 +61,63 @@ impl WalletFeatureFlagsService { watcher.watch(parent_dir, RecursiveMode::NonRecursive)?; let wallet_feature_flags_clone = wallet_feature_flags.clone(); + let watched_file_name = file_path.file_name().map(|n| n.to_os_string()); + let debounce_duration = Duration::from_millis(250); let watch_task = tokio::spawn(async move { - while let Some(result) = rx.recv().await { - match result { - Ok(event) => { - // This ensures Create, Rename, and Modify events triggered by atomic saves are caught. - let should_reload = event.paths.iter().any(|p| p.file_name() == file_path.file_name()); - - if !should_reload { - continue; + // Atomic file saves commonly emit bursts of events (Create/Rename/Modify). + // We debounce these bursts to avoid reloading (and logging) repeatedly. + let mut reload_pending = false; + let reload_sleep = time::sleep(debounce_duration); + tokio::pin!(reload_sleep); + + loop { + tokio::select! { + biased; + maybe_result = rx.recv() => { + let Some(result) = maybe_result else { + break; + }; + + match result { + Ok(event) => { + if !Self::is_reload_event_kind(&event.kind) { + continue; + } + + let should_reload = watched_file_name + .as_deref() + .map(|name| event.paths.iter().any(|p| p.file_name() == Some(name))) + .unwrap_or(false); + + if !should_reload { + continue; + } + + reload_pending = true; + reload_sleep.as_mut().reset(time::Instant::now() + debounce_duration); + } + Err(err) => { + tracing::error!("Wallet feature flags watcher error: {}", err); + } } + } + _ = &mut reload_sleep, if reload_pending => { + reload_pending = false; match Self::read_flags_from_file_async(&file_path).await { Ok(updated_flags) => { if let Ok(mut write_guard) = wallet_feature_flags_clone.write() { + if *write_guard == updated_flags { + // Avoid noisy log spam when events are emitted without content changes. + continue; + } + *write_guard = updated_flags; - tracing::info!("Wallet feature flags reloaded from {}", file_path.display()); + tracing::info!( + "Wallet feature flags reloaded from {}", + file_path.display() + ); } } Err(err) => { @@ -78,9 +129,6 @@ impl WalletFeatureFlagsService { } } } - Err(err) => { - tracing::error!("Wallet feature flags watcher error: {}", err); - } } } }); From 753ab1373224f3e3c9eb2bba3b0681121d51e017 Mon Sep 17 00:00:00 2001 From: Beast Date: Thu, 26 Mar 2026 16:20:28 +0800 Subject: [PATCH 2/2] chore: formatting --- src/services/wallet_feature_flags_service.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/services/wallet_feature_flags_service.rs b/src/services/wallet_feature_flags_service.rs index 99b2530..095d7ac 100644 --- a/src/services/wallet_feature_flags_service.rs +++ b/src/services/wallet_feature_flags_service.rs @@ -32,9 +32,7 @@ impl WalletFeatureFlagsService { fn is_reload_event_kind(kind: &EventKind) -> bool { match kind { EventKind::Create(_) | EventKind::Modify(ModifyKind::Name(_)) => true, - EventKind::Modify(modify_kind) => { - !matches!(modify_kind, ModifyKind::Metadata(_) | ModifyKind::Other) - } + EventKind::Modify(modify_kind) => !matches!(modify_kind, ModifyKind::Metadata(_) | ModifyKind::Other), _ => false, } }