diff --git a/CHANGELOG.md b/CHANGELOG.md index f52d7f8..9a80d9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## 0.2 +### 0.2.1 +- Fix picklecoder +- Fix connection failure transparency and add logging +- Add Cache-Control and ETag on first response +- Support Async RedisCluster client from redis-py + ### 0.2.0 - Make `request` and `response` optional. diff --git a/fastapi_cache/backends/redis.py b/fastapi_cache/backends/redis.py index 6d70627..0088f4f 100644 --- a/fastapi_cache/backends/redis.py +++ b/fastapi_cache/backends/redis.py @@ -1,16 +1,18 @@ from typing import Optional, Tuple -from redis.asyncio.client import Redis +from redis.asyncio.client import AbstractRedis +from redis.asyncio.cluster import AbstractRedisCluster from fastapi_cache.backends import Backend class RedisBackend(Backend): - def __init__(self, redis: Redis): + def __init__(self, redis: AbstractRedis): self.redis = redis + self.is_cluster = isinstance(redis, AbstractRedisCluster) async def get_with_ttl(self, key: str) -> Tuple[int, str]: - async with self.redis.pipeline(transaction=True) as pipe: + 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]: @@ -25,4 +27,4 @@ class RedisBackend(Backend): return await self.redis.eval(lua, numkeys=0) elif key: return await self.redis.delete(key) - return 0 + return 0 \ No newline at end of file diff --git a/fastapi_cache/decorator.py b/fastapi_cache/decorator.py index f08a39e..2d8ec54 100644 --- a/fastapi_cache/decorator.py +++ b/fastapi_cache/decorator.py @@ -1,4 +1,5 @@ import inspect +import logging import sys from functools import wraps from typing import Any, Awaitable, Callable, Optional, Type, TypeVar @@ -15,6 +16,8 @@ from starlette.responses import Response from fastapi_cache import FastAPICache from fastapi_cache.coder import Coder +logger = logging.getLogger(__name__) +logger.addHandler(logging.NullHandler()) P = ParamSpec("P") R = TypeVar("R") @@ -125,7 +128,8 @@ def cache( ) try: ttl, ret = await backend.get_with_ttl(cache_key) - except ConnectionError: + except Exception: + logger.warning(f"Error retrieving cache key '{cache_key}' from backend:", exc_info=True) ttl, ret = 0, None if not request: if ret is not None: @@ -133,8 +137,8 @@ def cache( ret = await ensure_async_func(*args, **kwargs) try: await backend.set(cache_key, coder.encode(ret), expire) - except ConnectionError: - pass + except Exception: + logger.warning(f"Error setting cache key '{cache_key}' in backend:", exc_info=True) return ret if request.method != "GET": @@ -156,8 +160,8 @@ def cache( try: await backend.set(cache_key, encoded_ret, expire) - except ConnectionError: - pass + except Exception: + logger.warning(f"Error setting cache key '{cache_key}' in backend:", exc_info=True) response.headers["Cache-Control"] = f"max-age={expire}" etag = f"W/{hash(encoded_ret)}"