Watch Files with Debounced Events
Receive filesystem notifications through notify, keep the watcher alive with a handle, and collapse rapid events into one batch.
Code
use notify::{Config, Event, RecommendedWatcher, RecursiveMode, Watcher};
use std::path::Path;
use std::sync::mpsc::{channel, Receiver};
use std::time::{Duration, Instant};
struct WatchHandle {
_watcher: RecommendedWatcher,
events: Receiver<Event>,
}
fn watch(path: &Path) -> notify::Result<WatchHandle> {
let (sender, events) = channel();
let mut watcher = RecommendedWatcher::new(
move |result: notify::Result<Event>| {
if let Ok(event) = result {
let _ = sender.send(event);
}
},
Config::default(),
)?;
watcher.watch(path, RecursiveMode::Recursive)?;
Ok(WatchHandle {
_watcher: watcher,
events,
})
}
fn main() -> notify::Result<()> {
let handle = watch(Path::new("."))?;
let started = Instant::now();
let mut last = Instant::now();
let mut pending = false;
let mut count = 0;
loop {
match handle.events.recv_timeout(Duration::from_millis(200)) {
Ok(event) => {
last = Instant::now();
pending = true;
count += 1;
println!("raw event: {:?}", event.kind);
}
Err(_) if pending && last.elapsed() >= Duration::from_millis(500) => {
println!("debounced batch of {count} events ready");
break;
}
Err(_) if !pending && started.elapsed() >= Duration::from_secs(2) => {
println!("no changes observed");
break;
}
Err(_) => {}
}
}
Ok(())
}
Report a problem with this exampleOpens a pre-filled issue on GitHub.