From 56d6911589e3dc43f29179287e8a864d40c59c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=92=95=E8=B0=B7=E9=85=B1?= <74496778+GooGuJiang@users.noreply.github.com> Date: Sun, 24 Aug 2025 05:01:10 +0800 Subject: [PATCH] Add multiplayer room event model and channel ID allocation Introduces the MultiplayerRealtimeRoomEvent SQLModel for tracking real-time room events. Adds an async helper to allocate unique channel IDs for rooms, and updates room creation logic to use this helper for assigning channel IDs automatically. --- .../multiplayer_realtime_room_event.py | 39 +++++++++++++++++++ app/router/lio.py | 31 +++++++++------ 2 files changed, 58 insertions(+), 12 deletions(-) create mode 100644 app/database/multiplayer_realtime_room_event.py diff --git a/app/database/multiplayer_realtime_room_event.py b/app/database/multiplayer_realtime_room_event.py new file mode 100644 index 0000000..037a351 --- /dev/null +++ b/app/database/multiplayer_realtime_room_event.py @@ -0,0 +1,39 @@ +from datetime import datetime +from typing import Optional, ClassVar + +from sqlalchemy import Text +from sqlalchemy.ext.asyncio import AsyncAttrs +from sqlmodel import SQLModel, Field, Column, DateTime, BigInteger, ForeignKey + +from app.models.model import UTCBaseModel +from app.utils import utcnow + + +class MultiplayerRealtimeRoomEventBase(SQLModel, UTCBaseModel): + event_type: str = Field(index=True) + event_detail: Optional[str] = Field(default=None, sa_column=Column(Text)) + + +class MultiplayerRealtimeRoomEvent(AsyncAttrs, MultiplayerRealtimeRoomEventBase, table=True): + __tablename__: ClassVar[str] = "multiplayer_realtime_room_event" + + id: int | None = Field(default=None, primary_key=True, index=True) + + room_id: int = Field( + sa_column=Column(ForeignKey("rooms.id"), index=True, nullable=False) + ) + playlist_item_id: int | None = Field( + default=None, + sa_column=Column(ForeignKey("playlists.id"), index=True, nullable=True), + ) + user_id: int | None = Field( + default=None, + sa_column=Column(BigInteger, ForeignKey("lazer_users.id"), index=True, nullable=True), + ) + + created_at: datetime = Field( + sa_column=Column(DateTime(timezone=True)), default_factory=utcnow + ) + updated_at: datetime = Field( + sa_column=Column(DateTime(timezone=True)), default_factory=utcnow + ) diff --git a/app/router/lio.py b/app/router/lio.py index 322582f..17952f8 100644 --- a/app/router/lio.py +++ b/app/router/lio.py @@ -7,7 +7,7 @@ from typing import Any, Dict, List from fastapi import APIRouter, HTTPException, Request, status, Query, Depends from pydantic import BaseModel from sqlmodel import col, select, desc -from sqlalchemy import update +from sqlalchemy import update, func from redis.asyncio import Redis from app.database.lazer_user import User @@ -24,6 +24,15 @@ from app.utils import utcnow router = APIRouter(prefix="/_lio", tags=["LIO"]) + +async def _alloc_channel_id(db: Database) -> int: + """ + 自动分配一个 >100 的 channel_id。 + 策略:取当前 rooms.channel_id 的最大值(没有时从100开始)+1。 + """ + result = await db.execute(select(func.max(Room.channel_id))) + current_max = result.scalar() or 100 + return int(current_max) + 1 class RoomCreateRequest(BaseModel): """Request model for creating a multiplayer room.""" name: str @@ -140,7 +149,6 @@ def _validate_playlist_items(items: List[Dict[str, Any]]) -> None: async def _create_room(db: Database, room_data: Dict[str, Any]) -> tuple[Room, int]: - """Create a new multiplayer room.""" host_user_id = room_data.get("user_id") room_name = room_data.get("name", "Unnamed Room") password = room_data.get("password") @@ -148,18 +156,16 @@ async def _create_room(db: Database, room_data: Dict[str, Any]) -> tuple[Room, i queue_mode = room_data.get("queue_mode", "HostOnly") if not host_user_id or not isinstance(host_user_id, int): - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="Missing or invalid user_id" - ) + raise HTTPException(status_code=400, detail="Missing or invalid user_id") - # Validate host user exists await _validate_user_exists(db, host_user_id) - - # Parse room type enums + match_type_enum, queue_mode_enum = _parse_room_enums(match_type, queue_mode) - # Create room + # 自动分配一个 channel_id (>100) + channel_id = await _alloc_channel_id(db) + + # 创建房间 room = Room( name=room_name, host_id=host_user_id, @@ -170,12 +176,13 @@ async def _create_room(db: Database, room_data: Dict[str, Any]) -> tuple[Room, i participant_count=1, auto_skip=False, auto_start_duration=0, + channel_id=channel_id, ) - + db.add(room) await db.commit() await db.refresh(room) - + return room, host_user_id