fix: preserve assignment event revisions

This commit is contained in:
Josh Creek
2026-09-01 08:13:35 +01:00
parent 23134796ee
commit 0cdb60c0d9
4 changed files with 27 additions and 2 deletions
+9 -1
View File
@@ -58,6 +58,10 @@ type AssignmentView struct {
ProtocolVersion int `json:"protocol_version"`
Transport string `json:"transport"`
JoinAuthorisation string `json:"join_authorisation"`
// Revision is routing metadata for the event stream, not part of the v1
// assignment response. Keeping it alongside the durable view prevents the
// REST recovery boundary from emitting a synthetic revision zero.
Revision uint64 `json:"-"`
}
type AssignmentProvider func(context.Context, string, string, time.Time) (AssignmentView, error)
@@ -509,10 +513,14 @@ func (s *Service) assignment(w http.ResponseWriter, r *http.Request) {
writeError(w, http.StatusServiceUnavailable, "assignment_unavailable")
return
}
_ = s.PublishControlPlaneEvent(ControlPlaneEvent{Event: "assignment_changed", Revision: 0, ResourceID: view.MatchID, OccurredAt: now, MatchID: view.MatchID, ServerID: view.ServerID, PlayerID: view.PlayerID})
_ = s.PublishControlPlaneEvent(assignmentChangedEvent(view, now))
writeJSON(w, http.StatusOK, view)
}
func assignmentChangedEvent(view AssignmentView, now time.Time) ControlPlaneEvent {
return ControlPlaneEvent{Event: "assignment_changed", Revision: view.Revision, ResourceID: view.MatchID, OccurredAt: now, MatchID: view.MatchID, ServerID: view.ServerID, PlayerID: view.PlayerID}
}
type rankedProfileResponse struct {
Rating float64 `json:"rating"`
RD float64 `json:"rd"`
+16
View File
@@ -983,3 +983,19 @@ func TestAssignmentRecoveryIsPlayerScopedAndRejectsExpiredOrMismatchedViews(t *t
t.Fatalf("expired assignment status=%d", status)
}
}
func TestAssignmentEventUsesAuthoritativeRevisionWithoutChangingResponseShape(t *testing.T) {
now := time.Unix(1000, 0).UTC()
view := AssignmentView{MatchID: "match-1", ServerID: "server-1", PlayerID: "player-a", Revision: 7}
event := assignmentChangedEvent(view, now)
if event.Revision != 7 || event.ResourceID != "match-1" || event.PlayerID != "player-a" {
t.Fatalf("assignment event = %+v", event)
}
payload, err := json.Marshal(view)
if err != nil {
t.Fatal(err)
}
if strings.Contains(string(payload), "revision") {
t.Fatalf("assignment response leaked event revision: %s", payload)
}
}
+1
View File
@@ -27,6 +27,7 @@ func AssignmentProviderFromStore(db *sql.DB) AssignmentProvider {
ProtocolVersion: assignment.ProtocolVersion,
Transport: assignment.Transport,
JoinAuthorisation: assignment.JoinAuthorisation,
Revision: assignment.Revision,
}, nil
}
}