fix: Circuit Breaker only triggers on transient DB errors, not HTTP exceptions

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.
This commit is contained in:
Agent Zero
2026-08-04 19:43:47 +02:00
parent 17765e47b4
commit efba5ceb9c
+5 -3
View File
@@ -224,7 +224,7 @@ async def get_db() -> AsyncGenerator[AsyncSession, None]:
Used for normal API requests with tenant context set via RLS. Used for normal API requests with tenant context set via RLS.
Includes retry logic for transient connection errors. 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(): async def _get_session():
factory = get_session_factory() factory = get_session_factory()
@@ -235,9 +235,11 @@ async def get_db() -> AsyncGenerator[AsyncSession, None]:
yield session yield session
await session.commit() await session.commit()
await get_circuit("db").record_success() await get_circuit("db").record_success()
except Exception: except Exception as exc:
await session.rollback() 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 raise
finally: finally:
await session.close() await session.close()