feat: exponential backoff on HTTP 429 (re-impl of #90)#108
Open
jliounis wants to merge 1 commit into
Open
Conversation
Re-implementation of the rate-limit retry portion of #90. Credit: @akshayabogoju-coder for the original proposal. Why --- Today, makeApiRequest fails immediately on HTTP 429. That makes the server flaky under bursts and propagates a hard failure to the MCP client for what is almost always a transient condition. Change ------ makeApiRequest now wraps the underlying HTTP call (extracted as singleApiAttempt) in a retry loop that: - Retries only on HTTP 429 (rate limit). Other 4xx/5xx fail fast, because we can't assume idempotency without operator-controlled idempotency keys. - Uses the schedule [2s, 4s, 8s] by default (3 retries, 4 attempts total). - Respects the upstream Retry-After header when present. The actual wait is max(configured-delay, retry-after-seconds * 1000) so the server never retries faster than the API asks. - Schedule is overridable via PERPLEXITY_RETRY_DELAYS_MS (comma- separated milliseconds) for tests and ops tuning. Scope notes ----------- This PR is intentionally narrower than the original #90: - It does NOT touch HTTP transport / 0.0.0.0 binding / origin controls (those belong in a separate security review). - It does NOT add a README "Professional Contributions" section (out of scope). - It does NOT remove `args: any` casts in tool handlers \u2014 the MCP SDK already enforces the Zod inputSchema before the handler runs, so the cast is cosmetic, not a safety hole. Worth its own cleanup PR if/when the SDK's handler generics stabilize. - The CWE-200 sanitization that #90 also touched is being shipped separately in #107 to keep review scopes clean. Tests ----- - npm test: 82 passed / 82 (was 78 on main). - 4 new tests in a "HTTP 429 retry behavior" suite: * success after N transient 429s * gives up after the configured retry count * does NOT retry non-429 errors (5xx fails fast) * Retry-After header is honored - Tests run with PERPLEXITY_RETRY_DELAYS_MS=0,0,0 to avoid real waits. - npm run build: clean. Co-authored-by: @akshayabogoju-coder
rbuchmayer-pplx
approved these changes
May 19, 2026
|
Thanks for refining the scope and driving the implementation, James—appreciate the credit. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Re-implementation of the rate-limit retry portion of the previously-closed #90. Credit: @akshayabogoju-coder for the original proposal.
Why
Today,
makeApiRequestfails immediately on HTTP 429. That makes the server flaky under bursts and propagates a hard failure to the MCP client for what is almost always a transient condition.Change
makeApiRequestnow wraps the underlying HTTP call (extracted assingleApiAttempt) in a retry loop:[2s, 4s, 8s]by default (3 retries, 4 attempts total).Retry-Afterwhen present. The actual wait ismax(configured-delay, retry-after-seconds * 1000)so the server never retries faster than the API asks.PERPLEXITY_RETRY_DELAYS_MS(comma-separated milliseconds) for tests and ops tuning.Scope notes
This PR is intentionally narrower than the original #90:
0.0.0.0binding / origin controls (separate security review).args: anycasts in tool handlers — the MCP SDK already enforces the ZodinputSchemabefore the handler runs, so the cast is cosmetic, not a safety hole. Worth its own cleanup PR if/when the SDK's handler generics stabilize.Tests
npm test: 82 passed / 82 (was 78 onmain).Retry-Afterheader is honoredPERPLEXITY_RETRY_DELAYS_MS=0,0,0to avoid real waits.npm run build: clean.Backward compatibility
PERPLEXITY_RETRY_DELAYS_MS) is opt-in; defaults to the 2s/4s/8s schedule that matches the original proposal.