mirror of
https://github.com/long2ice/fastapi-cache.git
synced 2026-03-25 13:07:53 +00:00
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.
31 lines
1.3 KiB
Python
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
|