Spaces:
Running
Running
File size: 1,841 Bytes
93ff956 954e0aa 93ff956 954e0aa 93ff956 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | """
Redis client singleton with graceful fallback.
Provides a single `get_redis()` function that returns a live Redis client
when REDIS_URL is configured, or None when it is not — so every caller can
do a simple `r = get_redis(); if r is None: <fallback>` without crashing.
Connection is created once and reused for the lifetime of the process.
"""
from typing import Optional
from loguru import logger
import redis
_redis_client: Optional[redis.Redis] = None
_redis_available: bool = False
def get_redis() -> Optional[redis.Redis]:
"""
Return a live Redis client, or None if Redis is not configured / reachable.
Thread-safe via module-level sentinel; first call initialises the client.
Subsequent calls return the same singleton.
"""
global _redis_client, _redis_available
if _redis_client is not None:
return _redis_client if _redis_available else None
# Lazy import so config is already loaded before this module is imported
from src.config import settings
url = settings.redis_url
if not url:
logger.info("REDIS_URL not configured — Redis features will fall back to Supabase/in-memory.")
_redis_available = False
return None
try:
client = redis.Redis.from_url(
url,
decode_responses=True, # always get str, not bytes
socket_connect_timeout=3,
socket_timeout=3,
retry_on_timeout=True,
)
client.ping() # verify connectivity at startup
_redis_client = client
_redis_available = True
logger.info("Redis connected successfully.")
return _redis_client
except Exception as e:
logger.warning(f"Redis connection failed ({e}) — falling back to Supabase/in-memory.")
_redis_available = False
return None
|