Description
Two related reliability issues:
-
packages/server/game/hub.go:69-74 — When a client's Send
channel is full, the hub closes the channel and removes the client
from the room. The peer receives no error or game_over frame, so
the UI freezes with no indication.
-
packages/web/src/app/chess/page.tsx:31-71 — The frontend does
not reconnect on socket close. After a network blip, the player must
manually refresh the page to resume.
Proposed fix
Server:
- Replace silent close with a
WSMessage{Type: "disconnect", payload: {reason: "slow_consumer"}} sent best-effort before closing.
- Add a
pong handler and a read deadline on the websocket so dead
connections are detected within ~60s instead of relying on the
client's next write.
Client:
- Extract the WebSocket effect into
packages/web/src/hooks/useChessSocket.ts
(the empty hooks/ dir already exists for this).
- Implement exponential backoff reconnection (1s, 2s, 4s, 8s, cap at 30s).
- On reconnect, resend the
join frame; on receiving game_update for
the same gameId, re-hydrate state.
- Show a small "Reconnecting..." banner when
readyState is not OPEN.
Acceptance criteria
Files
packages/server/game/hub.go
packages/server/handler/websocket.go
packages/web/src/hooks/useChessSocket.ts (new)
packages/web/src/app/chess/page.tsx
Description
Two related reliability issues:
packages/server/game/hub.go:69-74— When a client'sSendchannel is full, the hub closes the channel and removes the client
from the room. The peer receives no
errororgame_overframe, sothe UI freezes with no indication.
packages/web/src/app/chess/page.tsx:31-71— The frontend doesnot reconnect on socket close. After a network blip, the player must
manually refresh the page to resume.
Proposed fix
Server:
WSMessage{Type: "disconnect", payload: {reason: "slow_consumer"}}sent best-effort before closing.ponghandler and a read deadline on the websocket so deadconnections are detected within ~60s instead of relying on the
client's next write.
Client:
packages/web/src/hooks/useChessSocket.ts(the empty
hooks/dir already exists for this).joinframe; on receivinggame_updateforthe same
gameId, re-hydrate state.readyStateis not OPEN.Acceptance criteria
Sendbuffer fills receives adisconnectframebefore the connection closes
transient network blip; the board re-syncs within 30s
useChessSockethook exists underpackages/web/src/hooks/Files
packages/server/game/hub.gopackages/server/handler/websocket.gopackages/web/src/hooks/useChessSocket.ts(new)packages/web/src/app/chess/page.tsx