mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-11 00:14:00 +00:00
feat(multiplayer): publish allocation progress events
This commit is contained in:
@@ -39,8 +39,8 @@ WHERE mp.match_id = $1
|
||||
ORDER BY q.client_build`
|
||||
|
||||
const BindAllocatedMatchParticipantsSQL = `WITH bound AS (
|
||||
UPDATE matches
|
||||
SET server_id = $3
|
||||
UPDATE matches
|
||||
SET server_id = $3, revision = revision + 1
|
||||
WHERE match_id = $1 AND state = 'ALLOCATING' AND allocation_id = $2 AND server_id IS NULL
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM allocations
|
||||
@@ -58,7 +58,7 @@ const BindAllocatedMatchParticipantsSQL = `WITH bound AS (
|
||||
WHERE q.ticket_id = p.ticket_id AND q.player_id = p.player_id AND q.state = 'ACCEPTED'
|
||||
RETURNING q.ticket_id
|
||||
)
|
||||
SELECT (SELECT count(*) FROM participants), (SELECT count(*) FROM advanced)`
|
||||
SELECT (SELECT count(*) FROM participants), (SELECT count(*) FROM advanced), COALESCE((SELECT revision FROM bound), -1)`
|
||||
|
||||
const ReleaseAllocatedMatchClaimSQL = `UPDATE matches
|
||||
SET allocation_id = NULL, allocation_claimed_at = NULL
|
||||
@@ -245,18 +245,47 @@ func ClaimAllocatingMatch(ctx context.Context, db *sql.DB, transport string, now
|
||||
}
|
||||
|
||||
func BindAllocatedMatch(ctx context.Context, db *sql.DB, allocation domain.Allocation) error {
|
||||
if db == nil || allocation.MatchID == "" || allocation.AllocationID == "" || allocation.ServerID == "" || allocation.State != domain.ServerAllocated {
|
||||
if db == nil || allocation.MatchID == "" || allocation.AllocationID == "" || allocation.ServerID == "" || allocation.State != domain.ServerAllocated || allocation.AllocatedAt.IsZero() {
|
||||
return fmt.Errorf("invalid allocated match binding")
|
||||
}
|
||||
return RunSerializable(ctx, db, DefaultSerializableAttempts, func(ctx context.Context, tx *sql.Tx) error {
|
||||
var participants, advanced int
|
||||
if err := tx.QueryRowContext(ctx, BindAllocatedMatchParticipantsSQL, allocation.MatchID, allocation.AllocationID, allocation.ServerID).Scan(&participants, &advanced); err != nil {
|
||||
var revision int64
|
||||
if err := tx.QueryRowContext(ctx, BindAllocatedMatchParticipantsSQL, allocation.MatchID, allocation.AllocationID, allocation.ServerID).Scan(&participants, &advanced, &revision); err != nil {
|
||||
return err
|
||||
}
|
||||
if participants == 0 || participants != advanced {
|
||||
return domain.ErrConflict
|
||||
}
|
||||
return nil
|
||||
rows, err := tx.QueryContext(ctx, serverRegistrationParticipantIDsSQL, allocation.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": allocation.MatchID,
|
||||
"occurred_at": allocation.AllocatedAt, "state": string(domain.Allocating), "match_id": allocation.MatchID, "player_ids": playerIDs,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = tx.ExecContext(ctx, serverRegistrationOutboxSQL, fmt.Sprintf("match:%s:%d", allocation.MatchID, revision), allocation.MatchID, revision, payload)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user