fix(engine): widen 429 backoff budget, correct the rate-limit explanation
Measured directly against the live forge: nginx never sends a Retry-After header on its 429s (the branch handling it is dead code in practice), the limit is a leaky bucket rather than a fixed ban (a 20-25 request burst took up to ~15s to drain), it is IP-based rather than token-quota-based (a valid FORGEJO_TOKEN made no difference to a reproduced burst), and it triggers well below "13 calls in a loop" — 20 concurrent anonymous requests reproduced it directly. The old default (retries: 3, ~7s worst case) was tuned for a hard ban that doesn't exist. fetchWithRetry now defaults to retries: 5 with a maxDelayMs: 8000 cap (23s worst case), covering the measured drain time without one attempt blocking for a full uncapped exponential step. CLAUDE.md's explanation is corrected to match; test count in README/CLAUDE.md updated for the two new tests (111 -> 113). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W1ZJFViVYpr8cvf4fs91j1
This commit is contained in:
parent
568b8e374a
commit
e6b0f04021
4 changed files with 61 additions and 9 deletions
24
CLAUDE.md
24
CLAUDE.md
|
|
@ -56,11 +56,23 @@ would recreate, in data, exactly the drift this plugin exists to remove.
|
|||
INSTALL-TRUTH is the other (added after this used to say "one call" — that
|
||||
line went stale and stayed stale until a 13-repo shell loop trusted it and
|
||||
tripped the rate limiter at 26 requests). Both go through `fetchWithRetry`,
|
||||
which honors `Retry-After` on HTTP 429 rather than silently reporting SKIP.
|
||||
Both are anonymous — no token — so the gate works for any reader, not only
|
||||
someone holding one. A sweep across every repo still does not belong here:
|
||||
it needs the listing fetched once, not once per invocation, which is a
|
||||
different shape of caller (org-ops), not a flag on this engine.
|
||||
which retries HTTP 429 rather than silently reporting SKIP. Both are
|
||||
anonymous — no token, confirmed no different with one — so the gate works
|
||||
for any reader, not only someone holding one. A sweep across every repo
|
||||
still does not belong here: it needs the listing fetched once, not once per
|
||||
invocation, which is a different shape of caller (org-ops), not a flag on
|
||||
this engine.
|
||||
**The "13 calls in a loop" explanation was incomplete** (2026-08-04): the
|
||||
forge's nginx never sends `Retry-After` on its 429s (measured directly), so
|
||||
`fetchWithRetry` always falls back to exponential backoff — the
|
||||
`Retry-After` branch is live code with no live path yet. The limit is also
|
||||
smaller than "loop of 13" implied: 20 concurrent requests from one IP
|
||||
reproduced it directly, no loop needed, and a single well-formed 2-call
|
||||
invocation can still lose if something else on the same IP is calling the
|
||||
forge at the same moment (other repos' hooks, another session). The block
|
||||
is a leaky bucket, not a fixed ban — a 20-25 request burst took up to ~15s
|
||||
to fully drain. `fetchWithRetry` defaults to `retries: 5` /
|
||||
`maxDelayMs: 8000` (23s worst case) to cover that.
|
||||
- **Codepoints, not bytes, not UTF-16 units.** Use `[...s].length`. An em-dash
|
||||
exposes only the byte layer; astral characters expose the rest.
|
||||
- **The reader decides a link's level, not just what is required.** Root
|
||||
|
|
@ -77,7 +89,7 @@ would recreate, in data, exactly the drift this plugin exists to remove.
|
|||
## Commands
|
||||
|
||||
```bash
|
||||
npm test # 111 tests
|
||||
npm test # 113 tests
|
||||
node scripts/repo-standard-check.mjs --dir "$PWD" # gate one repo
|
||||
node scripts/repo-standard-check.mjs --offline # no network call
|
||||
node scripts/repo-standard-check.mjs --json # machine output
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue