Files
home_stack/backend/app/core/cache.py
T
furyhawk 3fa5720b5a perf: optimize backend API services and Docker build caching
- Add database connection pooling (pool_size=20, max_overflow=10, pool_pre_ping)
- Add LRU response caching for weather endpoints with configurable TTLs
- Reuse httpx.AsyncClient across weather API requests
- Add Docker build cache mounts for uv and npm package managers
- Optimize query ordering in users and items endpoints
- Apply ruff formatting fixes across backend
2026-04-23 19:45:48 +08:00

54 lines
1.6 KiB
Python

import time
from collections import OrderedDict
from collections.abc import Callable
from functools import wraps
from typing import Any
class LRUCache:
def __init__(self, max_size: int = 128, ttl: int = 300):
self.max_size = max_size
self.ttl = ttl
self.cache: OrderedDict[str, tuple[Any, float]] = OrderedDict()
def get(self, key: str) -> Any | None:
if key not in self.cache:
return None
value, timestamp = self.cache[key]
if time.time() - timestamp > self.ttl:
del self.cache[key]
return None
self.cache.move_to_end(key)
return value
def set(self, key: str, value: Any) -> None:
if key in self.cache:
self.cache.move_to_end(key)
elif len(self.cache) >= self.max_size:
self.cache.popitem(last=False)
self.cache[key] = (value, time.time())
def clear(self) -> None:
self.cache.clear()
weather_cache = LRUCache(max_size=64, ttl=300)
def cache_response(*, _ttl: int = 300, cache: LRUCache | None = None):
def decorator(func: Callable) -> Callable:
@wraps(func)
async def wrapper(*args: Any, **kwargs: Any) -> Any:
target_cache = cache or weather_cache
cache_key = f"{func.__name__}:{str(args)}:{str(sorted(kwargs.items()))}"
cached = target_cache.get(cache_key)
if cached is not None:
return cached
result = await func(*args, **kwargs)
target_cache.set(cache_key, result)
return result
return wrapper
return decorator