mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-11 00:14:00 +00:00
fix(multiplayer): gate API readiness on database
This commit is contained in:
+31
-2
@@ -100,6 +100,7 @@ type AssignmentView struct {
|
||||
|
||||
type AssignmentProvider func(context.Context, string, string, time.Time) (AssignmentView, error)
|
||||
type RosterProvider func(context.Context, domain.WorkloadBinding, time.Time) ([][]byte, error)
|
||||
type ReadinessCheck func(context.Context) error
|
||||
|
||||
type Service struct {
|
||||
Sessions *domain.SessionStore
|
||||
@@ -129,6 +130,7 @@ type Service struct {
|
||||
RateLimiter *RateLimiter
|
||||
ClientIPs *ClientIPResolver
|
||||
Admission AdmissionController
|
||||
ReadinessCheck ReadinessCheck
|
||||
// Log receives a credential-safe structured event for lifecycle-relevant
|
||||
// reads and mutations. Nil
|
||||
// is a valid, silent no-op -- every call site must stay optional so
|
||||
@@ -185,6 +187,7 @@ func (s *Service) logProposalOutcome(proposalID string, proposal domain.Proposal
|
||||
func (s *Service) Handler() http.Handler {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/healthz", s.health)
|
||||
mux.HandleFunc("/readyz", s.ready)
|
||||
mux.HandleFunc("/metrics", s.metrics)
|
||||
mux.HandleFunc("/v1/session/steam", s.steamSession)
|
||||
mux.HandleFunc("/v1/queue", s.queueCreate)
|
||||
@@ -208,6 +211,10 @@ func (s *Service) Handler() http.Handler {
|
||||
var handler http.Handler = mux
|
||||
if s.RateLimiter != nil {
|
||||
handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == "/healthz" || r.URL.Path == "/readyz" || r.URL.Path == "/metrics" {
|
||||
mux.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
if !s.RateLimiter.AllowKeys(requestRateKeys(r, s.ClientIPs), s.now()) {
|
||||
writeError(w, http.StatusTooManyRequests, "rate_limited")
|
||||
return
|
||||
@@ -229,7 +236,7 @@ func (s *Service) Handler() http.Handler {
|
||||
return handler
|
||||
}
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == "/metrics" || r.URL.Path == "/healthz" || strings.HasSuffix(r.URL.Path, "/events") {
|
||||
if r.URL.Path == "/metrics" || r.URL.Path == "/healthz" || r.URL.Path == "/readyz" || strings.HasSuffix(r.URL.Path, "/events") {
|
||||
handler.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
@@ -337,10 +344,32 @@ func (s *Service) steamSession(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, map[string]any{"player_id": session.PlayerID, "expires_at": session.ExpiresAt, "access_token": session.SessionID + ":" + token})
|
||||
}
|
||||
|
||||
func (s *Service) health(w http.ResponseWriter, _ *http.Request) {
|
||||
func (s *Service) health(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
writeError(w, http.StatusMethodNotAllowed, "method_not_allowed")
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]string{"status": "ok"})
|
||||
}
|
||||
|
||||
func (s *Service) ready(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
writeError(w, http.StatusMethodNotAllowed, "method_not_allowed")
|
||||
return
|
||||
}
|
||||
if s.ReadinessCheck == nil {
|
||||
writeError(w, http.StatusServiceUnavailable, "not_ready")
|
||||
return
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(r.Context(), time.Second)
|
||||
defer cancel()
|
||||
if err := s.ReadinessCheck(ctx); err != nil {
|
||||
writeError(w, http.StatusServiceUnavailable, "not_ready")
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]string{"status": "ready"})
|
||||
}
|
||||
|
||||
type queueCreateRequest struct {
|
||||
TicketID string `json:"ticket_id"`
|
||||
Playlist string `json:"playlist"`
|
||||
|
||||
Reference in New Issue
Block a user