mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-15 20:42:04 +00:00
feat: add rebuildable Redis candidate index
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/alicebob/miniredis/v2"
|
||||
"github.com/cosmic-clash/cosmic-clash/server/domain"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
func TestRedisCandidateIndexRebuildSnapshotAndRemove(t *testing.T) {
|
||||
mini, err := miniredis.Run()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer mini.Close()
|
||||
client := redis.NewClient(&redis.Options{Addr: mini.Addr()})
|
||||
defer client.Close()
|
||||
index := RedisCandidateIndex{Client: client, Prefix: "integration", TTL: time.Minute}
|
||||
now := time.Unix(1000, 0).UTC()
|
||||
candidates := []domain.Candidate{
|
||||
{TicketID: "ticket-b", PlayerID: "player-b", EnqueuedAt: now.Add(time.Second)},
|
||||
{TicketID: "ticket-a", PlayerID: "player-a", EnqueuedAt: now},
|
||||
}
|
||||
if err := index.Rebuild(context.Background(), candidates); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, err := index.Snapshot(context.Background(), now)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(got) != 1 || got[0].TicketID != "ticket-a" {
|
||||
t.Fatalf("snapshot before future candidate = %+v", got)
|
||||
}
|
||||
if err := index.Remove(context.Background(), "ticket-a"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, err = index.Snapshot(context.Background(), now.Add(2*time.Second))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(got) != 1 || got[0].TicketID != "ticket-b" {
|
||||
t.Fatalf("snapshot after remove = %+v", got)
|
||||
}
|
||||
if ttl, err := client.TTL(context.Background(), "integration:queue:candidates:data").Result(); err != nil || ttl <= 0 {
|
||||
t.Fatalf("candidate data TTL = %v, err = %v", ttl, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedisCandidateIndexRejectsInvalidAndDuplicateRebuilds(t *testing.T) {
|
||||
index := RedisCandidateIndex{TTL: time.Minute}
|
||||
if err := index.Rebuild(context.Background(), nil); err == nil {
|
||||
t.Fatal("nil Redis client accepted")
|
||||
}
|
||||
mini, err := miniredis.Run()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer mini.Close()
|
||||
client := redis.NewClient(&redis.Options{Addr: mini.Addr()})
|
||||
defer client.Close()
|
||||
index.Client = client
|
||||
candidate := domain.Candidate{TicketID: "ticket-a", PlayerID: "player-a", EnqueuedAt: time.Unix(1000, 0)}
|
||||
if err := index.Rebuild(context.Background(), []domain.Candidate{candidate, candidate}); err == nil {
|
||||
t.Fatal("duplicate candidate accepted")
|
||||
}
|
||||
if err := index.Upsert(context.Background(), domain.Candidate{TicketID: "", PlayerID: "player-a", EnqueuedAt: candidate.EnqueuedAt}); err == nil {
|
||||
t.Fatal("invalid candidate accepted")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user