TOTP-Login und Kiosk-Nonce-Check öffneten/schlossen bisher pro Request eine neue aioredis-Verbindung. Neuer get_async_redis()-Pool in core/redis.py wird von beiden Stellen genutzt, sauberer Shutdown im FastAPI-Lifespan. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015Ahyx6D3r7G1EuAc42nezn
55 lines
2.0 KiB
Python
55 lines
2.0 KiB
Python
"""Redis-Client für TimeMaster (sync + async, für Kiosk-Nonce-Cache, Sessions, Locks)."""
|
||
from __future__ import annotations
|
||
|
||
import logging
|
||
from typing import Optional
|
||
|
||
log = logging.getLogger(__name__)
|
||
|
||
_redis_client = None
|
||
_async_redis_client = None
|
||
|
||
|
||
def get_redis_client():
|
||
"""Gibt den (sync) Redis-Client zurück oder None wenn nicht konfiguriert/erreichbar."""
|
||
global _redis_client
|
||
if _redis_client is not None:
|
||
return _redis_client
|
||
try:
|
||
import redis as redis_lib
|
||
from app.core.config import settings
|
||
url = getattr(settings, "redis_url", "redis://localhost:6379/0")
|
||
_redis_client = redis_lib.from_url(url, decode_responses=True, socket_connect_timeout=2)
|
||
# Verbindung testen
|
||
_redis_client.ping()
|
||
log.info("Redis-Verbindung hergestellt: %s", url)
|
||
return _redis_client
|
||
except Exception as exc:
|
||
log.warning("Redis nicht verfügbar: %s", exc)
|
||
return None
|
||
|
||
|
||
def get_async_redis():
|
||
"""Gepoolter async Redis-Client (eine Verbindungspool-Instanz pro Prozess).
|
||
|
||
Nicht pro Request neu verbinden/schließen (frühere Falle in totp_login und
|
||
kiosk_security._check_and_set_nonce) – der Pool verwaltet Connections selbst.
|
||
Verbindungsfehler zeigen sich erst beim ersten Call (kein Ping hier), Aufrufer
|
||
müssen weiterhin except behandeln (Nonce-Fallback, TOTP-Lockout).
|
||
"""
|
||
global _async_redis_client
|
||
if _async_redis_client is None:
|
||
import redis.asyncio as aioredis
|
||
from app.core.config import settings
|
||
url = getattr(settings, "redis_url", "redis://localhost:6379/0")
|
||
_async_redis_client = aioredis.from_url(url, decode_responses=True)
|
||
return _async_redis_client
|
||
|
||
|
||
async def close_async_redis() -> None:
|
||
"""Pool sauber schließen – im FastAPI-Lifespan-Shutdown aufrufen."""
|
||
global _async_redis_client
|
||
if _async_redis_client is not None:
|
||
await _async_redis_client.aclose()
|
||
_async_redis_client = None
|