From f529816c13d36df0c58138544578765a2d9e4f04 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Thu, 19 Mar 2026 07:50:20 -0600 Subject: [PATCH] fix: remove blocking rate_limiter.acquire() from request paths The rate limiter's time.sleep() blocked the single uvicorn worker thread, deadlocking the entire server (health endpoint, dashboard, all requests). Removed acquire() from both streaming and non-streaming paths. The rate limiter still records 429s for circuit breaker stats but no longer blocks. --- src/mnemosyne/gateway.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/mnemosyne/gateway.py b/src/mnemosyne/gateway.py index 138cf1e..218a38d 100644 --- a/src/mnemosyne/gateway.py +++ b/src/mnemosyne/gateway.py @@ -2707,17 +2707,17 @@ def create_app( sse_buffer = bytearray() usage: dict[str, Any] = {} try: - rate_limiter: OutboundRateLimiter = app.state.rate_limiter - rate_limiter.acquire() with client.stream( "POST", upstream_path, json=outgoing_body, headers=headers ) as resp: status_code = resp.status_code - retry_after = None + # Record 429s for circuit breaker (non-blocking) if status_code == 429: ra = resp.headers.get("retry-after") retry_after = float(ra) if ra else 1.0 - rate_limiter.record_response(status_code, retry_after) + app.state.rate_limiter.record_response(429, retry_after) + else: + app.state.rate_limiter.record_response(status_code) if status_code >= 400: body = resp.read() bytes_out = len(body) @@ -2797,14 +2797,12 @@ def create_app( # Non-streaming try: - rate_limiter: OutboundRateLimiter = app.state.rate_limiter - rate_limiter.acquire() resp = client.post(upstream_path, json=outgoing_body, headers=headers) - retry_after = None if resp.status_code == 429: ra = resp.headers.get("retry-after") - retry_after = float(ra) if ra else 1.0 - rate_limiter.record_response(resp.status_code, retry_after) + app.state.rate_limiter.record_response(429, float(ra) if ra else 1.0) + else: + app.state.rate_limiter.record_response(resp.status_code) except httpx.HTTPError as e: emit_event( "provider_error",