From 90ad3e9e1b763aae2790ffc4503dfa28973b86bb Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Mon, 23 Jun 2025 17:13:58 +0200 Subject: [PATCH] improv(cosmic-config): use notifier debouncer on inotify watchers --- cosmic-config/Cargo.toml | 1 + cosmic-config/src/lib.rs | 20 +++++++++++--------- cosmic-config/src/subscription.rs | 3 ++- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/cosmic-config/Cargo.toml b/cosmic-config/Cargo.toml index a79237c8..424ea262 100644 --- a/cosmic-config/Cargo.toml +++ b/cosmic-config/Cargo.toml @@ -26,6 +26,7 @@ dirs.workspace = true tokio = { version = "1.44", optional = true, features = ["time"] } async-std = { version = "1.13", optional = true } tracing = "0.1" +notify-debouncer-full = "0.5.0" [target.'cfg(unix)'.dependencies] xdg = "2.5" diff --git a/cosmic-config/src/lib.rs b/cosmic-config/src/lib.rs index beab95fb..1f0c8846 100644 --- a/cosmic-config/src/lib.rs +++ b/cosmic-config/src/lib.rs @@ -1,15 +1,15 @@ //! Integrations for cosmic-config — the cosmic configuration system. use notify::{ - event::{EventKind, ModifyKind}, - Watcher, + event::{EventKind, ModifyKind}, RecommendedWatcher, Watcher }; +use notify_debouncer_full::{DebouncedEvent, Debouncer, RecommendedCache}; use serde::{de::DeserializeOwned, Serialize}; use std::{ fmt, fs, io::Write, path::{Path, PathBuf}, - sync::Mutex, + sync::Mutex, time::Duration, }; #[cfg(feature = "subscription")] @@ -244,7 +244,7 @@ impl Config { // This may end up being an mpsc channel instead of a function // See EventHandler in the notify crate: https://docs.rs/notify/latest/notify/trait.EventHandler.html // Having a callback allows for any application abstraction to be used - pub fn watch(&self, f: F) -> Result + pub fn watch(&self, f: F) -> Result, Error> // Argument is an array of all keys that changed in that specific transaction //TODO: simplify F requirements where @@ -256,10 +256,11 @@ impl Config { }; let user_path_clone = user_path.clone(); let mut watcher = - notify::recommended_watcher(move |event_res: Result| { - match &event_res { - Ok(event) => { - match &event.kind { + notify_debouncer_full::new_debouncer(Duration::from_secs(1), None, move |event_res: Result, Vec>| { + match event_res { + Ok(events) => { + for event in events { + match &event.event.kind { EventKind::Access(_) | EventKind::Modify(ModifyKind::Metadata(_)) => { // Data not mutated return; @@ -287,8 +288,9 @@ impl Config { if !keys.is_empty() { f(&watch_config, &keys); } + } } - Err(_err) => { + Err(_errs) => { //TODO: handle errors } } diff --git a/cosmic-config/src/subscription.rs b/cosmic-config/src/subscription.rs index 64255954..591b85ea 100644 --- a/cosmic-config/src/subscription.rs +++ b/cosmic-config/src/subscription.rs @@ -1,13 +1,14 @@ use iced_futures::futures::{SinkExt, Stream}; use iced_futures::{futures::channel::mpsc, stream}; use notify::RecommendedWatcher; +use notify_debouncer_full::{Debouncer, RecommendedCache}; use std::{borrow::Cow, hash::Hash}; use crate::{Config, CosmicConfigEntry}; pub enum ConfigState { Init(Cow<'static, str>, u64, bool), - Waiting(T, RecommendedWatcher, mpsc::Receiver>, Config), + Waiting(T, Debouncer, mpsc::Receiver>, Config), Failed, }