Here's a minimal example code, the question is about function shutdown.
If direct call handler.stop(), it will errors
error[E0507]: cannot move out of `*watcher` which is behind a mutable reference
|
200 | watcher.stop();
| ^^^^^^^ ------ `*watcher` moved due to this method call
| |
| move occurs because `*watcher` has type `Debouncer<notify::ReadDirectoryChangesWatcher, FileIdMap>`, whic, which does not implement the `Copy` trait
If the method stop(self) can be stop(&mut self), it will be ok.
So what's the proper way to stop the debouncer watcher if it's mut reference?
use chrono::prelude::*;
use notify::{Error, ReadDirectoryChangesWatcher, RecursiveMode, Watcher};
use notify_debouncer_full::{
new_debouncer, DebounceEventResult, DebouncedEvent, Debouncer, FileIdMap,
};
use std::{path::Path, time::Duration};
use tokio::{runtime::Handle, sync::mpsc::Receiver};
pub struct NotifyHandler {
pub notify_watcher: Option<Debouncer<ReadDirectoryChangesWatcher, FileIdMap>>,
pub receiver: Option<Receiver<Result<Vec<DebouncedEvent>, Vec<Error>>>>,
}
impl NotifyHandler {
pub async fn initialize_notify_scheduler(&mut self) {
let (tx, rx) = tokio::sync::mpsc::channel(1);
let rt = Handle::current();
let debouncer = new_debouncer(
Duration::from_secs(3),
None,
move |result: DebounceEventResult| {
let tx = tx.clone();
println!("calling by notify -> {:?}", &result);
rt.spawn(async move {
if let Err(e) = tx.send(result).await {
println!("Error sending event result: {:?}", e);
}
});
},
);
match debouncer {
Ok(watcher) => {
println!("Initialize notify watcher success");
self.notify_watcher = Some(watcher);
self.receiver = Some(rx);
}
Err(error) => {
println!("{:?}", error);
}
}
}
pub async fn watch(&mut self, path: &str) -> notify::Result<()> {
let watch_path = Path::new(path);
if watch_path.exists() {
let is_file = watch_path.is_file();
println!("Valid path {} is file {}", path, is_file);
} else {
println!("watch path {:?} not exists", watch_path);
}
if let Some(watcher) = self.notify_watcher.as_mut() {
watcher
.watcher()
.watch(watch_path, RecursiveMode::Recursive)?;
watcher
.cache()
.add_root(watch_path, RecursiveMode::Recursive);
if let Some(mut rx) = self.receiver.take() {
tokio::spawn(async move {
while let Some(res) = rx.recv().await {
match res {
Ok(events) => {
println!("events: {:?}", events);
}
Err(errors) => {
println!("errors: {:?}", errors)
}
}
}
});
}
}
Ok(())
}
pub async fn shutdown(&mut self) -> Result<(), std::io::Error> {
if let Some(watcher) = self.notify_watcher().await {
if let Some(rcv) = self.receiver.as_mut() {
rcv.close();
}
watcher.stop();
}
Ok(())
}
}
#[tokio::main]
async fn main() {
let mut notifier: NotifyHandler = NotifyHandler {
notify_watcher: None,
receiver: None,
};
notifier.initialize_notify_scheduler().await;
notifier.watch("D:\\Temp\\program\\test_md.txt").await.unwrap();
loop {
tokio::time::sleep(Duration::from_secs(3)).await;
let time: DateTime<Local> = Local::now();
println!(
"{}: Hello, world!",
time.format("%Y-%m-%d %H:%M:%S").to_string()
);
notifier.shutdown().unwrap();
}
}
Here's a minimal example code, the question is about function
shutdown
.If direct call
handler.stop()
, it will errorsIf the method
stop(self)
can bestop(&mut self)
, it will be ok.So what's the proper way to stop the debouncer watcher if it's mut reference?