fix(request): remove double-exponential backoff in getRateLimitBackoffWithReason#414
Conversation
Deep audit finding REQ-HIGH-01 (.sisyphus/notepads/deep-audit/reports/request.json). getRateLimitBackoff() already applies baseDelay * 2^(attempt-1) + jitter. getRateLimitBackoffWithReason() called calculateBackoffMs() which applied 2^(attempt-1) AGAIN, causing delays to hit the 60s maxBackoffMs cap after just 2 consecutive 429s instead of following the documented exponential curve. Fix: calculateBackoffMs now applies only the reason multiplier to the already-exponential delayMs. Cap via maxBackoffMs is preserved. Added regression test asserting 3-attempt delay stays well under cap and that attempt=1 to attempt=3 ratio is ~4x, not >16x.
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 58 minutes and 11 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Merge the reviewed rollup fix branch after deep audit, full verification battery, and real pack/install smoke test. This lands the integrated fix set from PRs #414-#429 and #431 via one reviewed branch, including the two rollup-only integration commits: - 7f50455 fix(rollup): add missing numeric tracker cleanup helpers from PR #419 - 056ad18 test(rollup): restore auth-list empty-state expectation to current behavior Rationale: the rollup branch was the only branch deep-audited end-to-end and pack/install smoke-tested as a complete artifact. Baseline failures in codex-bin-wrapper / benchmark-runtime-path-script already exist on main and are not regressions from this merge.
Addresses deep audit finding REQ-HIGH-01.
getRateLimitBackoff()already applies exponential + jitter.getRateLimitBackoffWithReason()was then callingcalculateBackoffMs()which applied2^(attempt-1)a second time, causing delays to hit the 60s cap after ~2 consecutive 429s.Fix:
calculateBackoffMsnow applies only the reason multiplier to the already-exponentialdelayMs.Regression test added asserting attempt=3 delay stays under cap and ratio vs attempt=1 is ~4x (single exponential) not >16x (double exponential).
See
.sisyphus/notepads/deep-audit/reports/request.jsonfor the original finding.note: greptile review for oc-chatgpt-multi-auth. cite files like
lib/foo.ts:123. confirm regression tests + windows concurrency/token redaction coverage.Greptile Summary
this PR fixes the double-exponential backoff bug (REQ-HIGH-01):
calculateBackoffMswas re-applying2^(attempt-1)on top of the already-exponentialdelayMsproduced bygetRateLimitBackoff, causing delays to saturatemaxBackoffMsafter ~2 consecutive 429s. the fix removes the exponential factor fromcalculateBackoffMsso it applies only the reason multiplier, and the regression test correctly pins the attempt=3/attempt=1 ratio at ~4x (single exponential). the change is self-contained and well-commented._attemptis silently ignored in the publiccalculateBackoffMssignature — consumers reading the compiled.d.tsseeattempt: numberand will expect it to influence the result, but it is a no-op. the doc comment explains the intent but the parameter should carry a stronger@deprecatedsignal or be dropped from a future minor version.Confidence Score: 5/5
safe to merge — core fix is correct, regression test is deterministic, no production callers of calculateBackoffMs outside getRateLimitBackoffWithReason
all findings are P2: the
_attemptno-op in the public API and the zero-jitter-only regression test are style/coverage concerns, not present defects. the double-exponential is correctly removed, and the only internal caller (getRateLimitBackoffWithReason) is fully updated and covered.lib/request/rate-limit-backoff.ts —
calculateBackoffMsJSDoc should explicitly mark_attemptas ignored for external consumersImportant Files Changed
2^(attempt-1)fromcalculateBackoffMs;_attemptis now a no-op in a publicly exported function, which is a silent API contract change for direct callersSequence Diagram
sequenceDiagram participant Caller participant GRLBWR as getRateLimitBackoffWithReason participant GRLB as getRateLimitBackoff participant State as rateLimitStateByAccountQuota participant CBM as calculateBackoffMs Caller->>GRLBWR: (accountIndex, quotaKey, serverRetryAfterMs, reason) GRLBWR->>GRLB: (accountIndex, quotaKey, serverRetryAfterMs) GRLB->>State: get previous state GRLB->>GRLB: baseDelay * 2^(attempt-1) + jitter GRLB->>State: store {attempt, jitteredDelayMs} GRLB-->>GRLBWR: {attempt, delayMs (exponential+jitter), isDuplicate} alt attempt === 1 && !isDuplicate GRLBWR->>CBM: (normalizedBaseDelay, _attempt, reason) Note over CBM: BEFORE: normalizedBaseDelay * 2^(attempt-1) * multiplier<br/>AFTER: normalizedBaseDelay * multiplier only else attempt > 1 OR isDuplicate GRLBWR->>CBM: (result.delayMs, _attempt, reason) Note over CBM: BEFORE: alreadyExponentialDelay * 2^(attempt-1) * multiplier double-exp<br/>AFTER: alreadyExponentialDelay * multiplier only end CBM-->>GRLBWR: min(baseDelayMs * multiplier, maxBackoffMs) GRLBWR-->>Caller: {attempt, delayMs (single-exponential + reason), isDuplicate, reason}Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "fix(request): remove double-exponential ..." | Re-trigger Greptile