feat(lobby): enter the game immediately and wait for the opponent inside it #51

Merged
developer merged 4 commits from feature/quick-game-open-wait into development 2026-06-13 09:14:51 +00:00
Owner

What

Quick auto-match no longer waits on a separate "searching" screen. Enqueue opens a real game seating the caller with an empty opponent seat (new game status open) and the player enters it at once — moving on their turn if it is theirs, otherwise watching their tiles. A second human searching the same variant+rule joins that open game; otherwise a background reaper seats a robot after a fixed 90 s + random 0–90 s wait (90–180 s total), pushing a new in-app opponent_joined event that fills the opponent card and re-enables resign and chat in place.

While a game is open: resign, chat and nudge are refused (no opponent yet); the lobby and opponent card show "searching for opponent"; New Game shows a line noting the wait can take a while and the app may be closed meanwhile. Friend games are unchanged.

Matchmaking state is now the open games in the database (the in-memory pool, lobby.poll and lobby.cancel are gone), concurrent enqueues serialised by a per-bucket advisory lock.

Schema (baseline edited — no prod data)

games.status gains open; game_players.account_id is nullable (the empty seat); games.open_deadline_at is the reaper's stamp. jet code regenerated.

⚠️ Contour: schema-change PR. After the deploy, the test contour needs DROP SCHEMA backend CASCADE + a backend restart so goose re-applies the edited baseline.

Tests (all green locally)

  • Backend: build/vet/gofmt; unit; integration (-tags=integration) incl. 10 new open-game cases (move while open, join after a move, resign/chat/nudge refused, reaper substitution, sweeper/driver skip, lobby empty seat).
  • UI: check, test:unit (161), build, bundle-gate (76/100 KB), Playwright e2e (108, Chromium + WebKit) incl. a new quick-match waiting -> joined spec.
  • No fbs/proto change (opponent_joined reuses the match_found payload), so codegen is unchanged.
## What Quick auto-match no longer waits on a separate "searching" screen. `Enqueue` opens a real game seating the caller with an **empty opponent seat** (new game status `open`) and the player enters it at once — moving on their turn if it is theirs, otherwise watching their tiles. A second human searching the same variant+rule **joins** that open game; otherwise a background reaper seats a **robot** after a fixed **90 s + random 0–90 s** wait (90–180 s total), pushing a new in-app **`opponent_joined`** event that fills the opponent card and re-enables resign and chat **in place**. While a game is `open`: resign, chat and nudge are refused (no opponent yet); the lobby and opponent card show "searching for opponent"; New Game shows a line noting the wait can take a while and the app may be closed meanwhile. Friend games are unchanged. Matchmaking state is now the **open games in the database** (the in-memory pool, `lobby.poll` and `lobby.cancel` are gone), concurrent enqueues serialised by a per-bucket advisory lock. ## Schema (baseline edited — no prod data) `games.status` gains `open`; `game_players.account_id` is **nullable** (the empty seat); `games.open_deadline_at` is the reaper's stamp. jet code regenerated. :warning: **Contour**: schema-change PR. After the deploy, the test contour needs `DROP SCHEMA backend CASCADE` + a backend restart so goose re-applies the edited baseline. ## Tests (all green locally) - **Backend**: build/vet/gofmt; unit; integration (`-tags=integration`) incl. 10 new open-game cases (move while open, join after a move, resign/chat/nudge refused, reaper substitution, sweeper/driver skip, lobby empty seat). - **UI**: check, test:unit (161), build, bundle-gate (76/100 KB), Playwright e2e (108, Chromium + WebKit) incl. a new quick-match waiting -> joined spec. - No fbs/proto change (`opponent_joined` reuses the match_found payload), so codegen is unchanged.
developer added 1 commit 2026-06-12 14:01:07 +00:00
feat(lobby): enter the game immediately and wait for the opponent inside it
CI / changes (pull_request) Successful in 1s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 14s
CI / ui (pull_request) Successful in 45s
CI / gate (pull_request) Successful in 1s
CI / deploy (pull_request) Successful in 1m4s
c305363ccd
Quick auto-match no longer waits on a separate screen: Enqueue opens a real game seating the caller with an empty opponent seat (new game status 'open') and the player enters it at once. A second human searching the same variant+rule joins that open game; otherwise a background reaper seats a robot after a 90s + random 0-90s wait, pushing a new in-app opponent_joined event that fills the opponent card and re-enables resign and chat in place.

Matchmaking state is now the open games in the database (the in-memory pool, lobby.poll and lobby.cancel are gone), serialised by a per-bucket advisory lock. While a game is open the starter may move on their turn, but resign, chat and nudge are refused; the lobby and opponent card show "searching for opponent".

Schema edited in the baseline (no prod data): 'open' status, nullable game_players.account_id for the empty seat, and a games.open_deadline_at stamp; jet code regenerated.
developer added 1 commit 2026-06-13 08:29:57 +00:00
fix(lobby): land in the opened game on enqueue + keep open games active in the lobby
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 10s
CI / integration (pull_request) Successful in 17s
CI / ui (pull_request) Successful in 45s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 58s
a3cb917ec7
Review fixes for open-game auto-match: decodeMatchResult dropped the game when matched=false (an open game awaiting an opponent), so the client never navigated into it - decode the game whenever present. The lobby grouped open games (status != 'active') into 'finished'; treat 'open' as in progress in groupGames/isMyTurn and resultBadge. The under-board status bar now reads "Opponent's turn" while the empty opponent seat is to move (instead of the searching placeholder). The New Game rule toggle is shown from the start when a Russian variant is available, so selecting a variant no longer shifts the layout.

Regression tests: codec (game decoded with matched=false), lobbysort + result (open is in progress), and the new-game e2e updated. UI-only; no backend or schema change.
developer added 1 commit 2026-06-13 08:50:17 +00:00
fix(gateway): put the opened game on the wire even when the enqueue is not yet matched
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 15s
CI / ui (pull_request) Successful in 46s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 57s
efaf633691
The real cause of 'Start game does not enter the game': encodeMatch gated the MatchResult game on matched (matched := m.Matched && m.Game != nil), so an open game awaiting an opponent (matched=false, game set) lost its game on the wire and the client had nothing to navigate into. Encode the game whenever m.Game is present; the backend's matched flag is authoritative. Regression test added (matched=false + game reaches the wire). The earlier codec fix guarded the same drop on the decode side.
developer added 1 commit 2026-06-13 09:08:58 +00:00
feat(admin): add an 'open' filter to the console games list
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 16s
CI / ui (pull_request) Successful in 45s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m8s
94534ad0f2
The games-list status filter offered only active/finished; add 'open' (auto-match games awaiting an opponent) to the subnav and accept it in normalizeGameStatus. Render test covers the new filter link.
owner approved these changes 2026-06-13 09:12:38 +00:00
developer merged commit 1d41cf8222 into development 2026-06-13 09:14:51 +00:00
developer deleted branch feature/quick-game-open-wait 2026-06-13 09:14:51 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: developer/scrabble-game#51