greentic_ext_runtime/
watcher.rs1use std::path::PathBuf;
2use std::sync::mpsc;
3use std::time::Duration;
4
5use notify::RecommendedWatcher;
6use notify::RecursiveMode;
7use notify_debouncer_full::{DebounceEventResult, Debouncer, RecommendedCache, new_debouncer};
8
9use crate::error::RuntimeError;
10
11#[derive(Debug, Clone)]
12pub enum FsEvent {
13 Added(PathBuf),
14 Modified(PathBuf),
15 Removed(PathBuf),
16}
17
18pub struct WatchHandle {
20 _debouncer: Debouncer<RecommendedWatcher, RecommendedCache>,
21}
22
23pub fn watch(paths: &[PathBuf]) -> Result<(mpsc::Receiver<FsEvent>, WatchHandle), RuntimeError> {
27 let (tx, rx) = mpsc::channel();
28 let mut debouncer = new_debouncer(
29 Duration::from_millis(500),
30 None,
31 move |res: DebounceEventResult| {
32 if let Ok(events) = res {
33 for ev in events {
34 for p in &ev.event.paths {
35 let out = match ev.event.kind {
36 notify::EventKind::Create(_) => FsEvent::Added(p.clone()),
37 notify::EventKind::Modify(_) => FsEvent::Modified(p.clone()),
38 notify::EventKind::Remove(_) => FsEvent::Removed(p.clone()),
39 _ => continue,
40 };
41 let _ = tx.send(out);
42 }
43 }
44 }
45 },
46 )
47 .map_err(|e| RuntimeError::Watcher(e.to_string()))?;
48
49 for p in paths {
50 if p.exists() {
51 debouncer
52 .watch(p, RecursiveMode::Recursive)
53 .map_err(|e| RuntimeError::Watcher(e.to_string()))?;
54 }
55 }
56 Ok((
57 rx,
58 WatchHandle {
59 _debouncer: debouncer,
60 },
61 ))
62}