kinetic_config/
watcher.rs1use notify::{Event, RecommendedWatcher, RecursiveMode, Watcher};
4use snafu::Snafu;
5use std::path::{Path, PathBuf};
6use tokio::sync::mpsc;
7use tracing::{error, info};
8
9#[derive(Debug, Snafu)]
10pub enum Error {
11 #[snafu(display("Failed to initialize file watcher: {}", source))]
12 WatcherInit { source: notify::Error },
13
14 #[snafu(display("Failed to watch path {}: {}", path.display(), source))]
15 WatchPath {
16 path: PathBuf,
17 source: notify::Error,
18 },
19}
20
21pub type Result<T, E = Error> = std::result::Result<T, E>;
22
23pub struct ConfigWatcher {
25 _watcher: RecommendedWatcher,
26 pub rx: mpsc::Receiver<()>,
27}
28
29impl ConfigWatcher {
30 pub fn new(path: impl AsRef<Path>) -> Result<Self> {
34 let path = path.as_ref().to_path_buf();
35 let (tx, rx) = mpsc::channel(1);
36
37 let mut watcher =
38 notify::recommended_watcher(move |res: std::result::Result<Event, notify::Error>| {
39 match res {
40 Ok(event) => {
41 if event.kind.is_modify()
44 || event.kind.is_create()
45 || event.kind.is_access()
46 {
47 info!("Configuration file change detected: {:?}", event.kind);
48 let _ = tx.try_send(());
51 }
52 }
53 Err(e) => error!("Watch error: {:?}", e),
54 }
55 })
56 .map_err(|e| Error::WatcherInit { source: e })?;
57
58 watcher
59 .watch(&path, RecursiveMode::NonRecursive)
60 .map_err(|e| Error::WatchPath {
61 path: path.clone(),
62 source: e,
63 })?;
64
65 info!("Started watching config file: {}", path.display());
66
67 Ok(Self {
68 _watcher: watcher,
69 rx,
70 })
71 }
72}