fix(multiplayer): fence client queue cancellation states

This commit is contained in:
Josh Creek
2026-09-03 00:15:41 +01:00
parent 1976c6eac6
commit a15368ed29
6 changed files with 75 additions and 6 deletions
+18 -2
View File
@@ -388,8 +388,8 @@ func TestPostgreSQLQueueHeartbeatAndCancelAreRevisionFenced(t *testing.T) {
if heartbeat.Revision != 1 || !heartbeat.ExpiresAt.Equal(now.Add(35*time.Second)) {
t.Fatalf("unexpected heartbeat result: %+v", heartbeat)
}
if _, err := HeartbeatQueueTicket(ctx, db, "heartbeat-player", "heartbeat-ticket", "heartbeat-op-0000002", 0, now.Add(6*time.Second)); err == nil {
t.Fatal("stale heartbeat revision was accepted")
if _, err := HeartbeatQueueTicket(ctx, db, "heartbeat-player", "heartbeat-ticket", "heartbeat-op-0000002", 0, now.Add(6*time.Second)); !errors.Is(err, domain.ErrStaleRevision) {
t.Fatalf("stale heartbeat error = %v, want ErrStaleRevision", err)
}
cancelled, err := CancelQueueTicket(ctx, db, "heartbeat-player", "heartbeat-ticket", "heartbeat-op-0000003", 1, now.Add(7*time.Second))
if err != nil {
@@ -398,6 +398,22 @@ func TestPostgreSQLQueueHeartbeatAndCancelAreRevisionFenced(t *testing.T) {
if cancelled.State != domain.Cancelled || cancelled.Revision != 2 {
t.Fatalf("unexpected cancellation result: %+v", cancelled)
}
if _, err := db.ExecContext(ctx, `INSERT INTO identities (player_id, steam_id) VALUES ('live-cancel-player', 'live-cancel-steam')`); err != nil {
t.Fatal(err)
}
if _, err := db.ExecContext(ctx, `INSERT INTO queue_tickets (ticket_id, player_id, playlist, state, client_build, protocol_version, enqueued_at, expires_at) VALUES ('live-cancel-ticket', 'live-cancel-player', 'ranked', 'LIVE', 'integration-build', 1, $1, $2)`, now, now.Add(time.Minute)); err != nil {
t.Fatal(err)
}
if _, err := CancelQueueTicket(ctx, db, "live-cancel-player", "live-cancel-ticket", "live-cancel-op-0001", 0, now.Add(8*time.Second)); !errors.Is(err, domain.ErrConflict) {
t.Fatalf("live cancellation error = %v, want ErrConflict", err)
}
var liveState string
if err := db.QueryRow(`SELECT state FROM queue_tickets WHERE ticket_id = 'live-cancel-ticket'`).Scan(&liveState); err != nil {
t.Fatal(err)
}
if liveState != "LIVE" {
t.Fatalf("live ticket state = %s after cancellation attempt", liveState)
}
}
// TestPostgreSQLConcurrentQueueHeartbeatIsRevisionFencedUnderRealRace is the