mirror of
https://github.com/long2ice/fastapi-cache.git
synced 2026-03-25 04:57:54 +00:00
Make backends store bytes instead of strings
This is, for the majority of backends, the native format anyway, and so we save encoding and decoding when using the PickleCodec or if (in future) a orjson Coder was to be added. For the JsonCodec, the only thing that changed is the location where the JSON data is encoded to bytes and decoded back again to a string.
This commit is contained in:
@@ -4,15 +4,15 @@ from typing import Optional, Tuple
|
||||
|
||||
class Backend:
|
||||
@abc.abstractmethod
|
||||
async def get_with_ttl(self, key: str) -> Tuple[int, Optional[str]]:
|
||||
async def get_with_ttl(self, key: str) -> Tuple[int, Optional[bytes]]:
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
async def get(self, key: str) -> Optional[str]:
|
||||
async def get(self, key: str) -> Optional[bytes]:
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
async def set(self, key: str, value: str, expire: Optional[int] = None) -> None:
|
||||
async def set(self, key: str, value: bytes, expire: Optional[int] = None) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
|
||||
@@ -39,11 +39,11 @@ class DynamoBackend(Backend):
|
||||
async def close(self) -> None:
|
||||
self.client = await self.client.__aexit__(None, None, None)
|
||||
|
||||
async def get_with_ttl(self, key: str) -> Tuple[int, str]:
|
||||
async def get_with_ttl(self, key: str) -> Tuple[int, Optional[bytes]]:
|
||||
response = await self.client.get_item(TableName=self.table_name, Key={"key": {"S": key}})
|
||||
|
||||
if "Item" in response:
|
||||
value = response["Item"].get("value", {}).get("S")
|
||||
value = response["Item"].get("value", {}).get("B")
|
||||
ttl = response["Item"].get("ttl", {}).get("N")
|
||||
|
||||
if not ttl:
|
||||
@@ -56,12 +56,12 @@ class DynamoBackend(Backend):
|
||||
|
||||
return 0, None
|
||||
|
||||
async def get(self, key: str) -> str:
|
||||
async def get(self, key: str) -> Optional[bytes]:
|
||||
response = await self.client.get_item(TableName=self.table_name, Key={"key": {"S": key}})
|
||||
if "Item" in response:
|
||||
return response["Item"].get("value", {}).get("S")
|
||||
return response["Item"].get("value", {}).get("B")
|
||||
|
||||
async def set(self, key: str, value: str, expire: Optional[int] = None) -> None:
|
||||
async def set(self, key: str, value: bytes, expire: Optional[int] = None) -> None:
|
||||
ttl = (
|
||||
{
|
||||
"ttl": {
|
||||
@@ -83,7 +83,7 @@ class DynamoBackend(Backend):
|
||||
Item={
|
||||
**{
|
||||
"key": {"S": key},
|
||||
"value": {"S": value},
|
||||
"value": {"B": value},
|
||||
},
|
||||
**ttl,
|
||||
},
|
||||
|
||||
@@ -8,7 +8,7 @@ from fastapi_cache.backends import Backend
|
||||
|
||||
@dataclass
|
||||
class Value:
|
||||
data: str
|
||||
data: bytes
|
||||
ttl_ts: int
|
||||
|
||||
|
||||
@@ -29,21 +29,21 @@ class InMemoryBackend(Backend):
|
||||
return v
|
||||
return None
|
||||
|
||||
async def get_with_ttl(self, key: str) -> Tuple[int, Optional[str]]:
|
||||
async def get_with_ttl(self, key: str) -> Tuple[int, Optional[bytes]]:
|
||||
async with self._lock:
|
||||
v = self._get(key)
|
||||
if v:
|
||||
return v.ttl_ts - self._now, v.data
|
||||
return 0, None
|
||||
|
||||
async def get(self, key: str) -> Optional[str]:
|
||||
async def get(self, key: str) -> Optional[bytes]:
|
||||
async with self._lock:
|
||||
v = self._get(key)
|
||||
if v:
|
||||
return v.data
|
||||
return None
|
||||
|
||||
async def set(self, key: str, value: str, expire: Optional[int] = None) -> None:
|
||||
async def set(self, key: str, value: bytes, expire: Optional[int] = None) -> None:
|
||||
async with self._lock:
|
||||
self._store[key] = Value(value, self._now + (expire or 0))
|
||||
|
||||
|
||||
@@ -9,14 +9,14 @@ class MemcachedBackend(Backend):
|
||||
def __init__(self, mcache: Client):
|
||||
self.mcache = mcache
|
||||
|
||||
async def get_with_ttl(self, key: str) -> Tuple[int, Optional[str]]:
|
||||
return 3600, await self.mcache.get(key.encode())
|
||||
async def get_with_ttl(self, key: str) -> Tuple[int, Optional[bytes]]:
|
||||
return 3600, await self.get(key)
|
||||
|
||||
async def get(self, key: str) -> Optional[str]:
|
||||
return await self.mcache.get(key, key.encode())
|
||||
async def get(self, key: str) -> Optional[bytes]:
|
||||
return await self.mcache.get(key.encode())
|
||||
|
||||
async def set(self, key: str, value: str, expire: Optional[int] = None) -> None:
|
||||
await self.mcache.set(key.encode(), value.encode(), exptime=expire or 0)
|
||||
async def set(self, key: str, value: bytes, expire: Optional[int] = None) -> None:
|
||||
await self.mcache.set(key.encode(), value, exptime=expire or 0)
|
||||
|
||||
async def clear(self, namespace: Optional[str] = None, key: Optional[str] = None) -> int:
|
||||
raise NotImplementedError
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Optional, Tuple
|
||||
from typing import Optional, Tuple, Union
|
||||
|
||||
from redis.asyncio.client import Redis
|
||||
from redis.asyncio.cluster import RedisCluster
|
||||
@@ -7,18 +7,18 @@ from fastapi_cache.backends import Backend
|
||||
|
||||
|
||||
class RedisBackend(Backend):
|
||||
def __init__(self, redis: Redis[str] | RedisCluster[str]):
|
||||
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, str]:
|
||||
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()
|
||||
|
||||
async def get(self, key: str) -> Optional[str]:
|
||||
async def get(self, key: str) -> Optional[bytes]:
|
||||
return await self.redis.get(key)
|
||||
|
||||
async def set(self, key: str, value: str, expire: Optional[int] = None) -> None:
|
||||
async def set(self, key: str, value: bytes, expire: Optional[int] = None) -> None:
|
||||
return await self.redis.set(key, value, ex=expire)
|
||||
|
||||
async def clear(self, namespace: Optional[str] = None, key: Optional[str] = None) -> int:
|
||||
|
||||
Reference in New Issue
Block a user