193 lines
6.0 KiB
Python
193 lines
6.0 KiB
Python
from __future__ import annotations
|
||
|
||
import asyncio
|
||
|
||
from app.config import settings
|
||
from app.dependencies.database import get_redis
|
||
from app.dependencies.fetcher import get_fetcher
|
||
from app.log import logger
|
||
from app.scheduler.user_cache_scheduler import (
|
||
schedule_user_cache_cleanup_task,
|
||
schedule_user_cache_preload_task,
|
||
schedule_user_cache_warmup_task,
|
||
)
|
||
|
||
|
||
class CacheScheduler:
|
||
"""缓存调度器 - 统一管理各种缓存任务"""
|
||
|
||
def __init__(self):
|
||
self.running = False
|
||
self.task = None
|
||
|
||
async def start(self):
|
||
"""启动调度器"""
|
||
if self.running:
|
||
return
|
||
|
||
self.running = True
|
||
self.task = asyncio.create_task(self._run_scheduler())
|
||
logger.info("CacheScheduler started")
|
||
|
||
async def stop(self):
|
||
"""停止调度器"""
|
||
self.running = False
|
||
if self.task:
|
||
self.task.cancel()
|
||
try:
|
||
await self.task
|
||
except asyncio.CancelledError:
|
||
pass
|
||
logger.info("CacheScheduler stopped")
|
||
|
||
async def _run_scheduler(self):
|
||
"""运行调度器主循环"""
|
||
# 启动时立即执行一次预热
|
||
await self._warmup_cache()
|
||
|
||
# 启动时执行一次排行榜缓存刷新
|
||
await self._refresh_ranking_cache()
|
||
|
||
# 启动时执行一次用户缓存预热
|
||
await self._warmup_user_cache()
|
||
|
||
beatmap_cache_counter = 0
|
||
ranking_cache_counter = 0
|
||
user_cache_counter = 0
|
||
user_cleanup_counter = 0
|
||
|
||
# 从配置文件获取间隔设置
|
||
check_interval = 5 * 60 # 5分钟检查间隔
|
||
beatmap_cache_interval = 30 * 60 # 30分钟beatmap缓存间隔
|
||
ranking_cache_interval = (
|
||
settings.ranking_cache_refresh_interval_minutes * 60
|
||
) # 从配置读取
|
||
user_cache_interval = 15 * 60 # 15分钟用户缓存预加载间隔
|
||
user_cleanup_interval = 60 * 60 # 60分钟用户缓存清理间隔
|
||
|
||
beatmap_cache_cycles = beatmap_cache_interval // check_interval
|
||
ranking_cache_cycles = ranking_cache_interval // check_interval
|
||
user_cache_cycles = user_cache_interval // check_interval
|
||
user_cleanup_cycles = user_cleanup_interval // check_interval
|
||
|
||
while self.running:
|
||
try:
|
||
# 每5分钟检查一次
|
||
await asyncio.sleep(check_interval)
|
||
|
||
if not self.running:
|
||
break
|
||
|
||
beatmap_cache_counter += 1
|
||
ranking_cache_counter += 1
|
||
user_cache_counter += 1
|
||
user_cleanup_counter += 1
|
||
|
||
# beatmap缓存预热
|
||
if beatmap_cache_counter >= beatmap_cache_cycles:
|
||
await self._warmup_cache()
|
||
beatmap_cache_counter = 0
|
||
|
||
# 排行榜缓存刷新
|
||
if ranking_cache_counter >= ranking_cache_cycles:
|
||
await self._refresh_ranking_cache()
|
||
ranking_cache_counter = 0
|
||
|
||
# 用户缓存预加载
|
||
if user_cache_counter >= user_cache_cycles:
|
||
await self._preload_user_cache()
|
||
user_cache_counter = 0
|
||
|
||
# 用户缓存清理
|
||
if user_cleanup_counter >= user_cleanup_cycles:
|
||
await self._cleanup_user_cache()
|
||
user_cleanup_counter = 0
|
||
|
||
except asyncio.CancelledError:
|
||
break
|
||
except Exception as e:
|
||
logger.error(f"Cache scheduler error: {e}")
|
||
await asyncio.sleep(60) # 出错后等待1分钟再继续
|
||
|
||
async def _warmup_cache(self):
|
||
"""执行缓存预热"""
|
||
try:
|
||
logger.info("Starting beatmap cache warmup...")
|
||
|
||
fetcher = await get_fetcher()
|
||
redis = get_redis()
|
||
|
||
# 预热主页缓存
|
||
await fetcher.warmup_homepage_cache(redis)
|
||
|
||
logger.info("Beatmap cache warmup completed successfully")
|
||
|
||
except Exception as e:
|
||
logger.error(f"Beatmap cache warmup failed: {e}")
|
||
|
||
async def _refresh_ranking_cache(self):
|
||
"""刷新排行榜缓存"""
|
||
try:
|
||
logger.info("Starting ranking cache refresh...")
|
||
|
||
redis = get_redis()
|
||
|
||
# 导入排行榜缓存服务
|
||
# 使用独立的数据库会话
|
||
from app.dependencies.database import with_db
|
||
from app.service.ranking_cache_service import (
|
||
schedule_ranking_refresh_task,
|
||
)
|
||
|
||
async with with_db() as session:
|
||
await schedule_ranking_refresh_task(session, redis)
|
||
|
||
logger.info("Ranking cache refresh completed successfully")
|
||
|
||
except Exception as e:
|
||
logger.error(f"Ranking cache refresh failed: {e}")
|
||
|
||
async def _warmup_user_cache(self):
|
||
"""用户缓存预热"""
|
||
try:
|
||
await schedule_user_cache_warmup_task()
|
||
except Exception as e:
|
||
logger.error(f"User cache warmup failed: {e}")
|
||
|
||
async def _preload_user_cache(self):
|
||
"""用户缓存预加载"""
|
||
try:
|
||
await schedule_user_cache_preload_task()
|
||
except Exception as e:
|
||
logger.error(f"User cache preload failed: {e}")
|
||
|
||
async def _cleanup_user_cache(self):
|
||
"""用户缓存清理"""
|
||
try:
|
||
await schedule_user_cache_cleanup_task()
|
||
except Exception as e:
|
||
logger.error(f"User cache cleanup failed: {e}")
|
||
|
||
|
||
# Beatmap缓存调度器(保持向后兼容)
|
||
class BeatmapsetCacheScheduler(CacheScheduler):
|
||
"""谱面集缓存调度器 - 为了向后兼容"""
|
||
|
||
pass
|
||
|
||
|
||
# 全局调度器实例
|
||
cache_scheduler = CacheScheduler()
|
||
# 保持向后兼容的别名
|
||
beatmapset_cache_scheduler = BeatmapsetCacheScheduler()
|
||
|
||
|
||
async def start_cache_scheduler():
|
||
"""启动缓存调度器"""
|
||
await cache_scheduler.start()
|
||
|
||
|
||
async def stop_cache_scheduler():
|
||
"""停止缓存调度器"""
|
||
await cache_scheduler.stop()
|