fix(server): game completion pipeline — stats recording + dict iteration safety
Three bugs prevented game stats from recording: 1. broadcast_game_state had game_over processing (log_game_end + stats) inside the per-player loop — if all players disconnected before the loop ran, stats never processed. Moved to run once before the loop. 2. room.broadcast and broadcast_game_state iterated players.items() without snapshotting, causing RuntimeError when concurrent player disconnects mutated the dict. Fixed with list(). 3. stats_service.process_game_from_state passed avg_round_score to a CASE expression without a type hint, causing asyncpg to fail with "could not determine data type of parameter $6". Added ::integer casts. Also wrapped per-player send_json calls in try/except so a single disconnected player doesn't abort the broadcast to remaining players. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -781,7 +781,7 @@ class StatsService:
|
||||
|
||||
# We don't have per-round data in legacy mode, so some stats are limited
|
||||
# Use total_score / num_rounds as an approximation for avg round score
|
||||
avg_round_score = total_score / num_rounds if num_rounds > 0 else None
|
||||
avg_round_score = total_score // num_rounds if num_rounds > 0 else total_score
|
||||
|
||||
# Update stats
|
||||
await conn.execute("""
|
||||
@@ -792,13 +792,13 @@ class StatsService:
|
||||
rounds_won = rounds_won + $4,
|
||||
total_points = total_points + $5,
|
||||
best_score = CASE
|
||||
WHEN best_score IS NULL THEN $6
|
||||
WHEN $6 IS NOT NULL AND $6 < best_score THEN $6
|
||||
WHEN best_score IS NULL THEN $6::integer
|
||||
WHEN $6::integer IS NOT NULL AND $6::integer < best_score THEN $6::integer
|
||||
ELSE best_score
|
||||
END,
|
||||
worst_score = CASE
|
||||
WHEN worst_score IS NULL THEN $7
|
||||
WHEN $7 IS NOT NULL AND $7 > worst_score THEN $7
|
||||
WHEN worst_score IS NULL THEN $7::integer
|
||||
WHEN $7::integer IS NOT NULL AND $7::integer > worst_score THEN $7::integer
|
||||
ELSE worst_score
|
||||
END,
|
||||
current_win_streak = CASE WHEN $2 = 1 THEN current_win_streak + 1 ELSE 0 END,
|
||||
|
||||
Reference in New Issue
Block a user