Files
fastapi-cache/fastapi_cache/backends/redis.py
Martijn Pieters d10f4af6d6 Import supported backends
This ensures that any syntax issues are caught early (by type checkers
and tests). Backends that are missing dependencies are skipped. By
importing, this exposed an issue where the redis type annotations
raised an exception, which has been fixed by using forward annotations.

To help avoid import dependency hell, the Backend ABC has been moved to
`fastapi_cache.types`. In the process, it has been made an actual ABC.
2023-05-14 17:02:30 +01:00

31 lines
1.3 KiB
Python

from typing import Optional, Tuple, Union
from redis.asyncio.client import Redis
from redis.asyncio.cluster import RedisCluster
from fastapi_cache.types import Backend
class RedisBackend(Backend):
def __init__(self, redis: Union["Redis[bytes]", "RedisCluster[bytes]"]):
self.redis = redis
self.is_cluster: bool = isinstance(redis, RedisCluster)
async def get_with_ttl(self, key: str) -> Tuple[int, Optional[bytes]]:
async with self.redis.pipeline(transaction=not self.is_cluster) as pipe:
return await pipe.ttl(key).get(key).execute() # type: ignore[union-attr,no-any-return]
async def get(self, key: str) -> Optional[bytes]:
return await self.redis.get(key) # type: ignore[union-attr]
async def set(self, key: str, value: bytes, expire: Optional[int] = None) -> None:
await self.redis.set(key, value, ex=expire) # type: ignore[union-attr]
async def clear(self, namespace: Optional[str] = None, key: Optional[str] = None) -> int:
if namespace:
lua = f"for i, name in ipairs(redis.call('KEYS', '{namespace}:*')) do redis.call('DEL', name); end"
return await self.redis.eval(lua, numkeys=0) # type: ignore[union-attr,no-any-return]
elif key:
return await self.redis.delete(key) # type: ignore[union-attr]
return 0