fix(mention): tie pending match requests to the file index generation - #374
Merged
Merged
Conversation
- Track in-flight match requests as `PendingMatch { sequence, generation }`
instead of a bare sequence number
- Only defer a refresh when the pending request belongs to the current
generation, so a request voided by an index restart no longer blocks it
- Validate both sequence and generation when applying a match result
- Add a deterministic regression test that restarts the index while a
request is in flight and asserts the search still settles
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
@-file autocomplete can hang permanently on "Searching files…" when the file index restarts while a match request is in flight. This ties an in-flight request to the file index generation it was issued against, so a request voided by a restart can no longer block the refresh that would recover the menu.MentionStatetracked in-flight match requests as a barepending_match_sequence: Option<u64>. A file index restart bumpsfile_index.generation, and the matcher drops stale-generation requests incomplete_querywithout sending a reply — so that sequence is never answered.apply_match_resultalso rejects any result whose generation moved, returning early and leaving the sequence set.request_match_for_active_mentionthen reads that dead promise as "a request is in flight" and defers every non-UserQueryrefresh, including the one issued by the restart itself. The menu stays atSearchingforever.The fix makes generation part of the request identity:
PendingMatch { sequence, generation }replaces the bare sequencesequenceandgenerationto match the pending request; the existing explicitresult.generation != app.file_index.generationcheck is kept, since an old result can still match an oldPendingMatchWhy
This is a general bug, not a macOS one. It was found via the Nightly macOS failures, where FSEvents coalescing reliably lands a
.gitignore-triggered rebuild inside the query window, but any generation bump during an in-flight query reproduces it. Other triggers on every platform:config/edit.rs— togglingrespect_gitignoreevents/session.rs— session start and cwd changestate/session_reset.rs— session resetfile_index.rs— watcher-drivenRebuildRequestedon.gitignore/.ignore/.git/info/excludechangesRoot cause was established by measurement, not inference — debug tracing on a macOS runner produced:
The matcher had computed the correct result for the correct query with a matching sequence. It was discarded solely because the generation moved in flight.
Closes
Fixes the recurring Nightly
app::mentionfailures onmacos-latest.Validation
Automated
cargo fmt --all -- --check— cleancargo clippy --all-targets --all-features -- -D warnings— cleancargo test— 1813 passed, 0 failedindex_restart_replaces_a_request_left_pending_by_the_previous_generation: issues a real request, restarts the index before the result is drained, runs the normal refresh path, and asserts the new pending request carries the new generation and that the search settles. Deterministic and platform-independent.pending_match.is_some()makes it fail withleft: 1, right: 2— the pending request stays pinned to the dead generation.Manual
A macOS Nightly run is dispatched on this branch to confirm on the real runner. Note that the original failure is a race, so a single green run is supporting evidence rather than proof; the regression test failing without the fix is what demonstrates the mechanism.
Screenshot
n/a
Notes
PendingMatchis a private struct insrc/app/mention.rsOut of scope, noted for follow-up:
request_matchlogs a query-channel send failure without reporting it back toMentionState, which could theoretically strand a current-generation pending request. Separate robustness issue; it does not weaken this fix.