"""Redis client wrapper.""" import redis.asyncio as redis from typing import Optional from src.core.config import get_config from src.core.logger import get_logger logger = get_logger(__name__) class RedisClient: """Redis client wrapper with automatic connection handling.""" def __init__(self): """Initialize Redis client.""" self.config = get_config() self._client: Optional[redis.Redis] = None self._pool: Optional[redis.ConnectionPool] = None def get_client(self) -> redis.Redis: """Get or create Redis client. Returns: Async Redis client """ if self._client is None: self._connect() return self._client def _connect(self): """Connect to Redis.""" redis_config = self.config.get("redis", {}) host = redis_config.get("host", "localhost") port = redis_config.get("port", 6379) db = redis_config.get("db", 0) password = redis_config.get("password") logger.info(f"Connecting to Redis at {host}:{port}/{db}") try: self._pool = redis.ConnectionPool( host=host, port=port, db=db, password=password, decode_responses=True, socket_connect_timeout=redis_config.get("socket_connect_timeout", 5) ) self._client = redis.Redis(connection_pool=self._pool) except Exception as e: logger.error(f"Failed to create Redis client: {e}") raise async def close(self): """Close Redis connection.""" if self._client: await self._client.aclose() logger.info("Redis connection closed") # Global instance _redis_client: Optional[RedisClient] = None def get_redis_client() -> RedisClient: """Get global Redis client instance.""" global _redis_client if _redis_client is None: _redis_client = RedisClient() return _redis_client