Skip to content

test(server): make the busy-rescan re-arm assertion timing-free - #1733

Merged
Dumbris merged 2 commits into
mainfrom
claude/contributor-issues-prs-review-ed9acf
Oct 22, 2026
Merged

Dumbris merged 2 commits into
mainfrom
claude/contributor-issues-prs-review-ed9acf

Conversation

@Dumbris

@Dumbris Dumbris commented Oct 22, 2026 •

Copy link
Copy Markdown
Member

Description

TestInformationalRescan_BusyServerIsRetriedNotDropped (Spec 118, #1689) failed on main in 4 of the last 8 unit-test runs and was the only red check on contributor PRs #1727, #1725 and #1715.

Cause. fireInformationalRescan deletes the server's entry from infoRescanTimers when the debounce timer fires and re-creates it only after the gates and the claim ran. On every busy fire there is a short window in which "is a timer armed" is false. The test sampled the map at one fixed instant (time.Sleep(4 * debounce)), which under CI load lands in that window. Reproduced locally: 1 failure in 150 runs with GOMAXPROCS=1 under 2×ncpu CPU burners.

Fix (test only). Read infoRescanSeq under the mutex before scheduling; the change itself takes before+1, so require.Eventually(rescanSeq("srv") > before+1) is a timing-free proof that a busy fire re-armed the timer. The "no scan attempted on top of a claimed slot" and "a busy slot is not a failed attempt" assertions are unchanged.

Verification. 400 runs of the fixed test under the same CPU contention: 0 failures. go test -race -count=3 -run TestInformationalRescan ./internal/server/ green. golangci-lint with the CI v2 config clean. Cross-reviewed with opencode (gpt-6.1-sol), two rounds: round 1 found the baseline read could hit the same gap (fixed by reading the counter before scheduling), round 2 CLEAN.

No production code changes.

Second flake, same PR

TestRefreshConcurrency_ScansDuringASlowSelfCheckSeeOldOrNew (from #1720) failed the darwin-amd64 Build Binaries job on this PR: 119.6ms is not less than 109.7ms (baseline median 1.19ms). Both refresh-concurrency guards compared the single worst of 300 scans against 50*median+50ms, which one GC pause on a macOS runner exceeds. They now bound p90 relative to the baseline and keep an absolute 2 s ceiling on the worst scan (no scheduler stall reaches it, any wait behind the gate or a fetch deadline does). 30 runs under CPU contention: 0 failures. opencode Sol 6.1 round 1 flagged that p90 alone could hide one scan absorbing a timed-out wait; the absolute ceiling is the answer to that.

TestInformationalRescan_BusyServerIsRetriedNotDropped sampled the rescan
timer map at one fixed instant. fireInformationalRescan drops the entry at
fire time and re-creates it only after the gates and the claim ran, so the
sample could land in that window under CI load (4 of 8 recent main runs).

Read infoRescanSeq before scheduling and wait for a sequence above
before+1, which only a busy re-arm can produce. No production change.
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Deploying mcpproxy-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 9871eed
Status: ✅  Deploy successful!
Preview URL: https://44a4780d.mcpproxy-docs.pages.dev
Branch Preview URL: https://claude-contributor-issues-pr.mcpproxy-docs.pages.dev

View logs

…absolute ceiling

The two guards compared the single worst of 300 scans against
50*median+50ms; one GC pause or descheduled goroutine on a macOS runner
hit 119ms against a 109ms bound. Bound p90 relative to the baseline and
keep an absolute 2s ceiling on the worst scan, which no scheduler stall
reaches but any wait behind the gate or a fetch deadline would.
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions

Copy link
Copy Markdown
Contributor

📦 Build Artifacts

Workflow Run: View Run
Branch: claude/contributor-issues-prs-review-ed9acf

Available Artifacts

  • archive-darwin-amd64 (32 MB)
  • archive-darwin-arm64 (29 MB)
  • archive-linux-amd64 (19 MB)
  • archive-linux-arm64 (17 MB)
  • archive-windows-amd64 (32 MB)
  • archive-windows-arm64 (28 MB)
  • frontend-dist-pr (0 MB)
  • installer-dmg-darwin-amd64 (28 MB)
  • installer-dmg-darwin-arm64 (25 MB)
  • smart-mcp-proxymcpproxy-goZAQA1G.dockerbuild (0 MB)

How to Download

Option 1: GitHub Web UI (easiest)

  1. Go to the workflow run page linked above
  2. Scroll to the bottom "Artifacts" section
  3. Click on the artifact you want to download

Option 2: GitHub CLI

gh run download 39750735140 --repo smart-mcp-proxy/mcpproxy-go

Note: Artifacts expire in 14 days.

@Dumbris
Dumbris merged commit 559fba0 into main Oct 22, 2026
52 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants