mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
fix(multiplayer): converge events through REST
This commit is contained in:
@@ -13,8 +13,10 @@ import (
|
||||
// RunProposalOutboxDispatcher delivers committed proposal changes to the
|
||||
// authenticated WebSocket subscribers. It only reads proposal_changed rows;
|
||||
// result and other outbox event types remain owned by their own consumers.
|
||||
// Delivery is at-least-once because the row is acknowledged only after every
|
||||
// participant publication succeeds.
|
||||
// The outbox guarantees after-commit publication into this replica's bounded
|
||||
// transient hub; WebSocket receipt is deliberately best-effort. Clients use
|
||||
// owner-scoped periodic REST recovery for correctness across disconnects and
|
||||
// replicas, so a socket notification is only a latency optimization.
|
||||
func RunProposalOutboxDispatcher(ctx context.Context, db *sql.DB, service *Service) {
|
||||
if db == nil || service == nil {
|
||||
return
|
||||
|
||||
@@ -349,6 +349,7 @@ type queueCreateRequest struct {
|
||||
type queueResponse struct {
|
||||
TicketID string `json:"ticket_id"`
|
||||
PlayerID string `json:"player_id"`
|
||||
ProposalID string `json:"proposal_id,omitempty"`
|
||||
MatchID string `json:"match_id,omitempty"`
|
||||
State string `json:"state"`
|
||||
Revision uint64 `json:"revision"`
|
||||
@@ -1117,7 +1118,7 @@ func decodeBody(w http.ResponseWriter, r *http.Request, target any) bool {
|
||||
}
|
||||
|
||||
func toQueueResponse(ticket domain.QueueTicket) queueResponse {
|
||||
return queueResponse{TicketID: ticket.TicketID, PlayerID: ticket.PlayerID, MatchID: ticket.MatchID, Playlist: string(ticket.Playlist), State: string(ticket.State), Revision: ticket.Revision, EnqueuedAt: ticket.EnqueuedAt, ExpiresAt: ticket.ExpiresAt}
|
||||
return queueResponse{TicketID: ticket.TicketID, PlayerID: ticket.PlayerID, ProposalID: ticket.ProposalID, MatchID: ticket.MatchID, Playlist: string(ticket.Playlist), State: string(ticket.State), Revision: ticket.Revision, EnqueuedAt: ticket.EnqueuedAt, ExpiresAt: ticket.ExpiresAt}
|
||||
}
|
||||
|
||||
func toProposalResponse(proposal domain.Proposal) proposalResponse {
|
||||
|
||||
@@ -23,7 +23,10 @@ import (
|
||||
type queueBackendSpy struct{ createCalls, heartbeatCalls, cancelCalls, getCalls int }
|
||||
|
||||
func TestQueueResponseCarriesRecoveredMatchIdentity(t *testing.T) {
|
||||
response := toQueueResponse(domain.QueueTicket{TicketID: "ticket-1234567890", PlayerID: "player-1234567890", MatchID: "match-1234567890", State: domain.AssignmentReady})
|
||||
response := toQueueResponse(domain.QueueTicket{TicketID: "ticket-1234567890", PlayerID: "player-1234567890", ProposalID: "proposal-1234567890", MatchID: "match-1234567890", State: domain.AssignmentReady})
|
||||
if response.ProposalID != "proposal-1234567890" {
|
||||
t.Fatalf("queue response proposal ID = %q", response.ProposalID)
|
||||
}
|
||||
if response.MatchID != "match-1234567890" {
|
||||
t.Fatalf("queue response match ID = %q", response.MatchID)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user