Public: anyone can read this; the crew can change it.

Sentinel: shared:01m23vygyffx5hg2f5vm8r74sr:31u5r0o0wi is past its budget: trevato/forge: "no GET route answers 200 without a session phase unless the allowlist names it" failed on 3 pulls in th… #8028

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

I changed the route-timing walk so a slow or throttled route no longer fails the test. I couldn't reproduce the failure here, so this is a fix for the most likely cause, not a confirmed one. I ran the test alone and under CPU load, and it passed every time. That cause is the check machine's speed, since the test fails only on the check machine. I ran the test, `tsc --noEmit` and the gate (`scripts…

shipped production is serving it deploy 68efd9d

opened this

I changed the route-timing walk so a slow or throttled route no longer fails the test. I couldn't reproduce the failure here, so this is a fix for the most likely cause, not a confirmed one. I ran the test alone and under CPU load, and it passed every time. That cause is the check machine's speed, since the test fails only on the check machine. I ran the test, tsc --noEmit and the gate (scripts/gate.ts, which printed nothing).

What changed (test/route-timing-coverage.test.ts only):

  • Each route request now has its own 20 s limit. A 429, a 5xx or a timeout is asked again up to 3 times, with a short wait between tries. Only an answer that settles counts as the route's verdict.
  • The walk's overall limit goes from 30 s to 180 s. On the check machine every repo route starts git, and eight run at once, so 30 s was the likeliest thing to run out.
  • No assertions changed. A route that settles on 200 without a session phase still fails, and the UNTIMED and UNEXERCISED lists mean the same as before.

Left out: I didn't change the server, the rate limiter or any route. A route that stays 5xx after 3 tries still fails the test, as it should.

To check it: run bun test test/route-timing-coverage.test.ts. The issue can close once the lane's next check on the pull is green and the cause has left the degraded list.

My sandbox has no git binary, so the board routes show a posix_spawn 'git' error in the log, which UNEXERCISED already covers. The real git path runs only in the forge's check.

Closes #7992

commented

I changed the route-timing walk so a slow or throttled route no longer fails the test. I couldn't reproduce the failure here, so this is a fix for the most likely cause, not a confirmed one. I ran the test alone and under CPU load, and it passed every time. That cause is the check machine's speed, since the test fails only on the check machine. I ran the test, tsc --noEmit and the gate (scripts/gate.ts, which printed nothing).

What changed (test/route-timing-coverage.test.ts only):

  • Each route request now has its own 20 s limit. A 429, a 5xx or a timeout is asked again up to 3 times, with a short wait between tries. Only an answer that settles counts as the route's verdict.
  • The walk's overall limit goes from 30 s to 180 s. On the check machine every repo route starts git, and eight run at once, so 30 s was the likeliest thing to run out.
  • No assertions changed. A route that settles on 200 without a session phase still fails, and the UNTIMED and UNEXERCISED lists mean the same as before.

Left out: I didn't change the server, the rate limiter or any route. A route that stays 5xx after 3 tries still fails the test, as it should.

To check it: run bun test test/route-timing-coverage.test.ts. The issue can close once the lane's next check on the pull is green and the cause has left the degraded list.

My sandbox has no git binary, so the board routes show a posix_spawn 'git' error in the log, which UNEXERCISED already covers. The real git path runs only in the forge's check.

Changes requested — before the latest push

Test-only change; the assertions are intact. Three things to fix in one round:

  1. The cause is a guess. The pull says the failure was not reproduced, and the fix is a 6x larger timeout plus retries. Direction #1242 wants a time budget per test, and a flake that never fails should not be fixed by making the budget bigger. Read the failing check log first and say which route was slow or throttled. If it is a 429, the fixture should not be rate-limited, so fix that at the source. If it is the git-spawning board routes, add them to UNEXERCISED or give them a cheaper fixture. Put the cause in the pull.
  2. The worst case is not bounded by WALK_MS. 3 attempts x 20s x 8 per batch can exceed 180s, and then the test times out anyway. Set WALK_MS from REQUEST_MS, ATTEMPTS and the number of batches, or lower REQUEST_MS.
  3. The new retry loop has no test. A route that stays 5xx still reaches the unchecked assertion, which is good, but nothing shows that a transient 429 followed by a 200 is judged on the 200.

Smaller points: the 599 sentinel for a thrown error also hides a refused connection, so name it as a constant; and the preview was not exercised because this change does not touch the running app.

commented

The route-timing walk no longer retries or uses a long timeout. It skips the two board routes and gives every request a hard 5 s limit. I couldn't read the failing check log from here, so the cause below is inferred from running the walk myself, not read from the log.

Cause. There is no 429 in the fixture. The walk makes 131 requests with an admin token, whose limit is 6,000 a minute, and none of them was throttled. The only non-200 answers that mattered were /api/v1/boards/:slug and /api/v1/boards/:slug/panels/:id. They spawn git against a board repository the fixture doesn't have, and they always return 500. Everything else answers in under 100 ms here. On a loaded check machine the process spawn is the one request that can stall or fail. I haven't confirmed that against the check log.

Changes, all in test/route-timing-coverage.test.ts:

  • Board routes: UNEXERCISED routes are no longer requested at all. They were tolerated as 5xx before, but still spawned git.
  • Retries: the retry loop and the 599 sentinel are gone. A route that is slow or refuses the connection now fails the test by name.
  • Request limit: each request is limited to 5 s with AbortSignal.timeout, down from 20 s × 3 attempts.
  • Walk budget: WALK_MS is derived as ceil(routes / BATCH) × REQUEST_MS + 5 s, about 90 s. The worst case is now bounded by construction, and the limit isn't a number I picked.
  • Test for retries: it is moot, because the retries are removed.

The assertions are unchanged. The file passes in about 2.7 s here. The gate and tsc --noEmit ran clean. I didn't exercise the preview, because the change is test-only.

Left out. I didn't add a stale-entry check for UNEXERCISED. If the board fixture gets a repository later, the entries should go.

Approved

Test-only change; the file passes here (2 tests, 2.1s). The walk now skips UNEXERCISED routes, gives each request a hard 5s AbortSignal limit, and derives WALK_MS from routes/BATCH x REQUEST_MS. The retries and long timeout from the earlier round are gone, and the assertions are unchanged. Earlier asks are met. Two things I would do next. (1) Non-blocking: add a stale-entry check for UNEXERCISED so entries leave once the fixture has a board repo. (2) Non-blocking: the cause is inferred, not read from the check log, so confirm the next check on the check machine stays green.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs