From efba5ceb9c0bb40c709285b31b479138eea473cf Mon Sep 17 00:00:00 2001 From: Agent Zero Date: Tue, 4 Aug 2026 19:43:47 +0200 Subject: [PATCH] fix: Circuit Breaker only triggers on transient DB errors, not HTTP exceptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CircuitBreakerMiddleware was blocking all requests (503 circuit_open) because every exception in get_db() — including 401 Unauthorized, 403 Forbidden, 404 Not Found — was calling record_failure() on the DB circuit breaker. This caused the circuit to trip after 5 non-DB errors (e.g. failed login attempts during security testing). Fix: Only call record_failure() when _is_transient_db_error(exc) returns True, filtering out HTTP exceptions that are not DB-related. --- app/core/db/__init__.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/core/db/__init__.py b/app/core/db/__init__.py index 7878b73..2212636 100644 --- a/app/core/db/__init__.py +++ b/app/core/db/__init__.py @@ -224,7 +224,7 @@ async def get_db() -> AsyncGenerator[AsyncSession, None]: Used for normal API requests with tenant context set via RLS. Includes retry logic for transient connection errors. """ - from app.core.resilience import get_circuit, retry_db + from app.core.resilience import get_circuit, retry_db, _is_transient_db_error async def _get_session(): factory = get_session_factory() @@ -235,9 +235,11 @@ async def get_db() -> AsyncGenerator[AsyncSession, None]: yield session await session.commit() await get_circuit("db").record_success() - except Exception: + except Exception as exc: await session.rollback() - await get_circuit("db").record_failure() + # Only record DB circuit failure for transient DB errors, not HTTP exceptions + if _is_transient_db_error(exc): + await get_circuit("db").record_failure() raise finally: await session.close()