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
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
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.
This commit is contained in:
@@ -166,14 +166,17 @@ func toWireState(s backendclient.StateResp) wire.StateView {
|
|||||||
// encodeMatch builds a MatchResult payload.
|
// encodeMatch builds a MatchResult payload.
|
||||||
func encodeMatch(m backendclient.MatchResp) []byte {
|
func encodeMatch(m backendclient.MatchResp) []byte {
|
||||||
b := flatbuffers.NewBuilder(512)
|
b := flatbuffers.NewBuilder(512)
|
||||||
matched := m.Matched && m.Game != nil
|
// Enqueue always lands the caller in a game; an open game awaiting an opponent reports
|
||||||
|
// matched=false but still carries it, so encode the game whenever it is present (else the
|
||||||
|
// client never receives it and cannot navigate in).
|
||||||
|
hasGame := m.Game != nil
|
||||||
var game flatbuffers.UOffsetT
|
var game flatbuffers.UOffsetT
|
||||||
if matched {
|
if hasGame {
|
||||||
game = buildGameView(b, *m.Game)
|
game = buildGameView(b, *m.Game)
|
||||||
}
|
}
|
||||||
fb.MatchResultStart(b)
|
fb.MatchResultStart(b)
|
||||||
fb.MatchResultAddMatched(b, matched)
|
fb.MatchResultAddMatched(b, m.Matched)
|
||||||
if matched {
|
if hasGame {
|
||||||
fb.MatchResultAddGame(b, game)
|
fb.MatchResultAddGame(b, game)
|
||||||
}
|
}
|
||||||
b.Finish(fb.MatchResultEnd(b))
|
b.Finish(fb.MatchResultEnd(b))
|
||||||
|
|||||||
@@ -114,6 +114,36 @@ func TestEnqueueRoundTripEncodesMatch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEnqueueEncodesOpenGameWhenNotMatched(t *testing.T) {
|
||||||
|
// An auto-match enqueue that opens a game awaiting an opponent returns matched=false but
|
||||||
|
// still carries the game; it must reach the client so it navigates into the game at once.
|
||||||
|
backend, cleanup := fakeBackend(t, func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
_, _ = w.Write([]byte(`{"matched":false,"game":{"id":"g-open","variant":"scrabble_en","status":"open","players":2,"to_move":0,"seats":[]}}`))
|
||||||
|
})
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
reg := transcode.NewRegistry(backend, nil)
|
||||||
|
op, _ := reg.Lookup(transcode.MsgLobbyEnqueue)
|
||||||
|
|
||||||
|
b := flatbuffers.NewBuilder(32)
|
||||||
|
v := b.CreateString("scrabble_en")
|
||||||
|
fb.EnqueueRequestStart(b)
|
||||||
|
fb.EnqueueRequestAddVariant(b, v)
|
||||||
|
b.Finish(fb.EnqueueRequestEnd(b))
|
||||||
|
|
||||||
|
payload, err := op.Handler(context.Background(), transcode.Request{Payload: b.FinishedBytes(), UserID: "u-1"})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("handler: %v", err)
|
||||||
|
}
|
||||||
|
m := fb.GetRootAsMatchResult(payload, 0)
|
||||||
|
if m.Matched() {
|
||||||
|
t.Fatal("an open game awaiting an opponent must report matched=false")
|
||||||
|
}
|
||||||
|
if g := m.Game(nil); g == nil || string(g.Id()) != "g-open" {
|
||||||
|
t.Fatalf("open game must be on the wire even when not matched: %+v", g)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestDomainErrorSurfacesBackendCode(t *testing.T) {
|
func TestDomainErrorSurfacesBackendCode(t *testing.T) {
|
||||||
backend, cleanup := fakeBackend(t, func(w http.ResponseWriter, r *http.Request) {
|
backend, cleanup := fakeBackend(t, func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusConflict)
|
w.WriteHeader(http.StatusConflict)
|
||||||
|
|||||||
Reference in New Issue
Block a user