Skip to main content

Module recovery

Module recovery 

Source
Expand description

Health tracking + retry policy for FsWatchPool. Split out of pool.rs so the recovery bookkeeping (what’s degraded, which backend is active) is testable independent of the notify/tokio wiring.

Structs§

FsWatchHealth
Snapshot of the pool’s current health, for diagnostics (muxlog, eventually a UI surface — not built here, see spec §6 non-goals).
HealthState 🔒

Enums§

WatchBackend
Which notify backend is actually driving watches right now. Polling only happens if the native backend failed to construct at all (rare — e.g. inotify unavailable) — see SPEC_SHARED_FS_WATCHER_FRAMEWORK_2026_08_07.md §4 point 2. Once picked at pool construction, this doesn’t change for the pool’s lifetime; per-path failures are tracked in degraded_paths instead, independent of which backend is in use.

Constants§

HEALTH_SWEEP_INTERVAL
How often the background sweep re-arms every currently-degraded path, self-healing a watch that failed to establish (or a prior sweep found dead) without needing a dedicated retry loop running forever. Deliberately scoped to degraded targets only, not every subscribed path — an earlier version of this sweep re-issued watch() unconditionally on everything, every tick, to also catch a silently dead healthy-looking watch (inotify instance-limit churn, a watched directory deleted and recreated at a new inode, a flaky network mount). That cost more than it bought: notify 7.0.0’s Windows backend leaks a File + Semaphore handle pair on every redundant watch() call (no cleanup of the previous entry), and even with an unwatch() first to avoid the leak, the gap between unwatch() and watch() drops event coverage for consumers with no reconciliation backstop of their own (config_watcher_fs, EditorFileWatcher, MediaFileWatcher). See pool.rs’s sweep() and docs/status/STATUS_FS_WATCH_SWEEP_HANDLE_LEAK_2026_08_22.md for the full history and the accepted trade-off (a truly silent death of an already-healthy watch is no longer self-healed by this sweep).
RETRY_BACKOFF
Backoff schedule for retrying a failed watch() call, per spec §4 point 1 — bounded at 3 attempts over ~4.2s total, not indefinite: a path that’s still failing after this moves into degraded_paths and is picked up by the periodic health sweep (pool.rs’s HEALTH_SWEEP_INTERVAL) instead of spinning a dedicated retry loop forever.