47 lines
1.5 KiB
Python
47 lines
1.5 KiB
Python
from __future__ import annotations
|
|
import functools
|
|
from typing import Any, Awaitable, Callable
|
|
from fastapi import Request
|
|
from fastapi.responses import ORJSONResponse
|
|
from src.infrastructure.cache import KeydbCache
|
|
from src.infrastructure.logger import get_logger
|
|
from src.presentation.dependencies.cache import get_redis
|
|
|
|
|
|
def cached(*, prefix: str) -> Callable:
|
|
|
|
def decorator(func: Callable[..., Awaitable[Any]]):
|
|
@functools.wraps(func)
|
|
async def wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
logger = get_logger()
|
|
|
|
request = kwargs.get('request')
|
|
if not isinstance(request, Request):
|
|
for a in args:
|
|
if isinstance(a, Request):
|
|
request = a
|
|
break
|
|
|
|
auth = kwargs.get('auth')
|
|
user_id = getattr(auth, 'user_id', None) if auth else None
|
|
|
|
if request is None or user_id is None:
|
|
return await func(*args, **kwargs)
|
|
|
|
cache_key = f'{prefix}:{user_id}'
|
|
|
|
try:
|
|
redis = get_redis(request)
|
|
cache = KeydbCache(redis)
|
|
hit = await cache.get_user(user_id)
|
|
if hit is not None:
|
|
logger.debug(f'Cache hit key={cache_key}')
|
|
return ORJSONResponse(status_code=200, content=hit)
|
|
except Exception as e:
|
|
logger.warning(f'Cache read failed key={cache_key} error={e}')
|
|
|
|
return await func(*args, **kwargs)
|
|
|
|
return wrapper
|
|
return decorator
|