Add grade hot cache
This commit is contained in:
@@ -1,12 +1,16 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
from typing import Literal
|
||||
|
||||
from app.config import settings
|
||||
from app.database.lazer_user import User
|
||||
from app.database.statistics import UserStatistics, UserStatisticsResp
|
||||
from app.dependencies.database import Database
|
||||
from app.dependencies.database import Database, get_redis
|
||||
from app.log import logger
|
||||
from app.models.score import GameMode
|
||||
from app.service.user_cache_service import get_user_cache_service
|
||||
|
||||
from .router import AllStrModel, router
|
||||
|
||||
@@ -38,10 +42,21 @@ class V1User(AllStrModel):
|
||||
pp_country_rank: int
|
||||
events: list[dict]
|
||||
|
||||
@classmethod
|
||||
def _get_cache_key(cls, user_id: int, ruleset: GameMode | None = None) -> str:
|
||||
"""生成 V1 用户缓存键"""
|
||||
if ruleset:
|
||||
return f"v1_user:{user_id}:ruleset:{ruleset}"
|
||||
return f"v1_user:{user_id}"
|
||||
|
||||
@classmethod
|
||||
async def from_db(
|
||||
cls, session: Database, db_user: User, ruleset: GameMode | None = None
|
||||
) -> "V1User":
|
||||
# 确保 user_id 不为 None
|
||||
if db_user.id is None:
|
||||
raise ValueError("User ID cannot be None")
|
||||
|
||||
ruleset = ruleset or db_user.playmode
|
||||
current_statistics: UserStatistics | None = None
|
||||
for i in await db_user.awaitable_attrs.statistics:
|
||||
@@ -101,24 +116,55 @@ async def get_user(
|
||||
default=1, ge=1, le=31, description="从现在起所有事件的最大天数"
|
||||
),
|
||||
):
|
||||
redis = get_redis()
|
||||
cache_service = get_user_cache_service(redis)
|
||||
|
||||
# 确定查询方式和用户ID
|
||||
is_id_query = type == "id" or user.isdigit()
|
||||
|
||||
# 解析 ruleset
|
||||
ruleset = GameMode.from_int_extra(ruleset_id) if ruleset_id else None
|
||||
|
||||
# 如果是 ID 查询,先尝试从缓存获取
|
||||
cached_v1_user = None
|
||||
user_id_for_cache = None
|
||||
|
||||
if is_id_query:
|
||||
try:
|
||||
user_id_for_cache = int(user)
|
||||
cached_v1_user = await cache_service.get_v1_user_from_cache(user_id_for_cache, ruleset)
|
||||
if cached_v1_user:
|
||||
return [V1User(**cached_v1_user)]
|
||||
except (ValueError, TypeError):
|
||||
pass # 不是有效的用户ID,继续数据库查询
|
||||
|
||||
# 从数据库查询用户
|
||||
db_user = (
|
||||
await session.exec(
|
||||
select(User).where(
|
||||
User.id == user
|
||||
if type == "id" or user.isdigit()
|
||||
else User.username == user,
|
||||
User.id == user if is_id_query else User.username == user,
|
||||
)
|
||||
)
|
||||
).first()
|
||||
|
||||
if not db_user:
|
||||
return []
|
||||
|
||||
try:
|
||||
return [
|
||||
await V1User.from_db(
|
||||
session,
|
||||
db_user,
|
||||
GameMode.from_int_extra(ruleset_id) if ruleset_id else None,
|
||||
# 生成用户数据
|
||||
v1_user = await V1User.from_db(session, db_user, ruleset)
|
||||
|
||||
# 异步缓存结果(如果有用户ID)
|
||||
if db_user.id is not None:
|
||||
user_data = v1_user.model_dump()
|
||||
asyncio.create_task(
|
||||
cache_service.cache_v1_user(user_data, db_user.id, ruleset)
|
||||
)
|
||||
]
|
||||
|
||||
return [v1_user]
|
||||
|
||||
except KeyError:
|
||||
raise HTTPException(400, "Invalid request")
|
||||
except ValueError as e:
|
||||
logger.error(f"Error processing V1 user data: {e}")
|
||||
raise HTTPException(500, "Internal server error")
|
||||
|
||||
Reference in New Issue
Block a user