Skip to content

fs/watch debounce only applies to the first event batch #24692

@chr1sc2y

Description

@chr1sc2y

Summary

I found a debounce bug in the app-server fs/watch notification path. The local debounce wrapper in app-server/src/fs_watch.rs stores the next deadline in next_allowance and initializes it only once. After the first event batch is emitted, later batches reuse that stale Instant, so subsequent filesystem changes can be emitted immediately instead of being debounced.

The upstream repository currently only allows collaborators to open pull requests, so I pushed a fix to my fork instead:

Impact

The first burst of file watcher events is coalesced correctly, but later bursts may bypass the intended debounce window. In the app-server path this affects fs/changed notifications, where the debounce interval is currently 200ms.

In practical terms, after the first notification burst, clients can receive noisier and less stable fs/changed notifications than intended.

Fix in the fork

The forked branch:

  • moves the debouncing wrapper into codex-file-watcher as DebouncedWatchReceiver
  • resets the debounce deadline for each event batch
  • uses deterministic path ordering via BTreeSet
  • flushes pending paths if the watcher channel closes during a debounce window
  • updates app-server fs/watch to use the shared debounce receiver

Regression coverage

I added a unit test with a 50ms debounce interval that verifies the second event batch is still debounced:

  1. send a
  2. wait 25ms
  3. send b
  4. receive one batch [a, b]
  5. send c
  6. assert recv() does not return within 25ms
  7. send d
  8. receive one batch [c, d]

Before the fix, step 6 can fail because the stale deadline is already in the past.

I also added coverage for flushing pending debounced paths when the sender closes.

Validation

Ran locally:

just fmt
PATH="$HOME/.cargo/bin:$PATH" just test -p codex-file-watcher
PATH="$HOME/.cargo/bin:$PATH" just test -p codex-app-server fs_watch

Results:

  • codex-file-watcher: 21 tests passed
  • codex-app-server fs_watch: 8 tests passed, 777 skipped
  • the bench-smoke step run by just test also passed

One unrelated existing warning appeared from codex-exec-server/src/client.rs about an unused variable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    app-serverIssues involving app server protocol or interfacesbugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions