feat: game lobby service
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
package redisstate_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"galaxy/lobby/internal/adapters/redisstate"
|
||||
|
||||
"github.com/alicebob/miniredis/v2"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func newLagTestProbe(t *testing.T, now time.Time) (*redisstate.StreamLagProbe, *miniredis.Miniredis, *redis.Client) {
|
||||
t.Helper()
|
||||
server := miniredis.RunT(t)
|
||||
client := redis.NewClient(&redis.Options{Addr: server.Addr()})
|
||||
t.Cleanup(func() {
|
||||
_ = client.Close()
|
||||
})
|
||||
probe, err := redisstate.NewStreamLagProbe(client, func() time.Time { return now })
|
||||
require.NoError(t, err)
|
||||
return probe, server, client
|
||||
}
|
||||
|
||||
func TestStreamLagProbeReturnsAgeOfNextEntry(t *testing.T) {
|
||||
now := time.UnixMilli(2_000_000_000_000).UTC()
|
||||
probe, _, client := newLagTestProbe(t, now)
|
||||
ctx := context.Background()
|
||||
|
||||
addEntry := func(ms int64) string {
|
||||
id, err := client.XAdd(ctx, &redis.XAddArgs{
|
||||
Stream: "demo",
|
||||
ID: formatEntryID(ms, 0),
|
||||
Values: map[string]any{"k": "v"},
|
||||
}).Result()
|
||||
require.NoError(t, err)
|
||||
return id
|
||||
}
|
||||
|
||||
saved := addEntry(now.UnixMilli() - 5_000) // already processed
|
||||
addEntry(now.UnixMilli() - 1_500) // first unprocessed → 1.5s old
|
||||
|
||||
age, ok, err := probe.OldestUnprocessedAge(ctx, "demo", saved)
|
||||
require.NoError(t, err)
|
||||
require.True(t, ok)
|
||||
assert.InDelta(t, (1_500 * time.Millisecond).Milliseconds(), age.Milliseconds(), 50)
|
||||
}
|
||||
|
||||
func TestStreamLagProbeReturnsFalseWhenAtTail(t *testing.T) {
|
||||
now := time.UnixMilli(2_000_000_000_000).UTC()
|
||||
probe, _, client := newLagTestProbe(t, now)
|
||||
ctx := context.Background()
|
||||
|
||||
id, err := client.XAdd(ctx, &redis.XAddArgs{
|
||||
Stream: "demo",
|
||||
ID: formatEntryID(now.UnixMilli()-2_000, 0),
|
||||
Values: map[string]any{"k": "v"},
|
||||
}).Result()
|
||||
require.NoError(t, err)
|
||||
|
||||
age, ok, err := probe.OldestUnprocessedAge(ctx, "demo", id)
|
||||
require.NoError(t, err)
|
||||
require.False(t, ok)
|
||||
assert.Zero(t, age)
|
||||
}
|
||||
|
||||
func TestStreamLagProbeFallsBackToHeadOnEmptyOffset(t *testing.T) {
|
||||
now := time.UnixMilli(2_000_000_000_000).UTC()
|
||||
probe, _, client := newLagTestProbe(t, now)
|
||||
ctx := context.Background()
|
||||
|
||||
_, err := client.XAdd(ctx, &redis.XAddArgs{
|
||||
Stream: "demo",
|
||||
ID: formatEntryID(now.UnixMilli()-3_000, 0),
|
||||
Values: map[string]any{"k": "v"},
|
||||
}).Result()
|
||||
require.NoError(t, err)
|
||||
|
||||
age, ok, err := probe.OldestUnprocessedAge(ctx, "demo", "")
|
||||
require.NoError(t, err)
|
||||
require.True(t, ok)
|
||||
assert.InDelta(t, (3 * time.Second).Milliseconds(), age.Milliseconds(), 50)
|
||||
}
|
||||
|
||||
func TestStreamLagProbeReturnsFalseOnEmptyStream(t *testing.T) {
|
||||
now := time.UnixMilli(2_000_000_000_000).UTC()
|
||||
probe, _, _ := newLagTestProbe(t, now)
|
||||
ctx := context.Background()
|
||||
|
||||
age, ok, err := probe.OldestUnprocessedAge(ctx, "demo", "")
|
||||
require.NoError(t, err)
|
||||
require.False(t, ok)
|
||||
assert.Zero(t, age)
|
||||
}
|
||||
|
||||
func formatEntryID(ms int64, seq int64) string {
|
||||
return strconv.FormatInt(ms, 10) + "-" + strconv.FormatInt(seq, 10)
|
||||
}
|
||||
Reference in New Issue
Block a user