fix(matchmaking): reset phase synchronously to stop stale-ready fast-join
CI/CD / CI - API (dotnet build + engine sim) (push) Successful in 3m27s
CI/CD / CI - Web (tsc + next build) (push) Successful in 1m16s
CI/CD / Deploy - local stack (db + server + web) (push) Successful in 1m2s

Leaving a match left mm.phase stuck on "ready". On the next league tap,
playLeague navigated to the matchmaking screen before svc.startMatchmaking
(which awaits connect+profile) could emit "searching" — so the screen mounted
with the old "ready" phase and its auto-enter effect instantly dropped the
player into a stale game with no lobby. Reset matchmaking to a fresh "searching"
state synchronously in the store before the async work to close the race.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-20 10:55:56 +03:30
parent 856fbab701
commit b12a7c7813
+8
View File
@@ -148,6 +148,14 @@ export const useOnlineStore = create<OnlineStore>((set, get) => ({
startMatchmaking: async (opts) => { startMatchmaking: async (opts) => {
const svc = getService(); const svc = getService();
if (mmUnsub) mmUnsub(); if (mmUnsub) mmUnsub();
// Reset to a fresh "searching" state SYNCHRONOUSLY before any async work. The
// matchmaking screen auto-enters the game when phase === "ready"; if a prior
// match left phase stuck on "ready", the screen would mount and fast-join a
// stale game before svc.startMatchmaking() (which awaits connect+profile) can
// emit "searching". Resetting here closes that race.
set({
matchmaking: { phase: "searching", players: [], elapsedMs: 0, ranked: opts.ranked, stake: opts.stake },
});
mmUnsub = svc.onMatchmaking((s) => set({ matchmaking: s })); mmUnsub = svc.onMatchmaking((s) => set({ matchmaking: s }));
await svc.startMatchmaking(opts); await svc.startMatchmaking(opts);
}, },