From 1bdc04ce1ae4d954cb84e8fafd2509ee60602fa6 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 24 Sep 2026 03:16:59 +0000 Subject: [PATCH] CircuitBreaker: measure the failure window from the previous failure last_failure_time_ was updated before IsWindowExpired() read it, so the window never expired and widely spaced failures still opened the breaker. Audit finding D8. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_015rcVQiiWyTzoNrsvLSaAfB --- ErrorRecovery.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ErrorRecovery.cc b/ErrorRecovery.cc index bfa6985..b6853f6 100644 --- a/ErrorRecovery.cc +++ b/ErrorRecovery.cc @@ -73,13 +73,15 @@ CircuitBreaker::RecordFailure() { std::lock_guard lg(mtx_); - const auto now = std::chrono::steady_clock::now(); - last_failure_time_ = now; + // The window is measured from the previous failure, so check it before + // recording this one. + const bool window_expired = IsWindowExpired(); + last_failure_time_ = std::chrono::steady_clock::now(); switch (state_) { case State::Closed: // Check if we need to reset the failure count (window expired) - if (IsWindowExpired()) { + if (window_expired) { failure_count_ = 0; }