fix(ui): also resync an open game on a foreground regain without a stream drop
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 48s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 59s

Closes the residual tail of the previous commit: when the live stream stays
alive across a brief suspend (Telegram/iOS can pause the socket without tearing
it down), an in-game event shed from a full hub buffer is never recovered by
the reconnect refetch (no reconnect) or the open-game poll (it only runs while
the stream is down). Mirror the lobby's focus re-poll: bump app.resync on a
foreground regain that did not drop the stream, and have Game.svelte refetch
the open game once per resync. Also rescues a missed move/game_over after a
suspend. Add a silent-join mock seam + an e2e isolating this path; extend the
ARCHITECTURE §10 fallback note.
This commit is contained in:
Ilia Denisov
2026-06-14 00:14:49 +02:00
parent 16402e64c0
commit 4409253dce
6 changed files with 60 additions and 9 deletions
+12 -1
View File
@@ -55,6 +55,10 @@ export const app = $state<{
notifications: number;
/** Unread chat-message count per game id, for the in-game score-bar and 💬 badges. */
chatUnread: Record<string, number>;
/** Monotonic counter bumped when the app returns to the foreground without the live stream
* having dropped. An open game watches it to refetch once, recovering an in-game event shed
* from a full hub buffer while suspended (the stream-drop case is covered by streamAlive). */
resync: number;
}>({
ready: false,
streamAlive: false,
@@ -70,6 +74,7 @@ export const app = $state<{
localeLocked: false,
notifications: 0,
chatUnread: {},
resync: 0,
});
let unsubscribeStream: (() => void) | null = null;
@@ -104,7 +109,13 @@ function goForeground(): void {
backgrounded = false;
foregroundedAt = Date.now();
if (!app.session) return;
if (!app.streamAlive) openStream(); // silently re-establish a stream dropped while away
if (!app.streamAlive) {
openStream(); // re-establish a stream dropped while away (its reconnect refetch then runs)
} else {
// The stream stayed alive across the suspend, so the reconnect refetch will not fire — but an
// event may have been shed from a full hub buffer while away; nudge an open game to refetch.
app.resync++;
}
void refreshNotifications();
}