2024-07-27 18:51:05 +01:00
|
|
|
//
|
|
|
|
use actix::prelude::*;
|
|
|
|
|
|
|
|
use actix::Recipient;
|
2024-07-30 11:37:47 +01:00
|
|
|
use anyhow::{Context, Result};
|
2024-09-01 13:10:14 +01:00
|
|
|
use notify::{event::ModifyKind, Watcher};
|
|
|
|
use tracing::{error, info};
|
2024-07-27 18:51:05 +01:00
|
|
|
|
2024-09-01 13:10:14 +01:00
|
|
|
use std::{
|
|
|
|
path::PathBuf,
|
|
|
|
sync::{
|
|
|
|
atomic::{AtomicBool, Ordering},
|
|
|
|
Arc,
|
|
|
|
},
|
|
|
|
time::Duration,
|
|
|
|
};
|
2024-07-27 18:51:05 +01:00
|
|
|
|
|
|
|
#[derive(Debug, Message)]
|
|
|
|
#[rtype(result = "()")]
|
|
|
|
pub struct FileUpdated;
|
|
|
|
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
|
|
pub enum Error {
|
|
|
|
#[error("io")]
|
|
|
|
Io(#[from] std::io::Error),
|
|
|
|
}
|
2024-08-10 20:08:07 +01:00
|
|
|
pub fn watch_file(path: PathBuf, recipient: Recipient<FileUpdated>) -> Result<Arc<AtomicBool>> {
|
2024-07-28 15:37:58 +01:00
|
|
|
let (tx, rx) = std::sync::mpsc::channel();
|
2024-08-10 20:08:07 +01:00
|
|
|
let shutdown = Arc::new(AtomicBool::default());
|
2024-07-28 15:37:58 +01:00
|
|
|
|
2024-07-30 11:37:47 +01:00
|
|
|
let mut handler = notify::recommended_watcher(tx).context("file watcher")?;
|
2024-07-28 15:37:58 +01:00
|
|
|
handler
|
|
|
|
.watch(&path, notify::RecursiveMode::NonRecursive)
|
2024-09-01 13:10:14 +01:00
|
|
|
.with_context(|| format!("Watching: {path:?}"))?;
|
2024-08-10 20:08:07 +01:00
|
|
|
let thread_shutdown = shutdown.clone();
|
|
|
|
actix_rt::task::spawn_blocking(move || {
|
2024-07-28 15:37:58 +01:00
|
|
|
loop {
|
2024-08-10 20:08:07 +01:00
|
|
|
if thread_shutdown.load(Ordering::Relaxed) {
|
|
|
|
drop(handler);
|
|
|
|
break;
|
|
|
|
}
|
2024-07-28 15:37:58 +01:00
|
|
|
for result in rx.try_iter() {
|
|
|
|
match result {
|
|
|
|
Ok(event) => match event.kind {
|
|
|
|
notify::EventKind::Modify(ModifyKind::Data(_)) => {
|
2024-09-01 13:10:14 +01:00
|
|
|
info!("File modified");
|
2024-07-28 15:37:58 +01:00
|
|
|
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:?}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-08-10 20:08:07 +01:00
|
|
|
std::thread::sleep(Duration::from_millis(1000));
|
2024-07-27 18:51:05 +01:00
|
|
|
}
|
2024-08-10 20:08:07 +01:00
|
|
|
});
|
|
|
|
Ok(shutdown)
|
2024-07-27 18:51:05 +01:00
|
|
|
}
|