mirror of
https://github.com/A-Minos/nonebot-plugin-tetris-stats.git
synced 2026-03-05 05:36:54 +08:00
⚡️ 为 IO 添加缓存
This commit is contained in:
@@ -0,0 +1,28 @@
|
|||||||
|
from datetime import UTC, datetime
|
||||||
|
|
||||||
|
from aiocache import Cache as ACache # type: ignore[import-untyped]
|
||||||
|
from nonebot.log import logger
|
||||||
|
from pydantic import parse_raw_as
|
||||||
|
|
||||||
|
from ...utils.request import Request
|
||||||
|
from .schemas.base import FailedModel, SuccessModel
|
||||||
|
|
||||||
|
|
||||||
|
class Cache:
|
||||||
|
cache = ACache(ACache.MEMORY)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def get(cls, url: str) -> bytes:
|
||||||
|
cached_data = await cls.cache.get(url)
|
||||||
|
if cached_data is None:
|
||||||
|
response_data = await Request.request(url)
|
||||||
|
parsed_data: SuccessModel | FailedModel = parse_raw_as(SuccessModel | FailedModel, response_data) # type: ignore[arg-type]
|
||||||
|
if isinstance(parsed_data, SuccessModel):
|
||||||
|
await cls.cache.add(
|
||||||
|
url,
|
||||||
|
response_data,
|
||||||
|
(parsed_data.cache.cached_until - datetime.now(UTC)).total_seconds(),
|
||||||
|
)
|
||||||
|
return response_data
|
||||||
|
logger.debug(f'{url}: Cache hit!')
|
||||||
|
return cached_data
|
||||||
@@ -13,22 +13,19 @@ from sqlalchemy import select
|
|||||||
|
|
||||||
from ...db import create_or_update_bind
|
from ...db import create_or_update_bind
|
||||||
from ...utils.exception import MessageFormatError, RequestError, WhatTheFuckError
|
from ...utils.exception import MessageFormatError, RequestError, WhatTheFuckError
|
||||||
from ...utils.request import Request, splice_url
|
from ...utils.request import splice_url
|
||||||
from ...utils.typing import GameType
|
from ...utils.typing import GameType
|
||||||
from .. import Processor as ProcessorMeta
|
from .. import Processor as ProcessorMeta
|
||||||
from ..schemas import BaseUser
|
from .cache import Cache
|
||||||
from .constant import BASE_URL, GAME_TYPE, RANK_PERCENTILE
|
from .constant import BASE_URL, GAME_TYPE, RANK_PERCENTILE
|
||||||
from .model import IORank
|
from .model import IORank
|
||||||
from .schemas.league_all import FailedModel as LeagueAllFailed
|
from .schemas.league_all import FailedModel as LeagueAllFailed
|
||||||
from .schemas.league_all import LeagueAll
|
from .schemas.league_all import LeagueAll
|
||||||
from .schemas.league_all import ValidUser as LeagueAllUser
|
from .schemas.league_all import ValidUser as LeagueAllUser
|
||||||
from .schemas.response import ProcessedData, RawResponse
|
from .schemas.response import ProcessedData, RawResponse
|
||||||
|
from .schemas.user import User
|
||||||
from .schemas.user_info import FailedModel as InfoFailed
|
from .schemas.user_info import FailedModel as InfoFailed
|
||||||
from .schemas.user_info import (
|
from .schemas.user_info import NeverPlayedLeague, NeverRatedLeague, UserInfo
|
||||||
NeverPlayedLeague,
|
|
||||||
NeverRatedLeague,
|
|
||||||
UserInfo,
|
|
||||||
)
|
|
||||||
from .schemas.user_info import SuccessModel as InfoSuccess
|
from .schemas.user_info import SuccessModel as InfoSuccess
|
||||||
from .schemas.user_records import FailedModel as RecordsFailed
|
from .schemas.user_records import FailedModel as RecordsFailed
|
||||||
from .schemas.user_records import SoloRecord, UserRecords
|
from .schemas.user_records import SoloRecord, UserRecords
|
||||||
@@ -38,17 +35,6 @@ from .typing import Rank
|
|||||||
driver = get_driver()
|
driver = get_driver()
|
||||||
|
|
||||||
|
|
||||||
class User(BaseUser):
|
|
||||||
ID: str | None = None
|
|
||||||
name: str | None = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def unique_identifier(self) -> str:
|
|
||||||
if self.ID is None:
|
|
||||||
raise ValueError('不完整的User!')
|
|
||||||
return self.ID
|
|
||||||
|
|
||||||
|
|
||||||
def identify_user_info(info: str) -> User | MessageFormatError:
|
def identify_user_info(info: str) -> User | MessageFormatError:
|
||||||
if match(r'^[a-f0-9]{24}$', info):
|
if match(r'^[a-f0-9]{24}$', info):
|
||||||
return User(ID=info)
|
return User(ID=info)
|
||||||
@@ -104,7 +90,7 @@ class Processor(ProcessorMeta):
|
|||||||
async def get_user_info(self) -> InfoSuccess:
|
async def get_user_info(self) -> InfoSuccess:
|
||||||
"""获取用户数据"""
|
"""获取用户数据"""
|
||||||
if self.processed_data.user_info is None:
|
if self.processed_data.user_info is None:
|
||||||
self.raw_response.user_info = await Request.request(
|
self.raw_response.user_info = await Cache.get(
|
||||||
splice_url([BASE_URL, 'users/', f'{self.user.ID or self.user.name}'])
|
splice_url([BASE_URL, 'users/', f'{self.user.ID or self.user.name}'])
|
||||||
)
|
)
|
||||||
user_info: UserInfo = parse_raw_as(UserInfo, self.raw_response.user_info) # type: ignore[arg-type]
|
user_info: UserInfo = parse_raw_as(UserInfo, self.raw_response.user_info) # type: ignore[arg-type]
|
||||||
@@ -116,20 +102,10 @@ class Processor(ProcessorMeta):
|
|||||||
async def get_user_records(self) -> RecordsSuccess:
|
async def get_user_records(self) -> RecordsSuccess:
|
||||||
"""获取Solo数据"""
|
"""获取Solo数据"""
|
||||||
if self.processed_data.user_records is None:
|
if self.processed_data.user_records is None:
|
||||||
self.raw_response.user_records = await Request.request(
|
self.raw_response.user_records = await Cache.get(
|
||||||
splice_url(
|
splice_url([BASE_URL, 'users/', f'{self.user.ID or self.user.name}/', 'records'])
|
||||||
[
|
|
||||||
BASE_URL,
|
|
||||||
'users/',
|
|
||||||
f'{self.user.ID or self.user.name}/',
|
|
||||||
'records',
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
user_records: UserRecords = parse_raw_as(
|
|
||||||
UserRecords, # type: ignore[arg-type]
|
|
||||||
self.raw_response.user_records,
|
|
||||||
)
|
)
|
||||||
|
user_records: UserRecords = parse_raw_as(UserRecords, self.raw_response.user_records) # type: ignore[arg-type]
|
||||||
if isinstance(user_records, RecordsFailed):
|
if isinstance(user_records, RecordsFailed):
|
||||||
raise RequestError(f'用户Solo数据请求错误:\n{user_records.error}')
|
raise RequestError(f'用户Solo数据请求错误:\n{user_records.error}')
|
||||||
self.processed_data.user_records = user_records
|
self.processed_data.user_records = user_records
|
||||||
@@ -178,10 +154,7 @@ class Processor(ProcessorMeta):
|
|||||||
|
|
||||||
@scheduler.scheduled_job('cron', hour='0,6,12,18', minute=0)
|
@scheduler.scheduled_job('cron', hour='0,6,12,18', minute=0)
|
||||||
async def get_io_rank_data() -> None:
|
async def get_io_rank_data() -> None:
|
||||||
league_all: LeagueAll = parse_raw_as(
|
league_all: LeagueAll = parse_raw_as(LeagueAll, await Cache.get(splice_url([BASE_URL, 'users/lists/league/all']))) # type: ignore[arg-type]
|
||||||
LeagueAll, # type: ignore[arg-type]
|
|
||||||
await Request.request(splice_url([BASE_URL, 'users/lists/league/all'])),
|
|
||||||
)
|
|
||||||
if isinstance(league_all, LeagueAllFailed):
|
if isinstance(league_all, LeagueAllFailed):
|
||||||
raise RequestError(f'用户Solo数据请求错误:\n{league_all.error}')
|
raise RequestError(f'用户Solo数据请求错误:\n{league_all.error}')
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
from ...schemas import BaseUser
|
||||||
|
|
||||||
|
|
||||||
|
class User(BaseUser):
|
||||||
|
ID: str | None = None
|
||||||
|
name: str | None = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unique_identifier(self) -> str:
|
||||||
|
if self.ID is None:
|
||||||
|
raise ValueError('不完整的User!')
|
||||||
|
return self.ID
|
||||||
Reference in New Issue
Block a user