syncweb_core/fs/
watcher.rs1use std::{
2 path::{Path, PathBuf},
3 sync::mpsc::{self, Receiver, TryRecvError},
4};
5
6use notify::{Event, RecommendedWatcher, RecursiveMode, Watcher};
7
8use crate::error::{Result, SyncwebError};
9
10#[derive(Clone, Debug)]
12#[non_exhaustive]
13pub struct FsEvent {
14 pub event: Event,
15 pub paths: Vec<PathBuf>,
16}
17
18pub struct FsWatcher {
20 watcher: RecommendedWatcher,
21 receiver: Receiver<Result<FsEvent>>,
22}
23
24impl std::fmt::Debug for FsWatcher {
25 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 formatter.debug_struct("FsWatcher").finish_non_exhaustive()
27 }
28}
29
30impl FsWatcher {
31 pub fn new(path: impl AsRef<Path>) -> Result<Self> {
36 let (sender, receiver) = mpsc::channel();
37 let watcher = notify::recommended_watcher(move |event_result: notify::Result<Event>| {
38 let result = event_result
39 .map(|event| FsEvent {
40 event: event.clone(),
41 paths: event.paths,
42 })
43 .map_err(|error| SyncwebError::operation("filesystem watcher event failed", error));
44 let _ = sender.send(result);
45 })
46 .map_err(|error| SyncwebError::operation("failed to create filesystem watcher", error))?;
47 let mut this = Self { watcher, receiver };
48 this.watcher
49 .watch(path.as_ref(), RecursiveMode::Recursive)
50 .map_err(|error| SyncwebError::operation("failed to watch filesystem path", error))?;
51 Ok(this)
52 }
53
54 pub fn recv(&self) -> Result<FsEvent> {
59 self.receiver
60 .recv()
61 .map_err(|error| SyncwebError::operation("filesystem watcher stopped", error))?
62 }
63
64 pub fn try_recv(&self) -> Result<Option<FsEvent>> {
69 match self.receiver.try_recv() {
70 Ok(event) => event.map(Some),
71 Err(TryRecvError::Empty) => Ok(None),
72 Err(TryRecvError::Disconnected) => Err(SyncwebError::operation(
73 "filesystem watcher stopped",
74 "event channel disconnected",
75 )),
76 }
77 }
78
79 pub fn unwatch(&mut self, path: impl AsRef<Path>) -> Result<()> {
84 self.watcher
85 .unwatch(path.as_ref())
86 .map_err(|error| SyncwebError::operation("failed to stop filesystem watcher", error))
87 }
88}