fix(circuit-breaker): preserve recovery timeout when recordFailure called in OPEN state#470
Conversation
|
@nikolasdehor is attempting to deploy a commit to the Pedro Valério Lopez's projects Team on Vercel. A member of the Team first needs to authorize it. |
WalkthroughFixes a bug in the CircuitBreaker module's Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested labels
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
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 |
There was a problem hiding this comment.
Pull request overview
This PR fixes a critical bug in the CircuitBreaker implementation where calling recordFailure() while the circuit is in the OPEN state would indefinitely reset the recovery timeout, preventing the circuit from ever transitioning to HALF_OPEN. The fix moves the _lastFailureTime update from the top of recordFailure() into the state-specific branches (CLOSED and HALF_OPEN only), making recordFailure() a no-op when the circuit is OPEN.
Changes:
- Fixed
recordFailure()to preserve the recovery timeout when called in OPEN state - Added comprehensive unit tests for CircuitBreaker with specific regression test for bug #469
- Updated install manifest with file hashes and metadata
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| .aios-core/core/ids/circuit-breaker.js | Fixed recordFailure() to only update _lastFailureTime and _failureCount in CLOSED and HALF_OPEN states, making it a no-op in OPEN state |
| tests/core/ids/circuit-breaker.test.js | Added comprehensive test suite covering all states, transitions, and edge cases including regression test for issue #469 |
| .aios-core/install-manifest.yaml | Updated auto-generated manifest with new hashes and timestamps |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
.aios-core/install-manifest.yaml
Outdated
| # | ||
| version: 4.2.13 | ||
| generated_at: "2026-02-17T12:48:43.195Z" | ||
| generated_at: "2026-02-23T01:09:10.561Z" |
There was a problem hiding this comment.
The manifest shows size changes for many files that don't appear to be part of this PR (e.g., multiple development/scripts files, templates, etc.). While the manifest is auto-generated, the PR description and changes only mention circuit-breaker.js and its tests. This suggests either:
- The manifest generation included unrelated changes from the working directory
- There are unpublished formatting/whitespace changes across many files
- The manifest generation logic has changed
Please verify that only the intended files (circuit-breaker.js and its test file) were modified in this PR, and regenerate the manifest if needed to ensure it only reflects the changes in this PR.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
tests/core/ids/circuit-breaker.test.js (1)
218-228: Consider adding a_failureCountassertion for completeness.The
recordFailureinHALF_OPENnow increments_failureCount(line 101 of the source). The test at lines 223–228 checks_successCountandtotalTrips, but doesn't verify_failureCountwas incremented. A minor addition for full coverage of the new behavior:💡 Suggested addition
test('recordFailure in HALF_OPEN resets successCount and increments totalTrips', () => { const tripsBefore = cb.getStats().totalTrips; + const failuresBefore = cb.getStats().failureCount; cb.recordFailure(); expect(cb._successCount).toBe(0); expect(cb.getStats().totalTrips).toBe(tripsBefore + 1); + expect(cb.getStats().failureCount).toBe(failuresBefore + 1); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/core/ids/circuit-breaker.test.js` around lines 218 - 228, Add an assertion to the existing test "recordFailure in HALF_OPEN resets successCount and increments totalTrips" to also verify that cb._failureCount increments by one after calling recordFailure(); locate the test block using the test name or the cb.recordFailure() call and add an expectation that cb._failureCount equals its previous value plus one (capture previous value before calling recordFailure()), keeping the existing assertions for cb._successCount and cb.getStats().totalTrips.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@tests/core/ids/circuit-breaker.test.js`:
- Around line 218-228: Add an assertion to the existing test "recordFailure in
HALF_OPEN resets successCount and increments totalTrips" to also verify that
cb._failureCount increments by one after calling recordFailure(); locate the
test block using the test name or the cb.recordFailure() call and add an
expectation that cb._failureCount equals its previous value plus one (capture
previous value before calling recordFailure()), keeping the existing assertions
for cb._successCount and cb.getStats().totalTrips.
6e623a1 to
02042b2
Compare
|
@Pedrovaleriolopez @oalanicolas, esse fix do circuit-breaker (issue #469) tá aberto desde 23/fev. São quase 3 semanas. Estamos entre os contribuidores mais ativos do projeto — 24 PRs abertos, reportamos dezenas de issues, criamos módulos inteiros. Gostaríamos de um retorno, mesmo que seja pra pedir mudanças. |
…lled in OPEN state When the circuit was OPEN, recordFailure() unconditionally updated _lastFailureTime, resetting the recovery timeout on every call. This prevented the circuit from ever transitioning to HALF_OPEN in systems that continued to record failures while the circuit was open. Fix: only update _lastFailureTime when transitioning to OPEN (from CLOSED or HALF_OPEN states). When already OPEN, recordFailure is a no-op. Closes SynkraAI#469
02042b2 to
8139235
Compare
|
Rebased on latest main and resolved the install-manifest.yaml conflict. Fixed an incorrect module path in the test file as well. All 29 tests pass. This PR fixes #469 — when recordFailure() was called while the circuit breaker was already in OPEN state, it was resetting the recovery timeout, which meant the breaker could never transition to HALF_OPEN for probe attempts. Ready for review. |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
@Pedrovaleriolopez, solicitando review deste PR. Aberto desde 23/fev, corrige a issue #469 (CircuitBreaker resetando O PR duplicado #584 (aberto 11/mar) inclui a mesma correção. Este PR está MERGEABLE e pronto para merge. |
Resumo
recordFailure()no CircuitBreaker que sobrescrevia o timeout de recuperação quando chamado no estado OPENrecoveryTimeout, impedindo que o circuito transitasse para HALF_OPENPlano de teste