prvng_platform/crates/ncl-sync/src/watcher.rs

48 lines
1.5 KiB
Rust
Raw Normal View History

use anyhow::Result;
use notify::{Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
use std::path::{Path, PathBuf};
use tokio::sync::mpsc;
use tracing::debug;
pub enum WatchEvent {
Changed(PathBuf),
Removed(PathBuf),
}
/// Start a single notify watcher for one or more paths. All events route to the same channel.
pub fn start_many(paths: &[PathBuf]) -> Result<(RecommendedWatcher, mpsc::Receiver<WatchEvent>)> {
let (tx, rx) = mpsc::channel::<WatchEvent>(128);
let mut watcher = notify::recommended_watcher(move |res: notify::Result<Event>| {
let Ok(event) = res else { return };
let kind = event.kind;
for path in event.paths {
if path.extension().is_none_or(|e| e != "ncl") {
continue;
}
let evt = match &kind {
EventKind::Remove(_) => WatchEvent::Removed(path),
_ => WatchEvent::Changed(path),
};
let _ = tx.try_send(evt);
}
})?;
for p in paths {
if p.exists() {
watcher.watch(p, RecursiveMode::Recursive)?;
debug!("watching: {}", p.display());
} else {
debug!("skip watch (not found): {}", p.display());
}
}
Ok((watcher, rx))
}
/// Convenience wrapper for single-path watching (preserves old API for tests/tools).
#[allow(dead_code)]
pub fn start(watch_path: &Path) -> Result<(RecommendedWatcher, mpsc::Receiver<WatchEvent>)> {
start_many(&[watch_path.to_path_buf()])
}