fix(watchers/watcher.node): Improve Node watcher robustness: inode tracking, ENOSPC detection, enhanced health checks and temp-file handling

This commit is contained in:
2025-12-08 19:31:48 +00:00
parent 913c14bfcf
commit 0c236d44d3
4 changed files with 92 additions and 14 deletions

View File

@@ -73,17 +73,28 @@ The `WriteStabilizer` class replaces chokidar's built-in write stabilization:
### Robustness Features (v6.1.0+)
The Node.js watcher includes automatic recovery mechanisms:
The Node.js watcher includes automatic recovery mechanisms based on learnings from [chokidar](https://github.com/paulmillr/chokidar) and known [fs.watch issues](https://github.com/nodejs/node/issues/47058):
**Auto-restart on failure:**
- Watchers automatically restart when errors occur
- Exponential backoff (1s → 30s max)
- Maximum 3 retry attempts before giving up
**Inode tracking (critical for long-running watchers):**
- `fs.watch()` watches the **inode**, not the path!
- When directories are replaced (git checkout, atomic saves), the inode changes
- Health check detects inode changes and restarts the watcher
- This is the most common cause of "watcher stops working after some time"
**Health check monitoring:**
- 30-second periodic health checks
- Detects when watched paths disappear
- Triggers automatic restart when issues detected
- Detects inode changes (directory replacement)
- Detects ENOSPC errors (inotify limit exceeded)
**ENOSPC detection (Linux inotify limit):**
- Detects when `/proc/sys/fs/inotify/max_user_watches` is exceeded
- Logs fix command: `echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p`
**Error isolation:**
- Subscriber errors don't crash the watcher
@@ -100,8 +111,17 @@ Example log output:
[smartwatch] Starting health check (every 30s)
[smartwatch] Watcher started with 1 active watcher(s)
[smartwatch] Health check: 1 watchers active
[smartwatch] Inode changed for ./src: 12345 -> 67890
[smartwatch] fs.watch watches inode, not path - restarting watcher
```
### Known fs.watch Limitations
1. **Watches inode, not path** - If a directory is replaced, watcher goes stale
2. **inotify limits on Linux** - Default `max_user_watches` (8192) may be too low
3. **No events for some atomic writes** - Some editors' save patterns may not trigger events
4. **Platform differences** - Linux uses inotify, macOS uses FSEvents/kqueue
### Testing
```bash