修复多人游戏成绩上传报错
This commit is contained in:
@@ -292,6 +292,9 @@ class ScoreResp(ScoreBase):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def from_db(cls, session: AsyncSession, score: Score) -> "ScoreResp":
|
async def from_db(cls, session: AsyncSession, score: Score) -> "ScoreResp":
|
||||||
|
# 确保 score 对象完全加载,避免懒加载问题
|
||||||
|
await session.refresh(score)
|
||||||
|
|
||||||
s = cls.model_validate(score.model_dump())
|
s = cls.model_validate(score.model_dump())
|
||||||
assert score.id
|
assert score.id
|
||||||
await score.awaitable_attrs.beatmap
|
await score.awaitable_attrs.beatmap
|
||||||
|
|||||||
@@ -97,6 +97,9 @@ async def submit_score(
|
|||||||
item_id: int | None = None,
|
item_id: int | None = None,
|
||||||
room_id: int | None = None,
|
room_id: int | None = None,
|
||||||
):
|
):
|
||||||
|
# 立即获取用户ID,避免后续的懒加载问题
|
||||||
|
user_id = current_user.id
|
||||||
|
|
||||||
if not info.passed:
|
if not info.passed:
|
||||||
info.rank = Rank.F
|
info.rank = Rank.F
|
||||||
score_token = (
|
score_token = (
|
||||||
@@ -106,14 +109,14 @@ async def submit_score(
|
|||||||
.where(ScoreToken.id == token)
|
.where(ScoreToken.id == token)
|
||||||
)
|
)
|
||||||
).first()
|
).first()
|
||||||
if not score_token or score_token.user_id != current_user.id:
|
if not score_token or score_token.user_id != user_id:
|
||||||
raise HTTPException(status_code=404, detail="Score token not found")
|
raise HTTPException(status_code=404, detail="Score token not found")
|
||||||
if score_token.score_id:
|
if score_token.score_id:
|
||||||
score = (
|
score = (
|
||||||
await db.exec(
|
await db.exec(
|
||||||
select(Score).where(
|
select(Score).where(
|
||||||
Score.id == score_token.score_id,
|
Score.id == score_token.score_id,
|
||||||
Score.user_id == current_user.id,
|
Score.user_id == user_id,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
).first()
|
).first()
|
||||||
@@ -169,6 +172,7 @@ async def submit_score(
|
|||||||
.where(Score.id == score_id)
|
.where(Score.id == score_id)
|
||||||
)).first()
|
)).first()
|
||||||
assert score is not None
|
assert score is not None
|
||||||
|
|
||||||
resp = await ScoreResp.from_db(db, score)
|
resp = await ScoreResp.from_db(db, score)
|
||||||
total_users = (await db.exec(select(func.count()).select_from(User))).first()
|
total_users = (await db.exec(select(func.count()).select_from(User))).first()
|
||||||
assert total_users is not None
|
assert total_users is not None
|
||||||
@@ -195,14 +199,15 @@ async def submit_score(
|
|||||||
await db.commit()
|
await db.commit()
|
||||||
|
|
||||||
# 成绩提交后刷新用户缓存 - 移至后台任务避免阻塞主流程
|
# 成绩提交后刷新用户缓存 - 移至后台任务避免阻塞主流程
|
||||||
# 预先获取用户ID避免在后台任务中触发延迟加载
|
# 预先获取游戏模式,避免在后台任务中触发延迟加载
|
||||||
user_id = current_user.id
|
score_gamemode = score.gamemode
|
||||||
|
|
||||||
if user_id is not None:
|
if user_id is not None:
|
||||||
background_task.add_task(
|
background_task.add_task(
|
||||||
_refresh_user_cache_background,
|
_refresh_user_cache_background,
|
||||||
redis,
|
redis,
|
||||||
user_id,
|
user_id,
|
||||||
score.gamemode
|
score_gamemode
|
||||||
)
|
)
|
||||||
background_task.add_task(process_user_achievement, resp.id)
|
background_task.add_task(process_user_achievement, resp.id)
|
||||||
return resp
|
return resp
|
||||||
@@ -414,10 +419,13 @@ async def create_solo_score(
|
|||||||
current_user: User = Security(get_client_user),
|
current_user: User = Security(get_client_user),
|
||||||
):
|
):
|
||||||
assert current_user.id is not None
|
assert current_user.id is not None
|
||||||
|
# 立即获取用户ID,避免懒加载问题
|
||||||
|
user_id = current_user.id
|
||||||
|
|
||||||
background_task.add_task(_preload_beatmap_for_pp_calculation, beatmap_id)
|
background_task.add_task(_preload_beatmap_for_pp_calculation, beatmap_id)
|
||||||
async with db:
|
async with db:
|
||||||
score_token = ScoreToken(
|
score_token = ScoreToken(
|
||||||
user_id=current_user.id,
|
user_id=user_id,
|
||||||
beatmap_id=beatmap_id,
|
beatmap_id=beatmap_id,
|
||||||
ruleset_id=GameMode.from_int(ruleset_id),
|
ruleset_id=GameMode.from_int(ruleset_id),
|
||||||
)
|
)
|
||||||
@@ -469,6 +477,9 @@ async def create_playlist_score(
|
|||||||
current_user: User = Security(get_client_user),
|
current_user: User = Security(get_client_user),
|
||||||
):
|
):
|
||||||
assert current_user.id is not None
|
assert current_user.id is not None
|
||||||
|
# 立即获取用户ID,避免懒加载问题
|
||||||
|
user_id = current_user.id
|
||||||
|
|
||||||
room = await session.get(Room, room_id)
|
room = await session.get(Room, room_id)
|
||||||
if not room:
|
if not room:
|
||||||
raise HTTPException(status_code=404, detail="Room not found")
|
raise HTTPException(status_code=404, detail="Room not found")
|
||||||
@@ -498,7 +509,7 @@ async def create_playlist_score(
|
|||||||
agg = await session.exec(
|
agg = await session.exec(
|
||||||
select(ItemAttemptsCount).where(
|
select(ItemAttemptsCount).where(
|
||||||
ItemAttemptsCount.room_id == room_id,
|
ItemAttemptsCount.room_id == room_id,
|
||||||
ItemAttemptsCount.user_id == current_user.id,
|
ItemAttemptsCount.user_id == user_id,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
agg = agg.first()
|
agg = agg.first()
|
||||||
@@ -516,7 +527,7 @@ async def create_playlist_score(
|
|||||||
# 这里应该不用验证mod了吧。。。
|
# 这里应该不用验证mod了吧。。。
|
||||||
background_task.add_task(_preload_beatmap_for_pp_calculation, beatmap_id)
|
background_task.add_task(_preload_beatmap_for_pp_calculation, beatmap_id)
|
||||||
score_token = ScoreToken(
|
score_token = ScoreToken(
|
||||||
user_id=current_user.id,
|
user_id=user_id,
|
||||||
beatmap_id=beatmap_id,
|
beatmap_id=beatmap_id,
|
||||||
ruleset_id=GameMode.from_int(ruleset_id),
|
ruleset_id=GameMode.from_int(ruleset_id),
|
||||||
playlist_item_id=playlist_id,
|
playlist_item_id=playlist_id,
|
||||||
@@ -545,6 +556,10 @@ async def submit_playlist_score(
|
|||||||
fetcher: Fetcher = Depends(get_fetcher),
|
fetcher: Fetcher = Depends(get_fetcher),
|
||||||
):
|
):
|
||||||
assert current_user.id is not None
|
assert current_user.id is not None
|
||||||
|
|
||||||
|
# 立即获取用户ID,避免懒加载问题
|
||||||
|
user_id = current_user.id
|
||||||
|
|
||||||
item = (
|
item = (
|
||||||
await session.exec(
|
await session.exec(
|
||||||
select(Playlist).where(
|
select(Playlist).where(
|
||||||
@@ -558,8 +573,6 @@ async def submit_playlist_score(
|
|||||||
if not room:
|
if not room:
|
||||||
raise HTTPException(status_code=404, detail="Room not found")
|
raise HTTPException(status_code=404, detail="Room not found")
|
||||||
room_category = room.category
|
room_category = room.category
|
||||||
|
|
||||||
user_id = current_user.id
|
|
||||||
score_resp = await submit_score(
|
score_resp = await submit_score(
|
||||||
background_task,
|
background_task,
|
||||||
info,
|
info,
|
||||||
@@ -611,6 +624,9 @@ async def index_playlist_scores(
|
|||||||
),
|
),
|
||||||
current_user: User = Security(get_current_user, scopes=["public"]),
|
current_user: User = Security(get_current_user, scopes=["public"]),
|
||||||
):
|
):
|
||||||
|
# 立即获取用户ID,避免懒加载问题
|
||||||
|
user_id = current_user.id
|
||||||
|
|
||||||
room = await session.get(Room, room_id)
|
room = await session.get(Room, room_id)
|
||||||
if not room:
|
if not room:
|
||||||
raise HTTPException(status_code=404, detail="Room not found")
|
raise HTTPException(status_code=404, detail="Room not found")
|
||||||
@@ -637,7 +653,7 @@ async def index_playlist_scores(
|
|||||||
score_resp = [await ScoreResp.from_db(session, score.score) for score in scores]
|
score_resp = [await ScoreResp.from_db(session, score.score) for score in scores]
|
||||||
for score in score_resp:
|
for score in score_resp:
|
||||||
score.position = await get_position(room_id, playlist_id, score.id, session)
|
score.position = await get_position(room_id, playlist_id, score.id, session)
|
||||||
if score.user_id == current_user.id:
|
if score.user_id == user_id:
|
||||||
user_score = score
|
user_score = score
|
||||||
|
|
||||||
if room.category == RoomCategory.DAILY_CHALLENGE:
|
if room.category == RoomCategory.DAILY_CHALLENGE:
|
||||||
@@ -675,6 +691,9 @@ async def show_playlist_score(
|
|||||||
current_user: User = Security(get_client_user),
|
current_user: User = Security(get_client_user),
|
||||||
redis: Redis = Depends(get_redis),
|
redis: Redis = Depends(get_redis),
|
||||||
):
|
):
|
||||||
|
# 立即获取用户ID,避免懒加载问题
|
||||||
|
user_id = current_user.id
|
||||||
|
|
||||||
room = await session.get(Room, room_id)
|
room = await session.get(Room, room_id)
|
||||||
if not room:
|
if not room:
|
||||||
raise HTTPException(status_code=404, detail="Room not found")
|
raise HTTPException(status_code=404, detail="Room not found")
|
||||||
@@ -781,11 +800,14 @@ async def pin_score(
|
|||||||
score_id: int = Path(description="成绩 ID"),
|
score_id: int = Path(description="成绩 ID"),
|
||||||
current_user: User = Security(get_client_user),
|
current_user: User = Security(get_client_user),
|
||||||
):
|
):
|
||||||
|
# 立即获取用户ID,避免懒加载问题
|
||||||
|
user_id = current_user.id
|
||||||
|
|
||||||
score_record = (
|
score_record = (
|
||||||
await db.exec(
|
await db.exec(
|
||||||
select(Score).where(
|
select(Score).where(
|
||||||
Score.id == score_id,
|
Score.id == score_id,
|
||||||
Score.user_id == current_user.id,
|
Score.user_id == user_id,
|
||||||
col(Score.passed).is_(True),
|
col(Score.passed).is_(True),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -823,9 +845,12 @@ async def unpin_score(
|
|||||||
score_id: int = Path(description="成绩 ID"),
|
score_id: int = Path(description="成绩 ID"),
|
||||||
current_user: User = Security(get_client_user),
|
current_user: User = Security(get_client_user),
|
||||||
):
|
):
|
||||||
|
# 立即获取用户ID,避免懒加载问题
|
||||||
|
user_id = current_user.id
|
||||||
|
|
||||||
score_record = (
|
score_record = (
|
||||||
await db.exec(
|
await db.exec(
|
||||||
select(Score).where(Score.id == score_id, Score.user_id == current_user.id)
|
select(Score).where(Score.id == score_id, Score.user_id == user_id)
|
||||||
)
|
)
|
||||||
).first()
|
).first()
|
||||||
if not score_record:
|
if not score_record:
|
||||||
@@ -836,7 +861,7 @@ async def unpin_score(
|
|||||||
changed_score = (
|
changed_score = (
|
||||||
await db.exec(
|
await db.exec(
|
||||||
select(Score).where(
|
select(Score).where(
|
||||||
Score.user_id == current_user.id,
|
Score.user_id == user_id,
|
||||||
Score.pinned_order > score_record.pinned_order,
|
Score.pinned_order > score_record.pinned_order,
|
||||||
Score.gamemode == score_record.gamemode,
|
Score.gamemode == score_record.gamemode,
|
||||||
)
|
)
|
||||||
@@ -864,9 +889,12 @@ async def reorder_score_pin(
|
|||||||
before_score_id: int | None = Body(default=None, description="放在该成绩之前"),
|
before_score_id: int | None = Body(default=None, description="放在该成绩之前"),
|
||||||
current_user: User = Security(get_client_user),
|
current_user: User = Security(get_client_user),
|
||||||
):
|
):
|
||||||
|
# 立即获取用户ID,避免懒加载问题
|
||||||
|
user_id = current_user.id
|
||||||
|
|
||||||
score_record = (
|
score_record = (
|
||||||
await db.exec(
|
await db.exec(
|
||||||
select(Score).where(Score.id == score_id, Score.user_id == current_user.id)
|
select(Score).where(Score.id == score_id, Score.user_id == user_id)
|
||||||
)
|
)
|
||||||
).first()
|
).first()
|
||||||
if not score_record:
|
if not score_record:
|
||||||
@@ -957,6 +985,9 @@ async def download_score_replay(
|
|||||||
current_user: User = Security(get_current_user, scopes=["public"]),
|
current_user: User = Security(get_current_user, scopes=["public"]),
|
||||||
storage_service: StorageService = Depends(get_storage_service),
|
storage_service: StorageService = Depends(get_storage_service),
|
||||||
):
|
):
|
||||||
|
# 立即获取用户ID,避免懒加载问题
|
||||||
|
user_id = current_user.id
|
||||||
|
|
||||||
score = (await db.exec(select(Score).where(Score.id == score_id))).first()
|
score = (await db.exec(select(Score).where(Score.id == score_id))).first()
|
||||||
if not score:
|
if not score:
|
||||||
raise HTTPException(status_code=404, detail="Score not found")
|
raise HTTPException(status_code=404, detail="Score not found")
|
||||||
@@ -967,11 +998,11 @@ async def download_score_replay(
|
|||||||
raise HTTPException(status_code=404, detail="Replay file not found")
|
raise HTTPException(status_code=404, detail="Replay file not found")
|
||||||
|
|
||||||
is_friend = (
|
is_friend = (
|
||||||
score.user_id == current_user.id
|
score.user_id == user_id
|
||||||
or (
|
or (
|
||||||
await db.exec(
|
await db.exec(
|
||||||
select(exists()).where(
|
select(exists()).where(
|
||||||
Relationship.user_id == current_user.id,
|
Relationship.user_id == user_id,
|
||||||
Relationship.target_id == score.user_id,
|
Relationship.target_id == score.user_id,
|
||||||
Relationship.type == RelationshipType.FOLLOW,
|
Relationship.type == RelationshipType.FOLLOW,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user