This commit is contained in:
@ -1,5 +1,45 @@
|
||||
from collections.abc import Callable, Coroutine
|
||||
from functools import wraps
|
||||
from typing import Any, TypeVar
|
||||
|
||||
from fastapi.responses import ORJSONResponse
|
||||
from orjson import dumps, loads
|
||||
from redis.asyncio import Redis
|
||||
|
||||
from apps.users.models import User
|
||||
from core.config import settings
|
||||
|
||||
client = Redis.from_url(settings.REDIS_URL)
|
||||
T = TypeVar('T')
|
||||
|
||||
|
||||
def cache_response(ttl: int = 60, namespace: str = 'main'):
|
||||
def decorator(
|
||||
func: Callable[..., Coroutine[Any, Any, T]],
|
||||
) -> Callable[..., Coroutine[Any, Any, T | ORJSONResponse]]:
|
||||
@wraps(func)
|
||||
async def wrapper(*args: Any, **kwargs: Any):
|
||||
cache_key = f'endpoints:{namespace}_{func.__name__}'
|
||||
user = kwargs.get('user')
|
||||
user_id = kwargs.get('user_id')
|
||||
|
||||
if user_id:
|
||||
cache_key += f':{user_id}'
|
||||
|
||||
if isinstance(user, User):
|
||||
cache_key += f':{user.id}'
|
||||
|
||||
cached_value = await client.get(cache_key)
|
||||
if cached_value:
|
||||
return ORJSONResponse(
|
||||
content=loads(cached_value), headers={'X-Cache': 'hit'}
|
||||
)
|
||||
|
||||
response = await func(*args, **kwargs)
|
||||
await client.set(cache_key, dumps(response), ex=ttl)
|
||||
|
||||
return response
|
||||
|
||||
return wrapper
|
||||
|
||||
return decorator
|
||||
|
||||
Reference in New Issue
Block a user