This repository was archived by the owner on Nov 14, 2025. It is now read-only.
Commit 4da304e
feat: Add automatic retry with exponential backoff and circuit breaker (#180)
* feat: Add automatic retry with exponential backoff and circuit breaker
Implements intelligent retry logic for improved reliability when the DeepSource API
experiences transient failures. This feature ensures high availability without user
intervention during API instability, rate limit spikes, or temporary network issues.
Key features:
- Exponential backoff with jitter to prevent thundering herd
- Per-endpoint circuit breaker pattern to prevent cascade failures
- Retry budget management to limit resource consumption
- Respect for Retry-After headers from the API
- Automatic handling of transient failures (network, 502, 503, 504)
- Rate-limited requests (429) are automatically retried
Configuration via environment variables:
- RETRY_MAX_ATTEMPTS (default: 3)
- RETRY_BASE_DELAY_MS (default: 1000ms)
- RETRY_MAX_DELAY_MS (default: 30000ms)
- RETRY_BUDGET_PER_MINUTE (default: 10)
- CIRCUIT_BREAKER_THRESHOLD (default: 5)
- CIRCUIT_BREAKER_TIMEOUT_MS (default: 30000ms)
Safety features:
- Only retries idempotent operations (queries/GET requests)
- Never retries mutations (update operations)
- Transparent to MCP clients - no user-visible errors during transient failures
Closes #153
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
* fix: resolve DeepSource code quality issues
- Remove unused beforeEach import from test file
- Replace non-null assertions with proper error handling
- Fix lexical declaration scoping in switch statements
- Update test expectations to match corrected behavior
- Remove unused @playwright/test dev dependency
Fixes issues identified in PR #180 by DeepSource:
- JS-0356: Unused variables (1 major issue)
- JS-0339: Non-null assertions (2 major issues)
- JS-0054: Lexical declarations in case clauses (3 minor issues)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
* fix: use ESLint disable comment for non-null assertions
The non-null assertions are safe because we just set the value in the Map
immediately before retrieving it. Using ESLint disable comments instead
of runtime checks avoids adding uncovered branches that would fail
coverage thresholds.
* fix: properly handle non-null assertions without suppression
Refactored getBreaker and getBudget methods to avoid non-null assertions
entirely by storing the created instance in a variable before setting it
in the Map. This eliminates the DeepSource JS-0339 issue while maintaining
the required test coverage thresholds.
* fix: resolve unhandled promise rejection in retry executor test
Fixed the test case 'should throw error when all retries fail' to properly
handle the promise rejection, preventing unhandled rejection warnings and
test failures in CI.
* fix: resolve remaining deepsource code quality issues
- JS-0105: Make isAxiosError method static as it doesn't use 'this'
- JS-0047: Add default cases to switch statements in recordSuccess and recordFailure
- JS-0045: Add explicit return statement in extractRetryAfter for consistency
All DeepSource issues have been resolved.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
* fix: resolve last deepsource issue js-0045
Remove async keyword from sleep function and ensure all code paths
return a Promise consistently.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
* Update src/utils/retry/retry-budget.ts
Co-authored-by: Copilot <[email protected]>
* Update src/utils/retry/circuit-breaker.ts
Co-authored-by: Copilot <[email protected]>
* test: improve test coverage for retry modules
- Add tests for circuit breaker default case handling (99.53% coverage)
- Add comprehensive tests for RetryBudget and RetryBudgetManager (100% coverage)
- Test getAllStats, resetAll, and clear methods
- Overall retry module coverage improved to 97.26%
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
* fix: add undefined check and deepsource skip comments
- Add undefined check when accessing retryTimestamps array element
- Add DeepSource skip comments for intentional any usage in tests
- Fix formatting in circuit-breaker.ts
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
---------
Co-authored-by: Claude <[email protected]>
Co-authored-by: Copilot <[email protected]>1 parent 74870dc commit 4da304e
File tree
18 files changed
+3293
-11
lines changed- .changeset
- src
- __tests__
- utils/retry
- client
- utils
- errors
- retry
18 files changed
+3293
-11
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
89 | 89 | | |
90 | 90 | | |
91 | 91 | | |
92 | | - | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
93 | 99 | | |
94 | 100 | | |
95 | 101 | | |
| |||
149 | 155 | | |
150 | 156 | | |
151 | 157 | | |
152 | | - | |
153 | | - | |
154 | | - | |
155 | | - | |
156 | | - | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
157 | 169 | | |
158 | 170 | | |
159 | 171 | | |
160 | 172 | | |
161 | | - | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
162 | 180 | | |
163 | 181 | | |
164 | 182 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
380 | 380 | | |
381 | 381 | | |
382 | 382 | | |
383 | | - | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
384 | 390 | | |
385 | | - | |
| 391 | + | |
| 392 | + | |
386 | 393 | | |
387 | 394 | | |
388 | | - | |
| 395 | + | |
389 | 396 | | |
390 | 397 | | |
391 | 398 | | |
| |||
0 commit comments