fix(integrations): retry linearGraphQl on a transient Linear 429 - #9385
Conversation
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
linearGraphQl (the sole HTTP entry point for every LinearAdapter method) did one fetch and threw on any non-OK response, so a transient Linear 429 (rate limit) hard-failed on the first attempt — unlike the GitHub-backed sibling adapters, which retry via the shared GitHub client. Add a bounded retry for 429 only: honor a valid non-negative Retry-After header when present, else a capped exponential backoff, up to a small fixed cap. Any other non-OK status still throws immediately, and an exhausted 429 falls through to the same throw, preserving the existing error contract. Bounded so the caller never hangs (same intent as LINEAR_FETCH_TIMEOUT_MS). Closes JSONbored#9319 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #9385 +/- ##
==========================================
+ Coverage 75.38% 75.40% +0.01%
==========================================
Files 275 276 +1
Lines 58023 58069 +46
Branches 6181 6193 +12
==========================================
+ Hits 43739 43785 +46
Misses 14014 14014
Partials 270 270
Flags with carried forward coverage won't be shown. Click here to find out more.
|
|
Tip ✅ LoopOver review result - approve/merge recommendedReview updated: 2026-07-27 15:39:35 UTC
Review summary Nits — 3 non-blocking
Decision drivers
Context & advisory signals — never blocks the verdict
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver 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://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. 🟩 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 LoopOver, a quiet PR intelligence layer for OSS maintainers.
|
Closes #9319
What
linearGraphQl(the raw POST helper shared byLinearAdapter.listOpenProjectsandfindLinearNativeLink) threw immediately on any non-OK response, so a transient Linear429rate-limit aborted the call — unlikesrc/github/client.ts, which already bounds its rate-limit responses with a small retry.This adds a bounded retry mirroring that shape, but with Linear's own status/header semantics and file-local constants (this module's convention, like
LINEAR_FETCH_TIMEOUT_MS):LINEAR_RATE_LIMIT_MAX_RETRIES = 2,LINEAR_RATE_LIMIT_BASE_BACKOFF_MS = 500,LINEAR_RATE_LIMIT_MAX_BACKOFF_MS = 4000linearRateLimitDelayMs(retryAfterHeader, attempt)— honors a valid non-negativeRetry-After(seconds), else capped exponential backoff, always bounded by the max.429with retries left: sleep then retry; any other non-OK status, or an exhausted429, throws exactly as before (the existing error contract is preserved).Tests
4 new cases in
test/unit/linear-adapter.test.ts(100% branch on the new code): 429→Retry-After: 0→200 succeeds; 429 exhausted throwsHTTP 429after exactly 3 calls; 429 with noRetry-Afterbacks off then succeeds; negativeRetry-Afterfalls back to backoff. Full file: 22 passed.