use std::path::PathBuf;
use std::time::Duration;
use notify::RecursiveMode;
use notify_debouncer_full::{Debouncer, NoCache};
use tokio::sync::mpsc::{UnboundedReceiver, unbounded_channel};
use super::{WatchBatch, Watcher};
pub struct NotifyWatcher {
batches: UnboundedReceiver<WatchBatch>,
_debouncer: Debouncer<notify::RecommendedWatcher, NoCache>,
}
impl NotifyWatcher {
pub const DEBOUNCE: Duration = Duration::from_millis(200);
pub fn new(roots: &[PathBuf]) -> Result<Self, notify::Error> {
let (sender, batches) = unbounded_channel();
let mut debouncer = notify_debouncer_full::new_debouncer_opt(
Self::DEBOUNCE,
None,
move |result: notify_debouncer_full::DebounceEventResult| {
let batch = match result {
Ok(events) => WatchBatch::Paths(
events
.into_iter()
.flat_map(|event| event.paths.clone())
.collect(),
),
Err(_) => WatchBatch::Rescan,
};
let _ = sender.send(batch);
},
NoCache::new(),
notify::Config::default(),
)?;
for root in roots {
debouncer.watch(root, RecursiveMode::Recursive)?;
}
Ok(Self {
batches,
_debouncer: debouncer,
})
}
}
#[async_trait::async_trait]
impl Watcher for NotifyWatcher {
async fn next_batch(&mut self) -> Option<WatchBatch> {
self.batches.recv().await
}
}