mirror of
https://github.com/PaiGramTeam/PaiGram.git
synced 2024-11-22 15:36:44 +00:00
🐛 Fix the issue of duplicate data being written to the database
This commit is contained in:
parent
6e3f7ce815
commit
e2649f63ee
@ -10,7 +10,7 @@ from genshin.models import BaseCharacter
|
|||||||
from genshin.models import CalculatorCharacterDetails
|
from genshin.models import CalculatorCharacterDetails
|
||||||
from pydantic import ValidationError
|
from pydantic import ValidationError
|
||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
from sqlmodel import SQLModel, Field, String, Column, Integer, BigInteger, select, DateTime, func, delete
|
from sqlmodel import SQLModel, Field, String, Column, Integer, BigInteger, select, DateTime, func, delete, Index
|
||||||
from telegram.ext import ContextTypes
|
from telegram.ext import ContextTypes
|
||||||
|
|
||||||
from core.basemodel import RegionEnum
|
from core.basemodel import RegionEnum
|
||||||
@ -45,10 +45,13 @@ class CookiesNotFoundError(Exception):
|
|||||||
|
|
||||||
class CharacterDetailsSQLModel(SQLModel, table=True):
|
class CharacterDetailsSQLModel(SQLModel, table=True):
|
||||||
__tablename__ = "character_details"
|
__tablename__ = "character_details"
|
||||||
__table_args__ = (dict(mysql_charset="utf8mb4", mysql_collate="utf8mb4_general_ci"),)
|
__table_args__ = (
|
||||||
|
Index("index_player_character", "player_id", "character_id", unique=True),
|
||||||
|
dict(mysql_charset="utf8mb4", mysql_collate="utf8mb4_general_ci"),
|
||||||
|
)
|
||||||
id: Optional[int] = Field(default=None, sa_column=Column(Integer, primary_key=True, autoincrement=True))
|
id: Optional[int] = Field(default=None, sa_column=Column(Integer, primary_key=True, autoincrement=True))
|
||||||
player_id: int = Field(sa_column=Column(BigInteger(), primary_key=True))
|
player_id: int = Field(sa_column=Column(BigInteger()))
|
||||||
character_id: int = Field(sa_column=Column(BigInteger(), primary_key=True))
|
character_id: int = Field(sa_column=Column(BigInteger()))
|
||||||
data: Optional[str] = Field(sa_column=Column(String(length=4096)))
|
data: Optional[str] = Field(sa_column=Column(String(length=4096)))
|
||||||
time_updated: Optional[datetime] = Field(sa_column=Column(DateTime, onupdate=func.now())) # pylint: disable=E1102
|
time_updated: Optional[datetime] = Field(sa_column=Column(DateTime, onupdate=func.now())) # pylint: disable=E1102
|
||||||
|
|
||||||
@ -61,7 +64,7 @@ class CharacterDetails(Plugin):
|
|||||||
) -> None:
|
) -> None:
|
||||||
self.mysql = mysql
|
self.mysql = mysql
|
||||||
self.redis = redis.client
|
self.redis = redis.client
|
||||||
self.ttl = 60 * 60 * 3
|
self.ttl = 60 * 60 * 6
|
||||||
|
|
||||||
async def initialize(self) -> None:
|
async def initialize(self) -> None:
|
||||||
def fetch_and_update_objects(connection):
|
def fetch_and_update_objects(connection):
|
||||||
@ -108,18 +111,34 @@ class CharacterDetails(Plugin):
|
|||||||
ttl = await self.redis.ttl(key)
|
ttl = await self.redis.ttl(key)
|
||||||
if max_ttl is None or (0 <= ttl <= max_ttl):
|
if max_ttl is None or (0 <= ttl <= max_ttl):
|
||||||
try:
|
try:
|
||||||
uid, character_id = re.findall(r"\d+", key)
|
player_id, character_id = re.findall(r"\d+", key)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logger.warning("非法Key %s", key)
|
logger.warning("非法Key %s", key)
|
||||||
continue
|
continue
|
||||||
data = await self.redis.get(key)
|
data = await self.redis.get(key)
|
||||||
str_data = str(data, encoding="utf-8")
|
str_data = str(data, encoding="utf-8")
|
||||||
sql_data = CharacterDetailsSQLModel(
|
|
||||||
player_id=uid, character_id=character_id, data=str_data, time_updated=datetime.now()
|
|
||||||
)
|
|
||||||
async with AsyncSession(self.mysql.engine) as session:
|
async with AsyncSession(self.mysql.engine) as session:
|
||||||
await session.merge(sql_data)
|
statement = (
|
||||||
await session.commit()
|
select(CharacterDetailsSQLModel)
|
||||||
|
.where(CharacterDetailsSQLModel.player_id == player_id)
|
||||||
|
.where(CharacterDetailsSQLModel.character_id == character_id)
|
||||||
|
)
|
||||||
|
results = await session.exec(statement)
|
||||||
|
sql_data = results.first()
|
||||||
|
if sql_data is None:
|
||||||
|
sql_data = CharacterDetailsSQLModel(
|
||||||
|
player_id=player_id, character_id=character_id, data=str_data, time_updated=datetime.now()
|
||||||
|
)
|
||||||
|
async with AsyncSession(self.mysql.engine) as session:
|
||||||
|
session.add(sql_data)
|
||||||
|
await session.commit()
|
||||||
|
else:
|
||||||
|
if sql_data.time_updated <= datetime.now() - timedelta(hours=2):
|
||||||
|
sql_data.data = str_data
|
||||||
|
sql_data.time_updated = datetime.now()
|
||||||
|
async with AsyncSession(self.mysql.engine) as session:
|
||||||
|
session.add(sql_data)
|
||||||
|
await session.commit()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_qname(uid: int, character: int):
|
def get_qname(uid: int, character: int):
|
||||||
@ -143,12 +162,6 @@ class CharacterDetails(Plugin):
|
|||||||
self.get_qname(uid, character_id), detail.json(), ex=self.ttl + randint * 60 # 使用随机数防止缓存雪崩
|
self.get_qname(uid, character_id), detail.json(), ex=self.ttl + randint * 60 # 使用随机数防止缓存雪崩
|
||||||
)
|
)
|
||||||
|
|
||||||
async def set_character_details_for_mysql(self, uid: int, character_id: int, detail: "CalculatorCharacterDetails"):
|
|
||||||
data = CharacterDetailsSQLModel(player_id=uid, character_id=character_id, data=detail.json())
|
|
||||||
async with AsyncSession(self.mysql.engine) as session:
|
|
||||||
await session.merge(data)
|
|
||||||
await session.commit()
|
|
||||||
|
|
||||||
async def get_character_details_for_mysql(
|
async def get_character_details_for_mysql(
|
||||||
self,
|
self,
|
||||||
uid: int,
|
uid: int,
|
||||||
|
Loading…
Reference in New Issue
Block a user