use std::path::PathBuf;
use std::time::Duration;
use notify::{RecommendedWatcher, RecursiveMode, Watcher};
use tokio::sync::mpsc;
#[derive(Debug, Clone)]
pub struct WatchEvent {
pub changed: bool,
}
pub struct DebouncedWatcher {
_watcher: RecommendedWatcher,
}
impl DebouncedWatcher {
pub fn start(
path: PathBuf,
debounce_duration: Duration,
sender: mpsc::Sender<WatchEvent>,
) -> notify::Result<Self> {
let (raw_tx, mut raw_rx) = mpsc::channel::<()>(64);
let watcher_tx = raw_tx.clone();
let mut watcher =
notify::recommended_watcher(move |res: notify::Result<notify::Event>| {
if res.is_ok() {
let _ = watcher_tx.try_send(());
}
})?;
watcher.watch(&path, RecursiveMode::Recursive)?;
tokio::spawn(async move {
loop {
if raw_rx.recv().await.is_none() {
break;
}
loop {
match tokio::time::timeout(debounce_duration, raw_rx.recv()).await {
Ok(Some(())) => continue,
Ok(None) => {
let _ = sender.send(WatchEvent { changed: true }).await;
return;
}
Err(_elapsed) => break,
}
}
if sender.send(WatchEvent { changed: true }).await.is_err() {
break;
}
}
});
Ok(Self { _watcher: watcher })
}
}