71 lines
2.1 KiB
Python
71 lines
2.1 KiB
Python
import json
|
|
from datetime import datetime, timedelta
|
|
from typing import Any
|
|
|
|
from astrbot.api import logger
|
|
|
|
from ..sqlite import AsyncSQLiteDB
|
|
|
|
|
|
class JSONCacheRepository:
|
|
"""基于 achievement_cache 表的通用 JSON 缓存。"""
|
|
|
|
def __init__(self, database: AsyncSQLiteDB):
|
|
self._database = database
|
|
|
|
async def get(
|
|
self,
|
|
key: str,
|
|
*,
|
|
max_age: timedelta = timedelta(days=30),
|
|
) -> tuple[Any | None, bool]:
|
|
try:
|
|
row = await self._database.select_one(
|
|
"achievement_cache",
|
|
"key=?",
|
|
(key,),
|
|
)
|
|
except Exception as exc:
|
|
logger.error(f"读取 JSON 缓存失败: key={key}, error={exc}")
|
|
return None, True
|
|
|
|
if not row:
|
|
return None, True
|
|
|
|
try:
|
|
payload = json.loads(row.get("content", "{}"))
|
|
updated_at = datetime.strptime(
|
|
row.get("updated_at", ""),
|
|
"%Y-%m-%d %H:%M:%S",
|
|
)
|
|
except (json.JSONDecodeError, TypeError, ValueError) as exc:
|
|
logger.error(f"解析 JSON 缓存失败: key={key}, error={exc}")
|
|
return None, True
|
|
|
|
return payload, datetime.now() - updated_at > max_age
|
|
|
|
async def set(self, key: str, payload: Any) -> None:
|
|
try:
|
|
content = json.dumps(payload, ensure_ascii=False)
|
|
except (TypeError, ValueError) as exc:
|
|
logger.error(f"序列化 JSON 缓存失败: key={key}, error={exc}")
|
|
return
|
|
|
|
try:
|
|
await self._database.execute(
|
|
"""
|
|
INSERT INTO achievement_cache (key, content, updated_at)
|
|
VALUES (?, ?, ?)
|
|
ON CONFLICT(key) DO UPDATE SET
|
|
content=excluded.content,
|
|
updated_at=excluded.updated_at
|
|
""",
|
|
(
|
|
key,
|
|
content,
|
|
datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
|
),
|
|
)
|
|
except Exception as exc:
|
|
logger.error(f"写入 JSON 缓存失败: key={key}, error={exc}")
|