95 lines
2.3 KiB
Python
95 lines
2.3 KiB
Python
import logging
|
|
import os
|
|
import fnmatch
|
|
from typing import Any, List, Tuple
|
|
|
|
import redis
|
|
from app.core.config import settings
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class InMemoryRedis:
|
|
"""Minimal in-memory Redis replacement for tests."""
|
|
|
|
def __init__(self):
|
|
self.store = {}
|
|
|
|
def get(self, key):
|
|
return self.store.get(key)
|
|
|
|
def set(self, key, value):
|
|
self.store[key] = value
|
|
return True
|
|
|
|
def setex(self, key, _seconds, value):
|
|
self.store[key] = value
|
|
return True
|
|
|
|
def delete(self, key):
|
|
if key in self.store:
|
|
del self.store[key]
|
|
return 1
|
|
return 0
|
|
|
|
def scan_iter(self, match=None):
|
|
if match is None:
|
|
yield from self.store.keys()
|
|
return
|
|
for key in list(self.store.keys()):
|
|
if fnmatch.fnmatch(key, match):
|
|
yield key
|
|
|
|
def publish(self, _channel, _message):
|
|
return 1
|
|
|
|
def ping(self):
|
|
return True
|
|
|
|
|
|
if os.getenv("TESTING") == "true":
|
|
redis_client = InMemoryRedis()
|
|
else:
|
|
redis_client = redis.Redis(
|
|
host=settings.REDIS_HOST,
|
|
port=settings.REDIS_PORT,
|
|
db=settings.REDIS_DB,
|
|
decode_responses=True,
|
|
)
|
|
|
|
|
|
def get_redis():
|
|
"""Dependency for getting Redis client."""
|
|
return redis_client
|
|
|
|
|
|
def get_redis_sync():
|
|
"""Get Redis client synchronously (non-dependency use)."""
|
|
return redis_client
|
|
|
|
|
|
class RedisManager:
|
|
"""Lightweight Redis helper with publish fallback for reliability tests."""
|
|
|
|
def __init__(self, client=None):
|
|
self._client = client
|
|
self._message_queue: List[Tuple[str, Any]] = []
|
|
|
|
def get_client(self):
|
|
return self._client or redis_client
|
|
|
|
def _publish_direct(self, channel: str, message: Any):
|
|
client = self.get_client()
|
|
return client.publish(channel, message)
|
|
|
|
def queue_message(self, channel: str, message: Any) -> None:
|
|
self._message_queue.append((channel, message))
|
|
|
|
def publish_with_fallback(self, channel: str, message: Any):
|
|
try:
|
|
return self._publish_direct(channel, message)
|
|
except Exception as exc:
|
|
self.queue_message(channel, message)
|
|
logger.warning("Redis publish failed, queued message: %s", exc)
|
|
return None
|