Spaces:
Running
Running
| """ | |
| Infrastructure - Redis Cache Implementation | |
| """ | |
| import json | |
| from typing import Any, Optional | |
| import redis.asyncio as redis | |
| from app.domain.interfaces import ICache | |
| class RedisCache(ICache): | |
| """Redis cache implementation""" | |
| def __init__(self, redis_url: str): | |
| self.redis_url = redis_url | |
| self._client: Optional[redis.Redis] = None | |
| async def _get_client(self) -> redis.Redis: | |
| """Get or create Redis client""" | |
| if self._client is None: | |
| self._client = await redis.from_url( | |
| self.redis_url, encoding="utf-8", decode_responses=True | |
| ) | |
| return self._client | |
| async def get(self, key: str) -> Optional[Any]: | |
| """Get value from cache""" | |
| client = await self._get_client() | |
| value = await client.get(key) | |
| if value is None: | |
| return None | |
| try: | |
| return json.loads(value) | |
| except json.JSONDecodeError: | |
| return value | |
| async def set(self, key: str, value: Any, ttl: Optional[int] = None) -> bool: | |
| """Set value in cache""" | |
| client = await self._get_client() | |
| # Serialize value | |
| if isinstance(value, (dict, list)): | |
| serialized = json.dumps(value) | |
| else: | |
| serialized = str(value) | |
| if ttl: | |
| await client.setex(key, ttl, serialized) | |
| else: | |
| await client.set(key, serialized) | |
| return True | |
| async def delete(self, key: str) -> bool: | |
| """Delete key from cache""" | |
| client = await self._get_client() | |
| result = await client.delete(key) | |
| return result > 0 | |
| async def exists(self, key: str) -> bool: | |
| """Check if key exists""" | |
| client = await self._get_client() | |
| return await client.exists(key) > 0 | |
| async def clear(self, pattern: str = "*") -> int: | |
| """Clear cache by pattern""" | |
| client = await self._get_client() | |
| keys = [] | |
| async for key in client.scan_iter(match=pattern): | |
| keys.append(key) | |
| if keys: | |
| return await client.delete(*keys) | |
| return 0 | |
| async def close(self) -> None: | |
| """Close Redis connection""" | |
| if self._client: | |
| await self._client.close() | |