feat(miner): retry a transient 5xx around the CI and gate-verdict pollers - #5420
Conversation
…lers A single brief 5xx from GitHub killed the whole poll loop: the pollers' own attempt loop only re-polls while a conclusion is genuinely pending, never after a server error, so a 5xx response fell straight through to a thrown error. Add a bounded fetchWithRetry wrapper that retries only a transient 5xx RESPONSE (exponential backoff, capped, max-attempts ceiling), distinct from the pending-retry loop, and wire it around the single fetch call in ci-poller and gate-verdict-poller. A 2xx/3xx/4xx response is returned immediately, and a THROWN network error is intentionally NOT retried — it propagates unchanged, preserving the pollers' existing failure-mode contract (JSONbored#4281). Pure control flow over injected fetchFn/sleepFn/backoffMs; fully unit-tested with no real network or timers. Closes JSONbored#4829
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5420 +/- ##
=======================================
Coverage 94.45% 94.45%
=======================================
Files 553 554 +1
Lines 44357 44371 +14
Branches 14659 14659
=======================================
+ Hits 41898 41912 +14
Misses 1784 1784
Partials 675 675
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
Tip 🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩 ✅ Gittensory review result - approve/merge recommendedReview updated: 2026-07-12 18:17:38 UTC
✅ Suggested Action - Approve/Merge
Review summary Nits — 5 non-blocking
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
[BETA] Chat with GittensoryAsk Gittensory a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://gittensory.aethereal.dev/docs/gittensory-commands 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
Summary
A single brief 5xx from GitHub killed the entire poll loop: the CI and gate-verdict pollers' own attempt loop only re-polls while a conclusion is genuinely
pending, never after a server error, so a 5xx response fell straight through to a thrown error and aborted the poll.This adds a bounded
fetchWithRetrywrapper (packages/gittensory-miner/lib/http-retry.js) around the pollers' single HTTP call:2xx/3xx/4xxresponse is returned immediately.Wired into
ci-poller.jsandgate-verdict-poller.js(one fetch call each). Pure control flow over injectedfetchFn/sleepFn/backoffMs— no real network or timers.Scope
packages/), noblockedPaths, no secrets/private terms.d.tscompanion addedValidation
npm run typechecknpm run test:coverage(full unsharded suite)test/unit/miner-http-retry.test.ts: 2xx first-try, 4xx-no-retry, 5xx-then-success, 5xx-exhausted-returns-5xx, thrown-error-propagates-immediately (no retry), maxAttempts=1, built-in sleep/backoff defaults, backoff sequence + fractional-maxAttempts flooring — 100% coveragetest/unit/miner-ci-poller.test.ts: a transient 5xx mid-poll is retried and the poll completes (Add retry/backoff to the CI and gate-verdict pollers #4829 acceptance)#4281failure-mode tests pass unchanged (thrown rejections still propagate immediately)Safety
maxAttemptsfloored-then-checked so a fractional value can't disable retries into a 0-attempt loopCloses #4829