feat: wire API queue projection to Redis

This commit is contained in:
Josh Creek
2026-09-01 09:28:49 +01:00
parent fe9f6f3cb5
commit 18538e833b
5 changed files with 119 additions and 5 deletions
+60
View File
@@ -19,6 +19,23 @@ import (
type queueBackendSpy struct{ createCalls, heartbeatCalls, cancelCalls, getCalls int }
type candidateIndexSpy struct {
upsertCalls, removeCalls int
upsertErr, removeErr error
last domain.Candidate
}
func (i *candidateIndexSpy) Upsert(_ context.Context, candidate domain.Candidate) error {
i.upsertCalls++
i.last = candidate
return i.upsertErr
}
func (i *candidateIndexSpy) Remove(_ context.Context, _ string) error {
i.removeCalls++
return i.removeErr
}
type sessionBackendSpy struct{ calls int }
type proposalBackendSpy struct {
@@ -612,6 +629,49 @@ func TestQueueAPIUsesInjectedPersistentBackendWithoutCandidateProvider(t *testin
}
}
func TestQueueAPIProjectsSuccessfulMutationsWithoutMakingRedisRequired(t *testing.T) {
now := time.Unix(1000, 0).UTC()
sessions := domain.NewSessionStore()
session, token, _ := sessions.Issue("player-1", time.Hour, now)
backend := &queueBackendSpy{}
index := &candidateIndexSpy{upsertErr: errors.New("redis unavailable"), removeErr: errors.New("redis unavailable")}
service := &Service{Sessions: sessions, QueueBackend: backend, CandidateIndex: index, Now: func() time.Time { return now }}
server := httptest.NewServer(service.Handler())
defer server.Close()
auth := "Bearer " + session.SessionID + ":" + token
request := func(method, path, key, revision string) *http.Response {
req, _ := http.NewRequest(method, server.URL+path, strings.NewReader(`{"ticket_id":"ticket-1","playlist":"ranked","client_build":"build-1","protocol_version":1}`))
req.Header.Set("Authorization", auth)
if key != "" {
req.Header.Set("Idempotency-Key", key)
}
if revision != "" {
req.Header.Set("If-Match-Revision", revision)
}
response, err := http.DefaultClient.Do(req)
if err != nil {
t.Fatal(err)
}
return response
}
response := request(http.MethodPost, "/v1/queue", "create-key-123456", "")
if response.StatusCode != http.StatusCreated {
t.Fatalf("create status=%d", response.StatusCode)
}
response.Body.Close()
if index.upsertCalls != 1 {
t.Fatalf("upsert calls=%d", index.upsertCalls)
}
response = request(http.MethodPost, "/v1/queue/ticket-1/cancel", "cancel-key-123456", "0")
if response.StatusCode != http.StatusOK {
t.Fatalf("cancel status=%d", response.StatusCode)
}
response.Body.Close()
if index.removeCalls != 1 {
t.Fatalf("remove calls=%d", index.removeCalls)
}
}
func TestQueueAPIDelegatesAllMutationsAndRecoveryToBackend(t *testing.T) {
now := time.Unix(1000, 0).UTC()
sessions := domain.NewSessionStore()