fix(watcher): forward notify backend errors instead of silently discarding

Previously Err(_) => return in the notify callback silently dropped all
backend errors (inotify exhaustion, fs unmount, permission loss), leaving
the application unaware that file monitoring had stopped working.

Add FileEvent::WatcherError { message: String } variant to propagate
backend errors through the existing bounded channel. The TUI consumer
receives the event without disrupting the UI for transient errors.

Closes #14
This commit is contained in:
dailz
2026-06-09 11:26:54 +08:00
parent d37ed6df68
commit 7852e92ecc
2 changed files with 22 additions and 1 deletions

View File

@@ -13,6 +13,7 @@ pub enum FileEvent {
Truncated { new_size: u64 },
Rotated { new_inode: u64 },
Removed,
WatcherError { message: String },
}
// ─── get_inode ──────────────────────────────────────────────────────────────
@@ -56,7 +57,12 @@ impl FileWatcher {
notify::recommended_watcher(move |res: std::result::Result<Event, notify::Error>| {
let event = match res {
Ok(e) => e,
Err(_) => return,
Err(error) => {
let _ = tx.try_send(FileEvent::WatcherError {
message: error.to_string(),
});
return;
}
};
match event.kind {
@@ -232,5 +238,19 @@ mod tests {
let d = FileEvent::Rotated { new_inode: 42 };
assert_ne!(a, d);
let e1 = FileEvent::WatcherError {
message: "io error".into(),
};
let e2 = FileEvent::WatcherError {
message: "io error".into(),
};
assert_eq!(e1, e2);
assert_ne!(
e1,
FileEvent::WatcherError {
message: "other".into()
}
);
}
}

View File

@@ -857,6 +857,7 @@ impl App {
FileEvent::Removed => {
self.loading_state = AppLoadingState::Error("File has been deleted".into());
}
FileEvent::WatcherError { message: _ } => {}
}
}
}