Repository navigation
Fix vendor prefetch breaker-test flake and outage over-requests - #510
Conversation
an_outage_mid_list_opens_the_breaker_at_the_same_package failed on macOS CI (16 requests vs 12) and fails ~1% locally under load. The test assumed the prefetch task lands the outage's first failure before the loop leaves the granted packages, but that depended on the mock server's 10-30ms delays beating a retry ladder. Making that assumption deterministic (the loop waits, as the real loop does while it writes) exposed a real amplification: once the loop consumed the failure and moved on, the barrier lifted with the reach still sized by the answers from before the outage, so the task fired up to three extra retry ladders (21 requests vs serial's 12) at a service the loop's breaker was one failure from giving up on. Lifting the barrier now drops the reach to one, so only the loop's own position is requested until the service answers well again. The test paces the loop on the lookahead instead of on wall-clock delays. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WDqizZLqhYTcaakGpnyv1r
|
bugbot run Generated by Claude Code |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 2f72a2a. Configure here.
|
[agent] Ready for review at
Generated by Claude Code |
|
Reviewed No blocking findings. The reach reset happens before the failure barrier is lifted, and the new notifier-based pacing pins the intended test ordering without changing the request-count or breaker assertions. Validation: Ran |
Problem
api::vendor_prefetch::tests::an_outage_mid_list_opens_the_breaker_at_the_same_package(socket-patch-core unit test) failed intest (macos-latest)on CI run 36878455088 (job 110423824031, branchagent/fix-yarn-berry-hosted-auth-leak, SHA0c461dcd). That branch doesn't touch the prefetch:A single failure in
testturns the whole CI run red (about 100 jobs and about 215 job-minutes per attempt, with the windows/macostestlegs taking 18–25 min), andyarn-classic-matrix,cargo-vex-matrixand others wait on it withneeds: test.Local reproduction (unchanged main, debug build, 4 vCPU): 0/200 when idle; 11/640 and 4/640 with 16 copies running in parallel plus 8 busy-loop CPU hogs. The failures were 14, 15 and 16 requests against 12, the same signature as CI.
Root cause
The test depends on timing, and the timing-independent version of the same scenario exposes a real over-request bug in the prefetch.
Lookahead::arrivethen lifts the barrier, but the reach is still 6, a size earned by answers that came before the outage. So packages 4, 5, 6 and 7 all start their retry ladders at once, against a service the loop's own breaker is one failure from giving up on. The module docs promise this case ("an outage part-way down a list … costs what the serial loop paid, as long as the task is running ahead of the loop") costs nothing extra. On a real outage, that means about three extra 3-attempt ladders hit the patch service per outage.Fix
crates/socket-patch-core/src/api/vendor_prefetch.rs:Lookahead::arrive: when the loop moves past the failed position and the barrier lifts, the reach drops to 1. Only the loop's own position may be requested until a good answer reopens the reach (next_reach(1)isSLOW_START). Outcomes are unchanged, since every decision is still made at consumption time. The only thing removed is speculative requests against a failing service. The module and field docs are updated to say so.run_pacedhelper waits on the lookahead's ownmovednotifier (30 s safety timeout) instead of on wall-clock delays. The test's request-count assertion is unchanged (planned == serial == 12), and so are its outcome and breaker-count assertions. Only the scheduling assumption they rested on now holds by construction.No test removed, no
#[ignore], no timeout raised, no retry added.Proof
left: 18/19/21/21/21, right: 12), so it now pins the bug.api::vendor_prefetchmodule (24 tests) gave 0 failures in 200 loaded runs.cargo test -p socket-patch-core --lib: 4715 passed. Four tests fail identically on unchanged main in this container because it runs as uid 0:relax_loop_must_not_traverse_symlinked_root,an_unremovable_hidden_lock_keeps_every_store_entry,wire_write_failure_maps_error_and_leaves_lock_untouchedandwire_failure_rolls_back_already_written_filesall expect permission errors.rustfmt --checkis clean on the touched file.cargo clippy -p socket-patch-core --all-targets -- -D warningsreports nothing invendor_prefetch.rs. The errors it does report are inmaven_repo.rs,nuget_feed.rs,yarn_berry_lock.rsandbun_binary.rs, and they are the same on unchanged main with this toolchain.Where the tests run
Nothing removed or moved. The test still runs in
ci.yml'stest(3 OSes),test-releaseandcoveragejobs.🤖 Generated with Claude Code
https://claude.ai/code/session_01WDqizZLqhYTcaakGpnyv1r
Generated by Claude Code
Note
Medium Risk
Changes when the prefetch task may hit the vendor service during outages; observable outcomes and breaker behavior at consumption are unchanged, but request volume and timing against a failing host differ in the post-failure window.
Overview
Vendor prefetch no longer fires extra grant/retry traffic after the serial loop consumes a mid-list availability failure. When the loop moves past the failed position and the lookahead barrier clears,
Lookahead::arrivenow resetsreachto 1, so only the loop’s current package may be speculated until the service answers well again—instead of keeping a pre-outage window that started retry ladders on several following packages.Docs for the module and
Lookaheaddescribe that tightened bound. The flakyan_outage_mid_list_opens_the_breaker_at_the_same_packagetest uses a newrun_pacedhelper that waits on lookahead state (failure landed) before each fetch, so the “prefetch ahead of the loop” assumption holds without relying on mock delays under CPU load.Reviewed by Cursor Bugbot for commit 2f72a2a. Configure here.
Generated by Claude Code