85 lines
2.2 KiB
Python
85 lines
2.2 KiB
Python
"""
|
|
Client Redis partagé — pool de connexions async pour ARQ et Pub/Sub.
|
|
Inclut le parsing d'URL Redis centralisé pour éviter la duplication.
|
|
"""
|
|
from typing import Tuple, Optional
|
|
|
|
from redis.asyncio import ConnectionPool, Redis
|
|
|
|
from app.config import settings
|
|
|
|
_pool: ConnectionPool | None = None
|
|
|
|
|
|
def parse_redis_url(url: str | None = None) -> Tuple[str, int, Optional[str], int]:
|
|
"""
|
|
Parse une URL Redis en (host, port, password, database).
|
|
|
|
Format accepté : redis://[user:password@]host[:port][/db]
|
|
Retourne ('localhost', 6379, None, 0) si l'URL est vide.
|
|
"""
|
|
if url is None:
|
|
url = settings.REDIS_URL
|
|
|
|
if not url:
|
|
return "localhost", 6379, None, 0
|
|
|
|
if url.startswith("redis://"):
|
|
url = url[8:]
|
|
if url.startswith("rediss://"):
|
|
url = url[9:]
|
|
|
|
password: Optional[str] = None
|
|
if "@" in url:
|
|
auth_part, url = url.rsplit("@", 1)
|
|
if ":" in auth_part:
|
|
password = auth_part.split(":", 1)[1]
|
|
else:
|
|
password = auth_part
|
|
|
|
database = 0
|
|
if "/" in url:
|
|
host_port, db_str = url.split("/", 1)
|
|
if db_str:
|
|
try:
|
|
database = int(db_str)
|
|
except ValueError:
|
|
pass
|
|
else:
|
|
host_port = url
|
|
|
|
host = "localhost"
|
|
port = 6379
|
|
if ":" in host_port:
|
|
host, port_str = host_port.rsplit(":", 1)
|
|
if port_str:
|
|
try:
|
|
port = int(port_str)
|
|
except ValueError:
|
|
port = 6379
|
|
else:
|
|
host = host_port or "localhost"
|
|
|
|
return host, port, password, database
|
|
|
|
|
|
async def get_redis_pool() -> Redis:
|
|
"""Retourne un client Redis avec pool de connexions partagé."""
|
|
global _pool
|
|
if _pool is None:
|
|
host, port, password, database = parse_redis_url()
|
|
_pool = ConnectionPool.from_url(
|
|
settings.REDIS_URL,
|
|
max_connections=20,
|
|
decode_responses=True,
|
|
)
|
|
return Redis(connection_pool=_pool)
|
|
|
|
|
|
async def close_redis_pool() -> None:
|
|
"""Ferme proprement le pool de connexions Redis."""
|
|
global _pool
|
|
if _pool is not None:
|
|
await _pool.disconnect()
|
|
_pool = None
|