mirror of
https://github.com/fawney19/Aether.git
synced 2026-01-12 04:28:28 +08:00
perf: 拆分热力图为独立接口并添加 Redis 缓存
- 新增独立热力图 API 端点 (/api/admin/usage/heatmap, /api/users/me/usage/heatmap) - 添加 Redis 缓存层 (5分钟 TTL),减少数据库查询 - 用户角色变更时清除热力图缓存 - 前端并行加载统计数据和热力图,添加加载/错误状态显示 - 修复 cache_decorator 缺少 JSON 解析错误处理的问题 - 更新 docker-compose 启动命令提示
This commit is contained in:
@@ -135,6 +135,20 @@ async def get_my_interval_timeline(
|
||||
return await pipeline.run(adapter=adapter, http_request=request, db=db, mode=adapter.mode)
|
||||
|
||||
|
||||
@router.get("/usage/heatmap")
|
||||
async def get_my_activity_heatmap(
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""
|
||||
Get user's activity heatmap data for the past 365 days.
|
||||
|
||||
This endpoint is cached for 5 minutes to reduce database load.
|
||||
"""
|
||||
adapter = GetMyActivityHeatmapAdapter()
|
||||
return await pipeline.run(adapter=adapter, http_request=request, db=db, mode=adapter.mode)
|
||||
|
||||
|
||||
@router.get("/providers")
|
||||
async def list_available_providers(request: Request, db: Session = Depends(get_db)):
|
||||
adapter = ListAvailableProvidersAdapter()
|
||||
@@ -650,13 +664,6 @@ class GetUsageAdapter(AuthenticatedApiAdapter):
|
||||
],
|
||||
}
|
||||
|
||||
response_data["activity_heatmap"] = UsageService.get_daily_activity(
|
||||
db=db,
|
||||
user_id=user.id,
|
||||
window_days=365,
|
||||
include_actual_cost=user.role == "admin",
|
||||
)
|
||||
|
||||
# 管理员可以看到真实成本
|
||||
if user.role == "admin":
|
||||
response_data["total_actual_cost"] = total_actual_cost
|
||||
@@ -723,6 +730,20 @@ class GetMyIntervalTimelineAdapter(AuthenticatedApiAdapter):
|
||||
return result
|
||||
|
||||
|
||||
class GetMyActivityHeatmapAdapter(AuthenticatedApiAdapter):
|
||||
"""Activity heatmap adapter with Redis caching for user."""
|
||||
|
||||
async def handle(self, context): # type: ignore[override]
|
||||
user = context.user
|
||||
result = await UsageService.get_cached_heatmap(
|
||||
db=context.db,
|
||||
user_id=user.id,
|
||||
include_actual_cost=user.role == "admin",
|
||||
)
|
||||
context.add_audit_metadata(action="activity_heatmap")
|
||||
return result
|
||||
|
||||
|
||||
class ListAvailableProvidersAdapter(AuthenticatedApiAdapter):
|
||||
async def handle(self, context): # type: ignore[override]
|
||||
from sqlalchemy.orm import selectinload
|
||||
|
||||
Reference in New Issue
Block a user