From ab26fad604d1b7eede2840edccaef3385e7120c6 Mon Sep 17 00:00:00 2001 From: hackjammer Date: Fri, 13 Jan 2023 23:53:02 +0000 Subject: [PATCH 1/4] passthrough for any type of backend exception --- CHANGELOG.md | 5 +++++ fastapi_cache/decorator.py | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f52d7f8..53fcfc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## 0.2 +### 0.2.1 +- Fix picklecoder +- Fix connection failure transparency +- Add Cache-Control and ETag on first response + ### 0.2.0 - Make `request` and `response` optional. diff --git a/fastapi_cache/decorator.py b/fastapi_cache/decorator.py index f08a39e..57f6a9d 100644 --- a/fastapi_cache/decorator.py +++ b/fastapi_cache/decorator.py @@ -125,7 +125,7 @@ def cache( ) try: ttl, ret = await backend.get_with_ttl(cache_key) - except ConnectionError: + except Exception: ttl, ret = 0, None if not request: if ret is not None: @@ -133,7 +133,7 @@ def cache( ret = await ensure_async_func(*args, **kwargs) try: await backend.set(cache_key, coder.encode(ret), expire) - except ConnectionError: + except Exception: pass return ret @@ -156,7 +156,7 @@ def cache( try: await backend.set(cache_key, encoded_ret, expire) - except ConnectionError: + except Exception: pass response.headers["Cache-Control"] = f"max-age={expire}" From e8193b5c22837485f4d2815ee90dad38b156e4dd Mon Sep 17 00:00:00 2001 From: hackjammer Date: Sun, 15 Jan 2023 21:54:16 +0000 Subject: [PATCH 2/4] enabled redis in cluster mode --- fastapi_cache/backends/redis.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) 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 From ea1ffcd7b460e294dcb456a5375867a78b051aa7 Mon Sep 17 00:00:00 2001 From: hackjammer Date: Tue, 17 Jan 2023 12:15:53 +0000 Subject: [PATCH 3/4] Add logging to decorator.py on backend failures --- CHANGELOG.md | 3 ++- fastapi_cache/decorator.py | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53fcfc9..9a80d9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,9 @@ ### 0.2.1 - Fix picklecoder -- Fix connection failure transparency +- 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 diff --git a/fastapi_cache/decorator.py b/fastapi_cache/decorator.py index 57f6a9d..44a5eef 100644 --- a/fastapi_cache/decorator.py +++ b/fastapi_cache/decorator.py @@ -2,6 +2,7 @@ import inspect import sys from functools import wraps from typing import Any, Awaitable, Callable, Optional, Type, TypeVar +import logging if sys.version_info >= (3, 10): from typing import ParamSpec @@ -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") @@ -126,6 +129,7 @@ def cache( try: ttl, ret = await backend.get_with_ttl(cache_key) 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: @@ -134,7 +138,7 @@ def cache( try: await backend.set(cache_key, coder.encode(ret), expire) except Exception: - pass + logger.warning(f"Error setting cache key '{cache_key}' in backend:", exc_info=True) return ret if request.method != "GET": @@ -157,7 +161,7 @@ def cache( try: await backend.set(cache_key, encoded_ret, expire) except Exception: - pass + 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)}" From 552a7695e83786f2afed2c6570c51c607ada9a16 Mon Sep 17 00:00:00 2001 From: long2ice Date: Wed, 1 Feb 2023 15:33:04 +0800 Subject: [PATCH 4/4] Update fastapi_cache/decorator.py Co-authored-by: mkdir700 <56359329+mkdir700@users.noreply.github.com> --- fastapi_cache/decorator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastapi_cache/decorator.py b/fastapi_cache/decorator.py index 44a5eef..2d8ec54 100644 --- a/fastapi_cache/decorator.py +++ b/fastapi_cache/decorator.py @@ -1,8 +1,8 @@ import inspect +import logging import sys from functools import wraps from typing import Any, Awaitable, Callable, Optional, Type, TypeVar -import logging if sys.version_info >= (3, 10): from typing import ParamSpec