From f628061971db1fd19b2a9f25d4f0789d42ad39df Mon Sep 17 00:00:00 2001 From: MingxuanGame Date: Sat, 20 Dec 2025 19:42:14 +0800 Subject: [PATCH] feat(score_token): add room_id to score token table --- app/database/score.py | 6 ++-- app/database/score_token.py | 31 ++++++++--------- app/router/v2/score.py | 12 ++----- ...20_96c4f4b3f0ab_score_token_add_room_id.py | 34 +++++++++++++++++++ 4 files changed, 54 insertions(+), 29 deletions(-) create mode 100644 migrations/versions/2025-12-20_96c4f4b3f0ab_score_token_add_room_id.py diff --git a/app/database/score.py b/app/database/score.py index 6bb4a28..473f200 100644 --- a/app/database/score.py +++ b/app/database/score.py @@ -975,8 +975,6 @@ async def process_score( score_token: ScoreToken, info: SoloScoreSubmissionInfo, session: AsyncSession, - item_id: int | None = None, - room_id: int | None = None, ) -> Score: gamemode = GameMode.from_int(info.ruleset_id).to_special_mode(info.mods) logger.info( @@ -1014,8 +1012,8 @@ async def process_score( nsmall_tick_hit=info.statistics.get(HitResult.SMALL_TICK_HIT, 0), nlarge_tick_hit=info.statistics.get(HitResult.LARGE_TICK_HIT, 0), nslider_tail_hit=info.statistics.get(HitResult.SLIDER_TAIL_HIT, 0), - playlist_item_id=item_id, - room_id=room_id, + playlist_item_id=score_token.playlist_item_id, + room_id=score_token.room_id, maximum_statistics=info.maximum_statistics, processed=True, ranked=ranked, diff --git a/app/database/score_token.py b/app/database/score_token.py index f6762bb..8724bf2 100644 --- a/app/database/score_token.py +++ b/app/database/score_token.py @@ -13,17 +13,6 @@ from sqlmodel import BigInteger, Field, ForeignKey, Relationship, SQLModel class ScoreTokenBase(SQLModel, UTCBaseModel): - score_id: int | None = Field(sa_column=Column(BigInteger), default=None) - ruleset_id: GameMode - playlist_item_id: int | None = Field(default=None) # playlist - created_at: datetime = Field(default_factory=utcnow, sa_column=Column(DateTime)) - updated_at: datetime = Field(default_factory=utcnow, sa_column=Column(DateTime)) - - -class ScoreToken(ScoreTokenBase, table=True): - __tablename__: str = "score_tokens" - __table_args__ = (Index("idx_user_playlist", "user_id", "playlist_item_id"),) - id: int | None = Field( default=None, sa_column=Column( @@ -33,18 +22,28 @@ class ScoreToken(ScoreTokenBase, table=True): autoincrement=True, ), ) + score_id: int | None = Field(sa_column=Column(BigInteger), default=None) + ruleset_id: GameMode user_id: int = Field(sa_column=Column(BigInteger, ForeignKey("lazer_users.id"))) beatmap_id: int = Field(foreign_key="beatmaps.id") - user: Mapped[User] = Relationship() + room_id: int | None = Field(default=None) + playlist_item_id: int | None = Field(default=None) # playlist + created_at: datetime = Field(default_factory=utcnow, sa_column=Column(DateTime)) + updated_at: datetime = Field(default_factory=utcnow, sa_column=Column(DateTime)) + +class ScoreToken(ScoreTokenBase, table=True): + __tablename__: str = "score_tokens" + __table_args__ = ( + Index("idx_user_playlist", "user_id", "playlist_item_id"), + Index("idx_playlist_room", "playlist_item_id", "room_id"), + ) + + user: Mapped[User] = Relationship() beatmap: Mapped[Beatmap] = Relationship() class ScoreTokenResp(ScoreTokenBase): - id: int - user_id: int - beatmap_id: int - @classmethod def from_db(cls, obj: ScoreToken) -> "ScoreTokenResp": return cls.model_validate(obj) diff --git a/app/router/v2/score.py b/app/router/v2/score.py index fffcea2..80bee1a 100644 --- a/app/router/v2/score.py +++ b/app/router/v2/score.py @@ -123,14 +123,11 @@ async def _process_user(score_id: int, user_id: int, redis: Redis, fetcher: Fetc async def submit_score( background_task: BackgroundTasks, info: SoloScoreSubmissionInfo, - beatmap: int, token: int, current_user: User, db: AsyncSession, redis: Redis, fetcher: Fetcher, - item_id: int | None = None, - room_id: int | None = None, ): # 立即获取用户ID,避免后续的懒加载问题 user_id = current_user.id @@ -154,6 +151,7 @@ async def submit_score( if not score: raise HTTPException(status_code=404, detail="Score not found") else: + beatmap = score_token.beatmap_id try: cache_service = get_beatmap_cache_service(redis, fetcher) await cache_service.smart_preload_for_score(beatmap) @@ -172,8 +170,6 @@ async def submit_score( score_token, info, db, - item_id, - room_id, ) await db.refresh(score_token) score_id = score.id @@ -474,7 +470,7 @@ async def submit_solo_score( redis: Redis, fetcher: Fetcher, ): - return await submit_score(background_task, info, beatmap_id, token, current_user, db, redis, fetcher) + return await submit_score(background_task, info, token, current_user, db, redis, fetcher) @router.post( @@ -555,6 +551,7 @@ async def create_playlist_score( beatmap_id=beatmap_id, ruleset_id=GameMode.from_int(ruleset_id), playlist_item_id=playlist_id, + room_id=room_id, ) session.add(score_token) await session.commit() @@ -595,14 +592,11 @@ async def submit_playlist_score( score_resp = await submit_score( background_task, info, - item.beatmap_id, token, current_user, session, redis, fetcher, - item.id, - room_id, ) await process_playlist_best_score( room_id, diff --git a/migrations/versions/2025-12-20_96c4f4b3f0ab_score_token_add_room_id.py b/migrations/versions/2025-12-20_96c4f4b3f0ab_score_token_add_room_id.py new file mode 100644 index 0000000..f486459 --- /dev/null +++ b/migrations/versions/2025-12-20_96c4f4b3f0ab_score_token_add_room_id.py @@ -0,0 +1,34 @@ +"""score_token: add room_id + +Revision ID: 96c4f4b3f0ab +Revises: d430db6fc051 +Create Date: 2025-12-20 11:39:02.640676 + +""" + +from collections.abc import Sequence + +from alembic import op +import sqlalchemy as sa + +# revision identifiers, used by Alembic. +revision: str = "96c4f4b3f0ab" +down_revision: str | Sequence[str] | None = "d430db6fc051" +branch_labels: str | Sequence[str] | None = None +depends_on: str | Sequence[str] | None = None + + +def upgrade() -> None: + """Upgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.add_column("score_tokens", sa.Column("room_id", sa.Integer(), nullable=True)) + op.create_index("idx_playlist_room", "score_tokens", ["playlist_item_id", "room_id"], unique=False) + # ### end Alembic commands ### + + +def downgrade() -> None: + """Downgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.drop_index("idx_playlist_room", table_name="score_tokens") + op.drop_column("score_tokens", "room_id") + # ### end Alembic commands ###