mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-11 00:14:00 +00:00
feat(multiplayer): publish allocation state events
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
@@ -45,7 +46,7 @@ const BindAllocatedMatchParticipantsSQL = `WITH bound AS (
|
||||
SELECT 1 FROM allocations
|
||||
WHERE allocation_id = $2 AND match_id = $1 AND server_id = $3 AND state = 'ALLOCATED'
|
||||
)
|
||||
RETURNING match_id
|
||||
RETURNING match_id, revision
|
||||
), participants AS (
|
||||
SELECT mp.ticket_id, mp.player_id
|
||||
FROM match_participants mp
|
||||
@@ -77,7 +78,13 @@ const AdvanceServerRegistrationSQL = `WITH matched AS (
|
||||
WHERE q.ticket_id = mp.ticket_id AND q.player_id = mp.player_id AND q.state = $3
|
||||
RETURNING q.ticket_id
|
||||
)
|
||||
SELECT (SELECT count(*) FROM matched), (SELECT count(*) FROM match_participants WHERE match_id = $1), (SELECT count(*) FROM advanced)`
|
||||
SELECT (SELECT count(*) FROM matched), (SELECT count(*) FROM match_participants WHERE match_id = $1), (SELECT count(*) FROM advanced), COALESCE((SELECT revision FROM matched), -1)`
|
||||
|
||||
const serverRegistrationParticipantIDsSQL = `SELECT player_id FROM match_participants WHERE match_id = $1 ORDER BY player_id`
|
||||
|
||||
const serverRegistrationOutboxSQL = `INSERT INTO outbox
|
||||
(event_id, aggregate_type, aggregate_id, revision, event_type, payload)
|
||||
VALUES ($1, 'match', $2, $3, 'state_changed', $4)`
|
||||
|
||||
const ServerRegistrationIdempotencyScope = "server.register"
|
||||
|
||||
@@ -120,13 +127,42 @@ func AdvanceServerRegistration(ctx context.Context, db *sql.DB, binding domain.W
|
||||
return nil
|
||||
}
|
||||
var matched, participants, advanced int
|
||||
if err := tx.QueryRowContext(ctx, AdvanceServerRegistrationSQL, binding.MatchID, binding.ServerID, from, to, binding.AllocationID, now, protocol).Scan(&matched, &participants, &advanced); err != nil {
|
||||
var revision int64
|
||||
if err := tx.QueryRowContext(ctx, AdvanceServerRegistrationSQL, binding.MatchID, binding.ServerID, from, to, binding.AllocationID, now, protocol).Scan(&matched, &participants, &advanced, &revision); err != nil {
|
||||
return err
|
||||
}
|
||||
if matched != 1 || participants == 0 || advanced != participants {
|
||||
return domain.ErrConflict
|
||||
}
|
||||
return nil
|
||||
rows, err := tx.QueryContext(ctx, serverRegistrationParticipantIDsSQL, binding.MatchID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
playerIDs := make([]string, 0, participants)
|
||||
for rows.Next() {
|
||||
var playerID string
|
||||
if err := rows.Scan(&playerID); err != nil {
|
||||
rows.Close()
|
||||
return err
|
||||
}
|
||||
playerIDs = append(playerIDs, playerID)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
rows.Close()
|
||||
return err
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
payload, err := json.Marshal(map[string]any{
|
||||
"event": "state_changed", "revision": revision, "resource_id": binding.MatchID,
|
||||
"occurred_at": now, "state": string(to), "match_id": binding.MatchID, "player_ids": playerIDs,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = tx.ExecContext(ctx, serverRegistrationOutboxSQL, fmt.Sprintf("match:%s:%d", binding.MatchID, revision), binding.MatchID, revision, payload)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user