mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-11 08:23:45 +00:00
fix(multiplayer): repair PostgreSQL integration invariants
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -288,7 +289,7 @@ func TestPostgreSQLAllocationMatchClaimLeaseAndBindFence(t *testing.T) {
|
||||
}
|
||||
}
|
||||
claim, found, err := ClaimAllocatingMatch(ctx, db, "enet", now)
|
||||
if err != nil || !found || claim.Request != (domain.AllocationRequest{AllocationID: "allocation-allocation-match", MatchID: "allocation-match", Region: "EU", Build: "build-1", Protocol: 1, Transport: "enet"}) {
|
||||
if err != nil || !found || claim.Request != (domain.AllocationRequest{AllocationID: "allocation-allocation-match", MatchID: "allocation-match", Playlist: domain.Casual, Region: "EU", Build: "build-1", Protocol: 1, Transport: "enet"}) {
|
||||
t.Fatalf("claim=%+v found=%t err=%v", claim, found, err)
|
||||
}
|
||||
if err := ReleaseAllocatedMatchClaim(ctx, db, claim.Request.MatchID, "different-allocation"); err != domain.ErrConflict {
|
||||
@@ -325,7 +326,18 @@ func TestPostgreSQLAllocationMatchClaimLeaseAndBindFence(t *testing.T) {
|
||||
if err := db.QueryRowContext(ctx, `SELECT event_type, payload FROM outbox WHERE aggregate_id = 'allocation-match' AND event_type = 'state_changed'`).Scan(&eventType, &eventPayload); err != nil {
|
||||
t.Fatalf("allocation outbox event: %v", err)
|
||||
}
|
||||
if eventType != "state_changed" || !strings.Contains(string(eventPayload), `"state":"ALLOCATING"`) || !strings.Contains(string(eventPayload), `"allocation-match-a"`) || !strings.Contains(string(eventPayload), `"allocation-match-b"`) {
|
||||
var event struct {
|
||||
State string `json:"state"`
|
||||
PlayerIDs []string `json:"player_ids"`
|
||||
}
|
||||
if err := json.Unmarshal(eventPayload, &event); err != nil {
|
||||
t.Fatalf("decode allocation outbox event: %v", err)
|
||||
}
|
||||
players := make(map[string]bool, len(event.PlayerIDs))
|
||||
for _, playerID := range event.PlayerIDs {
|
||||
players[playerID] = true
|
||||
}
|
||||
if eventType != "state_changed" || event.State != "ALLOCATING" || !players["allocation-match-a"] || !players["allocation-match-b"] {
|
||||
t.Fatalf("allocation outbox event = %s", eventPayload)
|
||||
}
|
||||
if _, found, err := ClaimAllocatingMatch(ctx, db, "enet", now.Add(2*time.Second)); err != nil || found {
|
||||
@@ -588,12 +600,15 @@ func TestPostgreSQLConnectionReceiptsStartCompleteRelaxedCasualRoster(t *testing
|
||||
if _, err := db.ExecContext(ctx, `INSERT INTO game_servers (server_id, region, build, protocol_version, transport, state) VALUES ('connect-server', 'EU', 'integration-build', 1, 'enet', 'ALLOCATED')`); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := db.ExecContext(ctx, `INSERT INTO matches (match_id, playlist, state, region, protocol_version, server_id, allocation_id, initial_connect_ready_at) VALUES ('connect-match', 'casual', 'ASSIGNMENT_READY', 'EU', 1, 'connect-server', 'connect-allocation', $1)`, now); err != nil {
|
||||
if _, err := db.ExecContext(ctx, `INSERT INTO matches (match_id, playlist, state, region, protocol_version) VALUES ('connect-match', 'casual', 'ALLOCATING', 'EU', 1)`); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := db.ExecContext(ctx, `INSERT INTO allocations (allocation_id, match_id, server_id, region, build, protocol_version, transport, request_digest, state, allocated_at) VALUES ('connect-allocation', 'connect-match', 'connect-server', 'EU', 'integration-build', 1, 'enet', $1, 'ALLOCATED', $2)`, []byte("request"), now); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := db.ExecContext(ctx, `UPDATE matches SET state = 'ASSIGNMENT_READY', server_id = 'connect-server', allocation_id = 'connect-allocation', allocation_claimed_at = $1, initial_connect_ready_at = $1 WHERE match_id = 'connect-match'`, now); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i := 0; i < 2; i++ {
|
||||
playerID := fmt.Sprintf("connect-player-%d", i)
|
||||
ticketID := fmt.Sprintf("connect-ticket-%d", i)
|
||||
@@ -662,7 +677,7 @@ func TestPostgreSQLLiveReconnectGraceExpiryPersistsAbandonmentWithoutReleasingRe
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
if _, err := db.ExecContext(ctx, `INSERT INTO matches (match_id, playlist, state, region, protocol_version, server_id) VALUES ('live-abandon-match', 'ranked', 'LIVE', 'EU', 1, 'live-abandon-server')`); err != nil {
|
||||
if _, err := db.ExecContext(ctx, `INSERT INTO matches (match_id, playlist, state, region, protocol_version, server_id, arena_path) VALUES ('live-abandon-match', 'ranked', 'LIVE', 'EU', 1, 'live-abandon-server', 'res://scenes/arena_01.tscn')`); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := db.ExecContext(ctx, `INSERT INTO match_participants (match_id, player_id, ticket_id, slot, team, connection_generation, connected_at, disconnected_at) VALUES
|
||||
@@ -1523,7 +1538,18 @@ func TestPostgreSQLStalledAllocationsAreReclaimedWithoutPenalisingPlayers(t *tes
|
||||
if err := db.QueryRow(`SELECT event_type, payload FROM outbox WHERE event_id = 'stalled-allocation:stalled-match:1'`).Scan(&eventType, &eventPayload); err != nil {
|
||||
t.Fatalf("stalled allocation state event missing: %v", err)
|
||||
}
|
||||
if eventType != "state_changed" || !strings.Contains(string(eventPayload), `"state":"FAILED"`) || !strings.Contains(string(eventPayload), `"stall-player-a"`) {
|
||||
var event struct {
|
||||
State string `json:"state"`
|
||||
PlayerIDs []string `json:"player_ids"`
|
||||
}
|
||||
if err := json.Unmarshal(eventPayload, &event); err != nil {
|
||||
t.Fatalf("decode stalled allocation outbox event: %v", err)
|
||||
}
|
||||
players := make(map[string]bool, len(event.PlayerIDs))
|
||||
for _, playerID := range event.PlayerIDs {
|
||||
players[playerID] = true
|
||||
}
|
||||
if eventType != "state_changed" || event.State != "FAILED" || !players["stall-player-a"] {
|
||||
t.Fatalf("stalled allocation event = %s %s, want FAILED state and affected player IDs", eventType, eventPayload)
|
||||
}
|
||||
|
||||
@@ -1653,8 +1679,8 @@ func TestPostgreSQLMigrationsRollBackAndReapplyCleanly(t *testing.T) {
|
||||
// Roll back every migration one at a time, in reverse, checking each
|
||||
// down file actually undoes what its forward file created — not just
|
||||
// that Rollback returns nil.
|
||||
if err := migrations.Rollback(context.Background(), db, dir, 4); err != nil {
|
||||
t.Fatalf("rollback 0010 through 0007: %v", err)
|
||||
if err := migrations.Rollback(context.Background(), db, dir, 7); err != nil {
|
||||
t.Fatalf("rollback 0013 through 0007: %v", err)
|
||||
}
|
||||
var hasInitialConnectReadyColumn bool
|
||||
if err := db.QueryRow(`SELECT count(*) > 0 FROM information_schema.columns WHERE table_name = 'matches' AND column_name = 'initial_connect_ready_at'`).Scan(&hasInitialConnectReadyColumn); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user