fix(redis): Timeouts für Async-Pool + Start-Health-Check-Log
get_async_redis() hatte keine socket_connect_timeout/socket_timeout/ max_connections – ein gehängtes Redis hätte Requests unbegrenzt blockiert statt schnell zu failen. Zusätzlich einmaliger Ping im Lifespan-Startup, nur zur Log-Sichtbarkeit (blockiert Boot nicht). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015Ahyx6D3r7G1EuAc42nezn
This commit is contained in:
@@ -36,13 +36,25 @@ def get_async_redis():
|
|||||||
kiosk_security._check_and_set_nonce) – der Pool verwaltet Connections selbst.
|
kiosk_security._check_and_set_nonce) – der Pool verwaltet Connections selbst.
|
||||||
Verbindungsfehler zeigen sich erst beim ersten Call (kein Ping hier), Aufrufer
|
Verbindungsfehler zeigen sich erst beim ersten Call (kein Ping hier), Aufrufer
|
||||||
müssen weiterhin except behandeln (Nonce-Fallback, TOTP-Lockout).
|
müssen weiterhin except behandeln (Nonce-Fallback, TOTP-Lockout).
|
||||||
|
|
||||||
|
Timeouts analog zum sync-Client gesetzt, sonst würde ein gehängtes Redis
|
||||||
|
(statt eines klaren Connection-Refused) Requests unbegrenzt blockieren.
|
||||||
|
max_connections deckt Lastspitzen bei einem uvicorn-Worker ab, ohne dass
|
||||||
|
ein einzelner langsamer Client den ganzen Pool erschöpfen kann.
|
||||||
"""
|
"""
|
||||||
global _async_redis_client
|
global _async_redis_client
|
||||||
if _async_redis_client is None:
|
if _async_redis_client is None:
|
||||||
import redis.asyncio as aioredis
|
import redis.asyncio as aioredis
|
||||||
from app.core.config import settings
|
from app.core.config import settings
|
||||||
url = getattr(settings, "redis_url", "redis://localhost:6379/0")
|
url = getattr(settings, "redis_url", "redis://localhost:6379/0")
|
||||||
_async_redis_client = aioredis.from_url(url, decode_responses=True)
|
_async_redis_client = aioredis.from_url(
|
||||||
|
url,
|
||||||
|
decode_responses=True,
|
||||||
|
socket_connect_timeout=2,
|
||||||
|
socket_timeout=5,
|
||||||
|
max_connections=50,
|
||||||
|
)
|
||||||
|
log.info("Async-Redis-Pool erstellt: %s (max_connections=50)", url)
|
||||||
return _async_redis_client
|
return _async_redis_client
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,17 @@ async def lifespan(app: FastAPI):
|
|||||||
from app.services.scheduler_service import start as start_scheduler
|
from app.services.scheduler_service import start as start_scheduler
|
||||||
start_scheduler()
|
start_scheduler()
|
||||||
|
|
||||||
|
# Async-Redis-Pool: einmaliger Ping beim Start, nur zur Sichtbarkeit im Log
|
||||||
|
# (Sessions/Lockouts/Nonce-Cache brauchen Redis, App startet aber auch ohne –
|
||||||
|
# Fehler zeigen sich dann erst beim ersten Request, siehe get_async_redis()).
|
||||||
|
if "pytest" not in sys.modules:
|
||||||
|
from app.core.redis import get_async_redis
|
||||||
|
try:
|
||||||
|
await get_async_redis().ping()
|
||||||
|
_log.info("Async-Redis-Pool: Verbindung beim Start OK.")
|
||||||
|
except Exception as exc:
|
||||||
|
_log.warning("Async-Redis-Pool: kein Redis beim Start erreichbar (%s).", exc)
|
||||||
|
|
||||||
yield
|
yield
|
||||||
# Shutdown
|
# Shutdown
|
||||||
from app.services.scheduler_service import shutdown as shutdown_scheduler
|
from app.services.scheduler_service import shutdown as shutdown_scheduler
|
||||||
|
|||||||
Reference in New Issue
Block a user