// use actix::prelude::*; use actix::Recipient; use anyhow::{Context, Result}; use notify::event::ModifyKind; use notify::Watcher; use tracing::error; use tracing::info; use std::path::PathBuf; use std::time::Duration; #[derive(Debug, Message)] #[rtype(result = "()")] pub struct FileUpdated; #[derive(Debug, thiserror::Error)] pub enum Error { #[error("io")] Io(#[from] std::io::Error), } pub async fn watch_file(path: PathBuf, recipient: Recipient) -> Result<()> { let (tx, rx) = std::sync::mpsc::channel(); let mut handler = notify::recommended_watcher(tx).context("file watcher")?; handler .watch(&path, notify::RecursiveMode::NonRecursive) .with_context(|| format!("Watch file: {path:?}"))?; info!("Watching: {:?}", path); async move { loop { for result in rx.try_iter() { match result { Ok(event) => match event.kind { notify::EventKind::Modify(ModifyKind::Data(_)) => { tracing::info!("File modified"); recipient.do_send(FileUpdated); break; } notify::EventKind::Modify(_) | notify::EventKind::Create(_) | notify::EventKind::Remove(_) | notify::EventKind::Any | notify::EventKind::Access(_) | notify::EventKind::Other => { /* do nothing */ } }, Err(err) => { error!(?err, "Watching file: {path:?}"); } } } actix_rt::time::sleep(Duration::from_millis(1000)).await; } } .await; Ok(()) }