Repository navigation
feat: /status + MCP status/projects always answer via a background snapshot - #342
Merged
Merged
Conversation
GET /status ran repo_statuses_lightweight() + a sysinfo refresh in the request path: across 28 repos that is dozens of filesystem probes and a SCIP LMDB env open, synchronous on async workers that a heavy rebuild wave (dotnet restore + scip-csharp children) OS-starves. Field case 2026-10-16: /status and the project list timed out for minutes while symbol indexing ran - the one endpoint that must always answer was the one that could not. Now a single background task measures (spawn_blocking, one pass at a time - under load the cadence stretches instead of piling measuring tasks onto a starved machine) and stores a StatusSnapshot in a slot whose lock is only ever held to swap an Arc. The handler is O(1): it answers the stored snapshot with snapshot_age_secs for staleness and a load summary (text_indexing / symbol_indexing / errored / refresh_interval_secs) so calling agents can throttle themselves. Before the first pass completes it answers "starting" immediately. Cadence: CODESEARCH_STATUS_REFRESH_SECS, default 2s.
The scope-free serve branch of index_status called repo_statuses_lightweight() inline - the same measuring-on-request-path problem that made GET /status time out under a rebuild wave. It now reads the background snapshot via ServeState::latest_status_snapshot() and answers "starting" before the first pass completes, so the MCP status tool responds in microseconds at all times.
Three unit tests over the snapshot logic: handle None-before-first-pass + roundtrip + age, compute on an empty fleet (incl. latest_status_snapshot being None pre-store), and the CODESEARCH_STATUS_REFRESH_SECS cadence env (7s override; unparseable/zero/empty all fall back to the 2s default - zero would busy-loop the measuring task). Env var name lives in constants.rs (STATUS_REFRESH_SECS_ENV). CHANGELOG under pending [1.5.33] + highlights line; plan ticked. Validation: cargo fmt --check clean, clippy --all-targets -D warnings clean (stage 2), cargo test --lib --bins 889+885 all green.
Final-review findings: (1) list_projects (MCP status kind=projects) was the last read endpoint still measuring inline - metadata reads, try_read stats and lock probes per repo on the request path, the exact second timeout the user reported on 2026-10-16. The per-repo probe pass moved into compute_projects_snapshot() (the only measurer, called from the background task); list_projects clones the stored payload and answers immediately; pre-first-pass it answers an empty list with an explicit warming warning (channel terminates - never a silent empty answer). RepoInfo gains Clone for the slot-out clone. (2) Handler-contract tests: status_handler starting-shape + full stored pass (legacy fields, load counters, numeric age) and MCP status/projects pre-first-pass answers. Review-fixes: - [Important][Test] changed handler behavior had no test -> direct async calls of status_handler and the status tool pin the starting shapes, legacy JSON fields and the load counters. - [Design] list_projects still measured inline -> snapshot-ized via compute_projects_snapshot; user's second timeout path now covered.
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.
Why
Field case 2026-10-16: while a full SCIP rebuild wave ran (dotnet restore + scip-csharp children starving the machine), GET /status stopped responding — the one endpoint that must always answer. Root cause: it measured inline in the request path (28 repos × filesystem probes + SCIP LMDB env opens + a sysinfo refresh, synchronous on OS-starved async workers); the MCP status tool and the projects list shared the same defect and timed out with it.
What
CODESEARCH_STATUS_REFRESH_SECS(default 2s).snapshot_age_secsand aloadobject (text_indexing/symbol_indexing/errored/refresh_interval_secs).Tests
6 new: handler contract (starting shape; stored pass = legacy fields + load counters + numeric age), MCP starting answers for index and projects, handle roundtrip, empty-fleet compute, refresh-interval env (override/unparseable/zero/empty,
#[serial]+ EnvRestore).Validation
cargo fmt --check clean; clippy --all-targets -D warnings clean; cargo test --lib --bins 891+887 green.