Skip to content

fix(watch): prevent watcher resubscribe crashes#2897

Merged
jschwxrz merged 2 commits into
mainfrom
slick-plums-drive
Jul 17, 2026
Merged

fix(watch): prevent watcher resubscribe crashes#2897
jschwxrz merged 2 commits into
mainfrom
slick-plums-drive

Conversation

@jschwxrz

Copy link
Copy Markdown
Collaborator
  • treats dropped fsevents notifications as a resync request instead of replacing a healthy subscription
  • serializes genuine watcher restarts and ignores stale callbacks during recovery
  • coalesces repeated TreeResource resync requests into one active refresh and one trailing refresh
  • updates the resync contract to cover recoverable event gaps

@jschwxrz

Copy link
Copy Markdown
Collaborator Author

@greptileai

@greptile-apps

greptile-apps Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR makes filesystem watcher recovery resilient to event gaps and restart races. The main changes are:

  • Treats dropped FSEvents notifications as resync requests.
  • Serializes watcher restarts and ignores stale callbacks.
  • Keeps the current subscription active when unsubscribe fails.
  • Coalesces repeated tree resync requests.
  • Adds focused recovery and disposal tests.

Confidence Score: 5/5

This looks safe to merge.

  • Failed unsubscribe attempts keep the existing watcher active and schedule another restart.
  • Restart and disposal paths guard against stale callbacks and overlapping work.
  • No blocking issues were found in the changed code.

Important Files Changed

Filename Overview
packages/core/src/services/fs-watch/impl/native-watch.ts Adds serialized restart handling, generation-based callback filtering, and recovery after unsubscribe failure.
packages/core/src/services/fs-watch/impl/native-watch.test.ts Covers event gaps, restart retries, stale callbacks, unsubscribe failures, and disposal races.
packages/core/src/files/tree/file-tree.ts Coalesces repeated resync requests and waits for active resync work during disposal.
packages/core/src/files/tree/file-tree.test.ts Updates the manual watcher and verifies active-plus-trailing resync behavior.
packages/core/src/services/fs-watch/api/models.ts Expands the resync callback contract to include native event gaps.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  E[Watcher callback] --> G{Current generation?}
  G -- No --> I[Ignore stale callback]
  G -- Yes --> R{Recoverable event gap?}
  R -- Yes --> C[Schedule resync]
  R -- No --> T[Schedule serialized restart]
  T --> U{Unsubscribe succeeds?}
  U -- No --> K[Restore current subscription]
  K --> C
  K --> T
  U -- Yes --> S{Replacement subscribes?}
  S -- No --> T
  S -- Yes --> N[Activate new generation]
  N --> C
  C --> F[Refresh file tree]
  F --> Q{Trailing request pending?}
  Q -- Yes --> F
  Q -- No --> D[Complete]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
  E[Watcher callback] --> G{Current generation?}
  G -- No --> I[Ignore stale callback]
  G -- Yes --> R{Recoverable event gap?}
  R -- Yes --> C[Schedule resync]
  R -- No --> T[Schedule serialized restart]
  T --> U{Unsubscribe succeeds?}
  U -- No --> K[Restore current subscription]
  K --> C
  K --> T
  U -- Yes --> S{Replacement subscribes?}
  S -- No --> T
  S -- Yes --> N[Activate new generation]
  N --> C
  C --> F[Refresh file tree]
  F --> Q{Trailing request pending?}
  Q -- Yes --> F
  Q -- No --> D[Complete]
Loading

Reviews (2): Last reviewed commit: "fix: retry recovery after unsubscribe fa..." | Re-trigger Greptile

Comment thread packages/core/src/services/fs-watch/impl/native-watch.ts
@arnestrickmann

Copy link
Copy Markdown
Contributor

Thanks @jschwxrz

@jschwxrz
jschwxrz merged commit 531b887 into main Jul 17, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants