fork
This commit is contained in:
65
src/services/calendar.py
Normal file
65
src/services/calendar.py
Normal file
@@ -0,0 +1,65 @@
|
||||
import asyncio
|
||||
import copy
|
||||
import time
|
||||
from typing import cast
|
||||
|
||||
from astrbot.api import logger
|
||||
|
||||
from .base import BaseBangumiService
|
||||
from .contracts import CalendarDay
|
||||
from .exceptions import BangumiApiError
|
||||
|
||||
|
||||
class CalendarService(BaseBangumiService):
|
||||
CALENDAR_CACHE_TTL_SECONDS = 12 * 60 * 60
|
||||
|
||||
def __init__(self, *args: object, **kwargs: object) -> None:
|
||||
super().__init__(*args, **kwargs)
|
||||
self._calendar_cache: list[CalendarDay] | None = None
|
||||
self._calendar_cache_expire_at: float = 0.0
|
||||
self._calendar_cache_lock = asyncio.Lock()
|
||||
|
||||
def _is_calendar_cache_valid(self, now: float) -> bool:
|
||||
return self._calendar_cache is not None and now < self._calendar_cache_expire_at
|
||||
|
||||
def invalidate_calendar_cache(self) -> None:
|
||||
self._calendar_cache = None
|
||||
self._calendar_cache_expire_at = 0.0
|
||||
|
||||
async def get_calendar(self) -> list[CalendarDay]:
|
||||
now = time.time()
|
||||
if self._is_calendar_cache_valid(now):
|
||||
return copy.deepcopy(self._calendar_cache)
|
||||
|
||||
# 双重检查 + 锁,避免并发下重复请求远端 API
|
||||
async with self._calendar_cache_lock:
|
||||
now = time.time()
|
||||
if self._is_calendar_cache_valid(now):
|
||||
return copy.deepcopy(self._calendar_cache)
|
||||
|
||||
url = f"{self.base_url}/calendar"
|
||||
previous_cache = copy.deepcopy(self._calendar_cache)
|
||||
try:
|
||||
data = await self._request(url, method="GET")
|
||||
except (BangumiApiError, RuntimeError, ValueError, TypeError) as e:
|
||||
logger.error(f"get_calendar 刷新缓存失败: {e}")
|
||||
if previous_cache is not None:
|
||||
return previous_cache
|
||||
return []
|
||||
|
||||
if not isinstance(data, list):
|
||||
logger.warning(f"get_calendar 返回了非 list 类型: {type(data)}")
|
||||
if previous_cache is not None:
|
||||
return previous_cache
|
||||
return []
|
||||
|
||||
normalized: list[CalendarDay] = []
|
||||
for item in data:
|
||||
if isinstance(item, dict):
|
||||
normalized.append(cast(CalendarDay, item))
|
||||
else:
|
||||
logger.warning(f"get_calendar 列表元素类型异常: {type(item)}")
|
||||
|
||||
self._calendar_cache = copy.deepcopy(normalized)
|
||||
self._calendar_cache_expire_at = now + self.CALENDAR_CACHE_TTL_SECONDS
|
||||
return copy.deepcopy(self._calendar_cache)
|
||||
Reference in New Issue
Block a user