Repository navigation
fix(watcher): pace re-indexes by the cost of the last successful run - #2840
halindrome wants to merge 2 commits into
Conversation
After a successful re-index the next poll waits max(interval, 3 x index duration), capped at 30 min, counted from when the index finished. A project whose full rebuild takes minutes no longer re-indexes back-to-back under continuous writes; indexing spends at most ~1/4 of wall time. Sub-second indexes keep the existing cadence; failure backoff and busy-skip are unchanged. Logs watcher.cooldown when the delay is extended. Refs DeusData#2835 Signed-off-by: Shane McCarron <shane.mccarron@corvexconnect.com>
QA Round 1Contract VerificationContract: #2835 + PR acceptance criteria (cost-proportional cooldown only).
Finding 1 — [claude] Cooldown is anchored to the stale poll-cycle timestamp, so a project indexed after another in the same cycle can be rebuilt back-to-back
Expected: after a successful index, the next poll is at least Finding 2 — [claude] Wire-up test checks the cooldown log line, not that the next poll is actually deferred
Summary
Panel: contract-security, regression-edges and test-quality all landed on ObservationsNone. SAST review not applicableTarget QA performed by Claude Code (claude-opus-5-5), manager + 3-lens panel Dispositions (orchestrator, Step 3B)
Verification
QA-Fix-Commit: a83e75b Posted by the developer account (QA-agent token unavailable). Review by Claude Opus 5.5 (Anthropic) in Claude Code via qa-panel. |
QA Round 2Contract VerificationContract: #2835 + PR acceptance criteria (cost-proportional cooldown only). Reviewed at the head that includes round 1's fix
Finding 1 — [claude] Header doc and test comment say the cooldown is measured from the index start; the code measures from the index finish
Round 1's fix (
The header now contradicts both the code and the Expected: both comments say the delay counts from the index finish: indexing takes about 1/(K+1) ≈ 1/4 of wall time, and a 5-minute rebuild idles for 15 minutes. There is no runtime effect, but a maintainer who trusts the header could move the anchor back, and no test would catch it (see Observations). The fix is a two-comment edit. Summary
Panel: contract-security, regression-edges and test-quality all ran on Observations
SAST review not applicableTarget QA performed by Claude Code (claude-opus-5-5), manager + 3-lens panel Dispositions (orchestrator, Step 3B)
Cycle outcome: no critical or major findings remain after round 2. The round-1 major (cooldown anchor) is fixed and verified. Not approved: no QA-agent token is available, and approval is the human reviewer's call. QA-Fix-Commit: 40966a2 Posted by the developer account (QA-agent token unavailable). Review by Claude Opus 5.5 (Anthropic) in Claude Code via qa-panel. |
|
Thanks for opening this — it has been seen, and it is queued. This note is automated, but it is not a brush-off: it exists so you know where your PR stands instead of having to guess from silence. Current review status: working through a backlog. What that means for this PR, concretely:
Things that will genuinely speed it up whenever review does happen:
If this fixes a bug, a reproduction we can run is worth more than a description of the symptom. Thanks for contributing, and sorry in advance for the wait. |
|
Thank you, Shane, for digging into #2835 so thoroughly: the analysis of why agent sessions force full rebuilds is very useful, and pacing the watcher by the cost of the last successful run is a clean, well-bounded idea. The helper is overflow-safe, failure backoff and busy-skip are untouched, and anchoring the cooldown to the end of the index is the right call. Two changes before we merge, please:
Could you also change "Closes #2835" to "Refs #2835" in the description? The issue lists follow-ups worth keeping open. Thanks again, this is careful work. |
…t sleeping Review feedback on DeusData#2840: - Cap the success cooldown at INDEX_FAIL_CEILING_MS (5 min) instead of a separate 30-minute ceiling, so under continuous writes a project falls at most one rebuild plus five minutes behind. The 3x factor is unchanged below the cap. - Add two CBM_ENABLE_TEST_SEAMS hooks: freeze the watcher's scheduling clock, and read a project's next_poll_ns. The wire-up test now advances the frozen clock inside index_fn instead of sleeping 1.8 s, and asserts the exact scheduled poll time for an instant index, a 60 s index (180 s, counted from the END of the index) and a 200 s index (capped at 300 s). Refs DeusData#2835 Signed-off-by: Shane McCarron <shane.mccarron@corvexconnect.com>
|
Thanks for the review! Both changes are in cbf3794. The work was done by Claude Opus 5.5 (Anthropic) in Claude Code.
The description now says "Refs #2835" and reflects the new cap and test. |
Summary
Pace watcher re-indexes by how long the last successful one took, so a large project whose full rebuild takes minutes no longer re-indexes back-to-back while an agent session keeps writing files.
Refs #2835
Today the next poll after a successful re-index is the normal interval (5 s + 1 s per 500 files, max 60 s). Any write changes the dirty signature, and a new file forces a full rebuild, so on a large monorepo indexing becomes nearly continuous. It competes for CPU with interactive queries the whole time.
Change
cbm_watcher_success_delay_ms(interval_ms, index_ms)(src/watcher/watcher.c/.h) is a pure helper that returnsmax(interval, 3 × index duration), capped at 5 minutes (the existingINDEX_FAIL_CEILING_MS). It never returns less than the interval, treats negative inputs as zero, and divides instead of multiplying so it cannot overflow.poll_projecttimes theindex_fncall withnow_ns(). After a success it schedules the next poll atindex end + success_delay, so short rebuilds use at most about 1/4 of wall time; a 60 s rebuild is followed by 3 minutes idle, and anything from 100 s up by 5 minutes. Under continuous writes a project falls at most one rebuild plus 5 minutes behind. It logswatcher.cooldown(project,delay_ms) only when the delay is extended.CBM_ENABLE_TEST_SEAMShooks (test builds only):cbm_watcher_test_set_clock_nsfreezes the watcher's scheduling clock, andcbm_watcher_test_next_poll_nsreads a project's scheduled next poll.Acceptance criteria
3 × index durationafter the index finishes (capped at 5 minutes), and never less than the normal interval.Testing
tests/test_watcher.c: four unit tests for the helper (fast index, scaling, clamp/degenerate, monotonic) and one behavioural test,watcher_success_cooldown_measures_index_issue2835. The behavioural test uses a real git repo and the frozen-clock seam: the index callback advances the clock instead of sleeping, and the test asserts the exact scheduled poll time. An instant index keeps the plain interval; a 60 s index schedules the next poll 180 s after the index ends (anchoring at the start would give 120 s); a 200 s index is capped at 300 s. No fixed delays.scripts/test.sh --suites watcher: 96 passed.scripts/test.sh --suites watcher,daemon,daemon_runtime,daemon_application,daemon_frontend,daemon_bootstrap,daemon_ipc,httpd,mcp: 841 passed, 0 failed, 7 skipped.🤖 Generated with Claude Code
https://claude.ai/code/session_01CDDUoWEZMNZ9fLvzp2pPGT