Update requirements-dev.txt to add E2E testing dependencies: fakeredis and mongomock for in-memory testing, and include testcontainers for PostgreSQL support.
171 lines
5.1 KiB
Python
171 lines
5.1 KiB
Python
"""
|
|
Fake Redis Repository adapter for testing.
|
|
|
|
This adapter implements the RedisRepository interface using fakeredis
|
|
to provide an in-memory Redis server for testing.
|
|
"""
|
|
|
|
import json
|
|
from typing import Any
|
|
|
|
import fakeredis
|
|
from sientia_do.notifications.handlers import CoreNotificationHandler as NotificationHandler
|
|
from sientia_do.observability.logger import Logger
|
|
from sientia_do.observability.metrics_controller import MetricsController
|
|
from sientia_do.observability.sientia_monitoring import SientiaMonitoring
|
|
|
|
|
|
class FakeRedisRepository(SientiaMonitoring):
|
|
"""
|
|
Fake Redis Repository that uses fakeredis for testing.
|
|
|
|
Implements the same interface as RedisRepository but uses
|
|
fakeredis for in-memory Redis operations.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
host: str,
|
|
port: int,
|
|
username: str,
|
|
password: str,
|
|
logger: Logger,
|
|
notification_handler: NotificationHandler,
|
|
metrics_controller: MetricsController,
|
|
):
|
|
"""
|
|
Initialize fake Redis repository with fakeredis.
|
|
|
|
Args:
|
|
host: Redis server address (ignored in fake mode)
|
|
port: Redis server port (ignored in fake mode)
|
|
username: Username (ignored in fake mode)
|
|
password: Password (ignored in fake mode)
|
|
logger: Logger instance
|
|
notification_handler: Notification handler
|
|
metrics_controller: Metrics controller
|
|
"""
|
|
SientiaMonitoring.__init__(
|
|
self,
|
|
logger=logger,
|
|
notification_handler=notification_handler,
|
|
metrics_controller=metrics_controller,
|
|
)
|
|
# Create fake Redis server
|
|
self.redis_client = fakeredis.FakeStrictRedis(
|
|
decode_responses=True
|
|
)
|
|
|
|
def _get_redis(self):
|
|
"""Get fakeredis connection."""
|
|
return self.redis_client
|
|
|
|
async def get(self, key: str, metadata: dict | None = None):
|
|
"""
|
|
Gets a value from fake Redis by key.
|
|
|
|
Args:
|
|
key: Key of the value to retrieve
|
|
metadata: Optional dictionary with additional metadata
|
|
|
|
Return:
|
|
Deserialized value from Redis or None if not found
|
|
"""
|
|
redis = self._get_redis()
|
|
try:
|
|
history = redis.get(key)
|
|
return json.loads(history) if history else None
|
|
except Exception as e:
|
|
self.error(f'Error getting data from fake redis: {e}', metadata or {})
|
|
raise e
|
|
|
|
async def set(
|
|
self,
|
|
key: str,
|
|
data: dict,
|
|
ttl: int = 600,
|
|
nx: bool = False,
|
|
metadata: dict | None = None,
|
|
) -> bool:
|
|
"""
|
|
Sets a value in fake Redis with optional TTL.
|
|
|
|
Args:
|
|
key: Key of the value to set
|
|
data: Dictionary with data to store
|
|
ttl: Time to live in seconds (default: 600)
|
|
nx: If True, only sets if key doesn't exist (default: False)
|
|
metadata: Optional dictionary with additional metadata
|
|
|
|
Return:
|
|
True if value was set, False otherwise
|
|
"""
|
|
redis = self._get_redis()
|
|
try:
|
|
result = redis.set(
|
|
key, json.dumps(data), ex=ttl, nx=nx
|
|
)
|
|
return bool(result)
|
|
except Exception as e:
|
|
self.error(f'Error setting data in fake redis: {e}', metadata or {})
|
|
raise e
|
|
|
|
async def delete(self, key: str, metadata: dict | None = None):
|
|
"""
|
|
Removes a key from fake Redis.
|
|
|
|
Args:
|
|
key: Key to be removed
|
|
metadata: Optional dictionary with additional metadata
|
|
"""
|
|
redis = self._get_redis()
|
|
try:
|
|
redis.delete(key)
|
|
except Exception as e:
|
|
self.error(f'Error deleting data from fake redis: {e}', metadata or {})
|
|
raise e
|
|
|
|
async def expire(self, key: str, ttl: int, metadata: dict | None = None):
|
|
"""
|
|
Sets the time to live (TTL) of an existing Redis key.
|
|
|
|
Args:
|
|
key: Key whose TTL will be set
|
|
ttl: Time to live in seconds
|
|
metadata: Optional dictionary with additional metadata
|
|
"""
|
|
redis = self._get_redis()
|
|
try:
|
|
redis.expire(key, ttl)
|
|
except Exception as e:
|
|
self.error(f'Error expiring data from fake redis: {e}', metadata or {})
|
|
raise e
|
|
|
|
async def keys(self, pattern: str, metadata: dict | None = None):
|
|
"""
|
|
Gets all keys matching the specified pattern.
|
|
|
|
Args:
|
|
pattern: Search pattern for keys
|
|
metadata: Optional dictionary with additional metadata
|
|
|
|
Return:
|
|
List of keys matching the pattern
|
|
"""
|
|
redis = self._get_redis()
|
|
try:
|
|
keys = redis.keys(pattern)
|
|
return keys
|
|
except Exception as e:
|
|
self.error(f'Error getting keys from fake redis: {e}', metadata or {})
|
|
raise e
|
|
|
|
def close(self):
|
|
"""
|
|
Closes fake Redis connection and shuts down monitoring.
|
|
"""
|
|
if self.redis_client:
|
|
self.redis_client.close()
|
|
SientiaMonitoring.shutdown(self)
|
|
|