fix(server): mark games abandoned on room teardown + staging leaderboard

When handle_player_leave emptied a room or handle_end_game was invoked,
the room was removed from memory without touching games_v2. Periodic
cleanup only scans in-memory rooms, so those rows were stranded as
status='active' forever — staging had 42 orphans accumulated over 5h.

- event_store.update_game_abandoned: guarded UPDATE (status='active' only)
- GameLogger.log_game_abandoned{,_async}: fire-and-forget wrapper
- handle_end_game + handle_player_leave: flip status before remove_room
- LEADERBOARD_INCLUDE_TEST_DEFAULT: env override so staging can show
  soak-harness accounts by default; prod keeps them hidden

Verified on staging: 42 orphans swept on restart, soak accounts now
visible on /api/stats/leaderboard (rank 1-4).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
adlee-was-taken
2026-04-18 00:37:49 -04:00
parent 70498b1c33
commit d5f8eef6b3
7 changed files with 230 additions and 3 deletions

View File

@@ -171,6 +171,12 @@ class ServerConfig:
# Rate limiting
RATE_LIMIT_ENABLED: bool = True
# Leaderboard: include soak-harness test accounts by default when the
# client doesn't pass ?include_test. Production keeps this False so real
# users never see synthetic traffic; staging can flip it True so bring-up
# traffic actually shows on the board.
LEADERBOARD_INCLUDE_TEST_DEFAULT: bool = False
# Error tracking (Sentry)
SENTRY_DSN: str = ""
@@ -216,6 +222,7 @@ class ServerConfig:
MATCHMAKING_MAX_PLAYERS=get_env_int("MATCHMAKING_MAX_PLAYERS", 4),
ADMIN_EMAILS=admin_emails,
RATE_LIMIT_ENABLED=get_env_bool("RATE_LIMIT_ENABLED", True),
LEADERBOARD_INCLUDE_TEST_DEFAULT=get_env_bool("LEADERBOARD_INCLUDE_TEST_DEFAULT", False),
SENTRY_DSN=get_env("SENTRY_DSN", ""),
card_values=CardValues(
ACE=get_env_int("CARD_ACE", 1),