refactor: player snapshot - cursor pagination
This commit is contained in:
parent
b6e46dee35
commit
41cb1d042e
|
@ -59,17 +59,22 @@ func (repo *PlayerSnapshotBunRepository) Create(
|
||||||
func (repo *PlayerSnapshotBunRepository) List(
|
func (repo *PlayerSnapshotBunRepository) List(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
params domain.ListPlayerSnapshotsParams,
|
params domain.ListPlayerSnapshotsParams,
|
||||||
) (domain.PlayerSnapshots, error) {
|
) (domain.ListPlayerSnapshotsResult, error) {
|
||||||
var playerSnapshots bunmodel.PlayerSnapshots
|
var playerSnapshots bunmodel.PlayerSnapshots
|
||||||
|
|
||||||
if err := repo.db.NewSelect().
|
if err := repo.db.NewSelect().
|
||||||
Model(&playerSnapshots).
|
Model(&playerSnapshots).
|
||||||
Apply(listPlayerSnapshotsParamsApplier{params: params}.apply).
|
Apply(listPlayerSnapshotsParamsApplier{params: params}.apply).
|
||||||
Scan(ctx); err != nil && !errors.Is(err, sql.ErrNoRows) {
|
Scan(ctx); err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||||
return nil, fmt.Errorf("couldn't select player snapshots from the db: %w", err)
|
return domain.ListPlayerSnapshotsResult{}, fmt.Errorf("couldn't select player snapshots from the db: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return playerSnapshots.ToDomain()
|
converted, err := playerSnapshots.ToDomain()
|
||||||
|
if err != nil {
|
||||||
|
return domain.ListPlayerSnapshotsResult{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain.NewListPlayerSnapshotsResult(separateListResultAndNext(converted, params.Limit()))
|
||||||
}
|
}
|
||||||
|
|
||||||
type listPlayerSnapshotsParamsApplier struct {
|
type listPlayerSnapshotsParamsApplier struct {
|
||||||
|
@ -81,6 +86,10 @@ func (a listPlayerSnapshotsParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQ
|
||||||
q = q.Where("ps.server_key IN (?)", bun.In(serverKeys))
|
q = q.Where("ps.server_key IN (?)", bun.In(serverKeys))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if playerIDs := a.params.PlayerIDs(); len(playerIDs) > 0 {
|
||||||
|
q = q.Where("ps.player_id IN (?)", bun.In(playerIDs))
|
||||||
|
}
|
||||||
|
|
||||||
for _, s := range a.params.Sort() {
|
for _, s := range a.params.Sort() {
|
||||||
column, dir, err := a.sortToColumnAndDirection(s)
|
column, dir, err := a.sortToColumnAndDirection(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -90,7 +99,49 @@ func (a listPlayerSnapshotsParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQ
|
||||||
q.OrderExpr("? ?", column, dir.Bun())
|
q.OrderExpr("? ?", column, dir.Bun())
|
||||||
}
|
}
|
||||||
|
|
||||||
return q.Limit(a.params.Limit()).Offset(a.params.Offset())
|
return q.Limit(a.params.Limit() + 1).Apply(a.applyCursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a listPlayerSnapshotsParamsApplier) applyCursor(q *bun.SelectQuery) *bun.SelectQuery {
|
||||||
|
cursor := a.params.Cursor()
|
||||||
|
|
||||||
|
if cursor.IsZero() {
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
sort := a.params.Sort()
|
||||||
|
cursorApplier := cursorPaginationApplier{
|
||||||
|
data: make([]cursorPaginationApplierDataElement, 0, len(sort)),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range sort {
|
||||||
|
var err error
|
||||||
|
var el cursorPaginationApplierDataElement
|
||||||
|
|
||||||
|
el.column, el.direction, err = a.sortToColumnAndDirection(s)
|
||||||
|
if err != nil {
|
||||||
|
return q.Err(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch s {
|
||||||
|
case domain.PlayerSnapshotSortIDASC,
|
||||||
|
domain.PlayerSnapshotSortIDDESC:
|
||||||
|
el.value = cursor.ID()
|
||||||
|
el.unique = true
|
||||||
|
case domain.PlayerSnapshotSortServerKeyASC,
|
||||||
|
domain.PlayerSnapshotSortServerKeyDESC:
|
||||||
|
el.value = cursor.ServerKey()
|
||||||
|
case domain.PlayerSnapshotSortDateASC,
|
||||||
|
domain.PlayerSnapshotSortDateDESC:
|
||||||
|
el.value = cursor.Date()
|
||||||
|
default:
|
||||||
|
return q.Err(fmt.Errorf("%s: %w", s.String(), errInvalidSortValue))
|
||||||
|
}
|
||||||
|
|
||||||
|
cursorApplier.data = append(cursorApplier.data, el)
|
||||||
|
}
|
||||||
|
|
||||||
|
return q.Apply(cursorApplier.apply)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a listPlayerSnapshotsParamsApplier) sortToColumnAndDirection(
|
func (a listPlayerSnapshotsParamsApplier) sortToColumnAndDirection(
|
||||||
|
|
|
@ -30,7 +30,8 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
|
||||||
|
|
||||||
require.NotEmpty(t, params)
|
require.NotEmpty(t, params)
|
||||||
|
|
||||||
playerSnapshots, err := repos.playerSnapshot.List(ctx, domain.NewListPlayerSnapshotsParams())
|
res, err := repos.playerSnapshot.List(ctx, domain.NewListPlayerSnapshotsParams())
|
||||||
|
playerSnapshots := res.PlayerSnapshots()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
for i, p := range params {
|
for i, p := range params {
|
||||||
date := p.Date().Format(dateFormat)
|
date := p.Date().Format(dateFormat)
|
||||||
|
@ -60,8 +61,9 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
|
||||||
|
|
||||||
require.NotEmpty(t, params)
|
require.NotEmpty(t, params)
|
||||||
|
|
||||||
playerSnapshots, err := repos.playerSnapshot.List(ctx, domain.NewListPlayerSnapshotsParams())
|
res, err := repos.playerSnapshot.List(ctx, domain.NewListPlayerSnapshotsParams())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
playerSnapshots := res.PlayerSnapshots()
|
||||||
|
|
||||||
m := make(map[string][]int)
|
m := make(map[string][]int)
|
||||||
|
|
||||||
|
@ -119,18 +121,13 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
|
||||||
|
|
||||||
repos := newRepos(t)
|
repos := newRepos(t)
|
||||||
|
|
||||||
playerSnapshots, listPlayerSnapshotsErr := repos.playerSnapshot.List(ctx, domain.NewListPlayerSnapshotsParams())
|
|
||||||
require.NoError(t, listPlayerSnapshotsErr)
|
|
||||||
require.NotEmpty(t, playerSnapshots)
|
|
||||||
randPlayerSnapshot := playerSnapshots[0]
|
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
params func(t *testing.T) domain.ListPlayerSnapshotsParams
|
params func(t *testing.T) domain.ListPlayerSnapshotsParams
|
||||||
assertPlayerSnapshots func(
|
assertResult func(
|
||||||
t *testing.T,
|
t *testing.T,
|
||||||
params domain.ListPlayerSnapshotsParams,
|
params domain.ListPlayerSnapshotsParams,
|
||||||
playerSnapshots domain.PlayerSnapshots,
|
res domain.ListPlayerSnapshotsResult,
|
||||||
)
|
)
|
||||||
assertError func(t *testing.T, err error)
|
assertError func(t *testing.T, err error)
|
||||||
}{
|
}{
|
||||||
|
@ -140,12 +137,13 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
|
||||||
t.Helper()
|
t.Helper()
|
||||||
return domain.NewListPlayerSnapshotsParams()
|
return domain.NewListPlayerSnapshotsParams()
|
||||||
},
|
},
|
||||||
assertPlayerSnapshots: func(
|
assertResult: func(
|
||||||
t *testing.T,
|
t *testing.T,
|
||||||
_ domain.ListPlayerSnapshotsParams,
|
_ domain.ListPlayerSnapshotsParams,
|
||||||
playerSnapshots domain.PlayerSnapshots,
|
res domain.ListPlayerSnapshotsResult,
|
||||||
) {
|
) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
playerSnapshots := res.PlayerSnapshots()
|
||||||
assert.NotEmpty(t, len(playerSnapshots))
|
assert.NotEmpty(t, len(playerSnapshots))
|
||||||
assert.True(t, slices.IsSortedFunc(playerSnapshots, func(a, b domain.PlayerSnapshot) int {
|
assert.True(t, slices.IsSortedFunc(playerSnapshots, func(a, b domain.PlayerSnapshot) int {
|
||||||
return cmp.Or(
|
return cmp.Or(
|
||||||
|
@ -154,6 +152,8 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
|
||||||
cmp.Compare(a.ID(), b.ID()),
|
cmp.Compare(a.ID(), b.ID()),
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
|
assert.False(t, res.Self().IsZero())
|
||||||
|
assert.True(t, res.Next().IsZero())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -167,12 +167,13 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
|
||||||
}))
|
}))
|
||||||
return params
|
return params
|
||||||
},
|
},
|
||||||
assertPlayerSnapshots: func(
|
assertResult: func(
|
||||||
t *testing.T,
|
t *testing.T,
|
||||||
_ domain.ListPlayerSnapshotsParams,
|
_ domain.ListPlayerSnapshotsParams,
|
||||||
playerSnapshots domain.PlayerSnapshots,
|
res domain.ListPlayerSnapshotsResult,
|
||||||
) {
|
) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
playerSnapshots := res.PlayerSnapshots()
|
||||||
assert.NotEmpty(t, len(playerSnapshots))
|
assert.NotEmpty(t, len(playerSnapshots))
|
||||||
assert.True(t, slices.IsSortedFunc(playerSnapshots, func(a, b domain.PlayerSnapshot) int {
|
assert.True(t, slices.IsSortedFunc(playerSnapshots, func(a, b domain.PlayerSnapshot) int {
|
||||||
return cmp.Or(
|
return cmp.Or(
|
||||||
|
@ -192,12 +193,13 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
|
||||||
}))
|
}))
|
||||||
return params
|
return params
|
||||||
},
|
},
|
||||||
assertPlayerSnapshots: func(
|
assertResult: func(
|
||||||
t *testing.T,
|
t *testing.T,
|
||||||
_ domain.ListPlayerSnapshotsParams,
|
_ domain.ListPlayerSnapshotsParams,
|
||||||
playerSnapshots domain.PlayerSnapshots,
|
res domain.ListPlayerSnapshotsResult,
|
||||||
) {
|
) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
playerSnapshots := res.PlayerSnapshots()
|
||||||
assert.NotEmpty(t, len(playerSnapshots))
|
assert.NotEmpty(t, len(playerSnapshots))
|
||||||
assert.True(t, slices.IsSortedFunc(playerSnapshots, func(a, b domain.PlayerSnapshot) int {
|
assert.True(t, slices.IsSortedFunc(playerSnapshots, func(a, b domain.PlayerSnapshot) int {
|
||||||
return cmp.Compare(a.ID(), b.ID())
|
return cmp.Compare(a.ID(), b.ID())
|
||||||
|
@ -214,12 +216,13 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
|
||||||
}))
|
}))
|
||||||
return params
|
return params
|
||||||
},
|
},
|
||||||
assertPlayerSnapshots: func(
|
assertResult: func(
|
||||||
t *testing.T,
|
t *testing.T,
|
||||||
_ domain.ListPlayerSnapshotsParams,
|
_ domain.ListPlayerSnapshotsParams,
|
||||||
playerSnapshots domain.PlayerSnapshots,
|
res domain.ListPlayerSnapshotsResult,
|
||||||
) {
|
) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
playerSnapshots := res.PlayerSnapshots()
|
||||||
assert.NotEmpty(t, len(playerSnapshots))
|
assert.NotEmpty(t, len(playerSnapshots))
|
||||||
assert.True(t, slices.IsSortedFunc(playerSnapshots, func(a, b domain.PlayerSnapshot) int {
|
assert.True(t, slices.IsSortedFunc(playerSnapshots, func(a, b domain.PlayerSnapshot) int {
|
||||||
return cmp.Compare(a.ID(), b.ID()) * -1
|
return cmp.Compare(a.ID(), b.ID()) * -1
|
||||||
|
@ -227,43 +230,89 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: fmt.Sprintf("OK: serverKeys=[%s]", randPlayerSnapshot.ServerKey()),
|
name: "OK: serverKeys",
|
||||||
params: func(t *testing.T) domain.ListPlayerSnapshotsParams {
|
params: func(t *testing.T) domain.ListPlayerSnapshotsParams {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
params := domain.NewListPlayerSnapshotsParams()
|
params := domain.NewListPlayerSnapshotsParams()
|
||||||
|
|
||||||
|
res, err := repos.playerSnapshot.List(ctx, params)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, res.PlayerSnapshots())
|
||||||
|
randPlayerSnapshot := res.PlayerSnapshots()[0]
|
||||||
|
|
||||||
require.NoError(t, params.SetServerKeys([]string{randPlayerSnapshot.ServerKey()}))
|
require.NoError(t, params.SetServerKeys([]string{randPlayerSnapshot.ServerKey()}))
|
||||||
|
|
||||||
return params
|
return params
|
||||||
},
|
},
|
||||||
assertPlayerSnapshots: func(
|
assertResult: func(
|
||||||
t *testing.T,
|
t *testing.T,
|
||||||
params domain.ListPlayerSnapshotsParams,
|
params domain.ListPlayerSnapshotsParams,
|
||||||
playerSnapshots domain.PlayerSnapshots,
|
res domain.ListPlayerSnapshotsResult,
|
||||||
) {
|
) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
serverKeys := params.ServerKeys()
|
serverKeys := params.ServerKeys()
|
||||||
|
|
||||||
|
playerSnapshots := res.PlayerSnapshots()
|
||||||
|
assert.NotZero(t, playerSnapshots)
|
||||||
for _, ps := range playerSnapshots {
|
for _, ps := range playerSnapshots {
|
||||||
assert.True(t, slices.Contains(serverKeys, ps.ServerKey()))
|
assert.True(t, slices.Contains(serverKeys, ps.ServerKey()))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "OK: offset=1 limit=2",
|
name: "OK: playerIDs serverKeys",
|
||||||
|
params: func(t *testing.T) domain.ListPlayerSnapshotsParams {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
params := domain.NewListPlayerSnapshotsParams()
|
||||||
|
|
||||||
|
res, err := repos.playerSnapshot.List(ctx, params)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, res.PlayerSnapshots())
|
||||||
|
randPlayerSnapshot := res.PlayerSnapshots()[0]
|
||||||
|
|
||||||
|
require.NoError(t, params.SetServerKeys([]string{randPlayerSnapshot.ServerKey()}))
|
||||||
|
require.NoError(t, params.SetPlayerIDs([]int{randPlayerSnapshot.PlayerID()}))
|
||||||
|
|
||||||
|
return params
|
||||||
|
},
|
||||||
|
assertResult: func(
|
||||||
|
t *testing.T,
|
||||||
|
params domain.ListPlayerSnapshotsParams,
|
||||||
|
res domain.ListPlayerSnapshotsResult,
|
||||||
|
) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
serverKeys := params.ServerKeys()
|
||||||
|
playerIDs := params.PlayerIDs()
|
||||||
|
|
||||||
|
playerSnapshots := res.PlayerSnapshots()
|
||||||
|
assert.NotZero(t, playerSnapshots)
|
||||||
|
for _, ps := range playerSnapshots {
|
||||||
|
assert.True(t, slices.Contains(serverKeys, ps.ServerKey()))
|
||||||
|
assert.True(t, slices.Contains(playerIDs, ps.PlayerID()))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "OK: limit=2",
|
||||||
params: func(t *testing.T) domain.ListPlayerSnapshotsParams {
|
params: func(t *testing.T) domain.ListPlayerSnapshotsParams {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
params := domain.NewListPlayerSnapshotsParams()
|
params := domain.NewListPlayerSnapshotsParams()
|
||||||
require.NoError(t, params.SetOffset(1))
|
|
||||||
require.NoError(t, params.SetLimit(2))
|
require.NoError(t, params.SetLimit(2))
|
||||||
return params
|
return params
|
||||||
},
|
},
|
||||||
assertPlayerSnapshots: func(
|
assertResult: func(
|
||||||
t *testing.T,
|
t *testing.T,
|
||||||
params domain.ListPlayerSnapshotsParams,
|
params domain.ListPlayerSnapshotsParams,
|
||||||
playerSnapshots domain.PlayerSnapshots,
|
res domain.ListPlayerSnapshotsResult,
|
||||||
) {
|
) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
assert.Len(t, playerSnapshots, params.Limit())
|
assert.Len(t, res.PlayerSnapshots(), params.Limit())
|
||||||
|
assert.False(t, res.Self().IsZero())
|
||||||
|
assert.False(t, res.Next().IsZero())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -284,7 +333,7 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
|
||||||
|
|
||||||
res, err := repos.playerSnapshot.List(ctx, params)
|
res, err := repos.playerSnapshot.List(ctx, params)
|
||||||
assertError(t, err)
|
assertError(t, err)
|
||||||
tt.assertPlayerSnapshots(t, params, res)
|
tt.assertResult(t, params, res)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -70,7 +70,7 @@ type tribeSnapshotRepository interface {
|
||||||
|
|
||||||
type playerSnapshotRepository interface {
|
type playerSnapshotRepository interface {
|
||||||
Create(ctx context.Context, params ...domain.CreatePlayerSnapshotParams) error
|
Create(ctx context.Context, params ...domain.CreatePlayerSnapshotParams) error
|
||||||
List(ctx context.Context, params domain.ListPlayerSnapshotsParams) (domain.PlayerSnapshots, error)
|
List(ctx context.Context, params domain.ListPlayerSnapshotsParams) (domain.ListPlayerSnapshotsResult, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type repositories struct {
|
type repositories struct {
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
package domaintest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
|
||||||
|
"github.com/brianvoe/gofakeit/v7"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PlayerSnapshotCursorConfig struct {
|
||||||
|
ID int
|
||||||
|
ServerKey string
|
||||||
|
Date time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPlayerSnapshotCursor(tb TestingTB, opts ...func(cfg *PlayerSnapshotCursorConfig)) domain.PlayerSnapshotCursor {
|
||||||
|
tb.Helper()
|
||||||
|
|
||||||
|
cfg := &PlayerSnapshotCursorConfig{
|
||||||
|
ID: RandID(),
|
||||||
|
ServerKey: RandServerKey(),
|
||||||
|
Date: gofakeit.Date(),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
psc, err := domain.NewPlayerSnapshotCursor(
|
||||||
|
cfg.ID,
|
||||||
|
cfg.ServerKey,
|
||||||
|
cfg.Date,
|
||||||
|
)
|
||||||
|
require.NoError(tb, err)
|
||||||
|
|
||||||
|
return psc
|
||||||
|
}
|
||||||
|
|
||||||
|
type PlayerSnapshotConfig struct {
|
||||||
|
ID int
|
||||||
|
PlayerID int
|
||||||
|
ServerKey string
|
||||||
|
NumVillages int
|
||||||
|
Points int
|
||||||
|
Rank int
|
||||||
|
TribeID int
|
||||||
|
OD domain.OpponentsDefeated
|
||||||
|
Date time.Time
|
||||||
|
CreatedAt time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPlayerSnapshot(tb TestingTB, opts ...func(cfg *PlayerSnapshotConfig)) domain.PlayerSnapshot {
|
||||||
|
tb.Helper()
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
cfg := &PlayerSnapshotConfig{
|
||||||
|
ID: RandID(),
|
||||||
|
PlayerID: RandID(),
|
||||||
|
ServerKey: RandServerKey(),
|
||||||
|
NumVillages: gofakeit.IntRange(1, 10000),
|
||||||
|
Points: gofakeit.IntRange(1, 10000),
|
||||||
|
Rank: gofakeit.IntRange(1, 10000),
|
||||||
|
TribeID: RandID(),
|
||||||
|
OD: NewOpponentsDefeated(tb),
|
||||||
|
Date: now,
|
||||||
|
CreatedAt: now,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
ps, err := domain.UnmarshalPlayerSnapshotFromDatabase(
|
||||||
|
cfg.ID,
|
||||||
|
cfg.PlayerID,
|
||||||
|
cfg.ServerKey,
|
||||||
|
cfg.NumVillages,
|
||||||
|
cfg.Points,
|
||||||
|
cfg.Rank,
|
||||||
|
cfg.TribeID,
|
||||||
|
cfg.OD,
|
||||||
|
cfg.Date,
|
||||||
|
cfg.CreatedAt,
|
||||||
|
)
|
||||||
|
require.NoError(tb, err)
|
||||||
|
|
||||||
|
return ps
|
||||||
|
}
|
|
@ -115,6 +115,14 @@ func (ps PlayerSnapshot) CreatedAt() time.Time {
|
||||||
return ps.createdAt
|
return ps.createdAt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ps PlayerSnapshot) ToCursor() (PlayerSnapshotCursor, error) {
|
||||||
|
return NewPlayerSnapshotCursor(ps.id, ps.serverKey, ps.date)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps PlayerSnapshot) IsZero() bool {
|
||||||
|
return ps == PlayerSnapshot{}
|
||||||
|
}
|
||||||
|
|
||||||
type PlayerSnapshots []PlayerSnapshot
|
type PlayerSnapshots []PlayerSnapshot
|
||||||
|
|
||||||
type CreatePlayerSnapshotParams struct {
|
type CreatePlayerSnapshotParams struct {
|
||||||
|
@ -224,16 +232,112 @@ func (s PlayerSnapshotSort) String() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const PlayerSnapshotListMaxLimit = 500
|
type PlayerSnapshotCursor struct {
|
||||||
|
id int
|
||||||
|
serverKey string
|
||||||
|
date time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
const playerSnapshotCursorModelName = "PlayerSnapshotCursor"
|
||||||
|
|
||||||
|
func NewPlayerSnapshotCursor(id int, serverKey string, date time.Time) (PlayerSnapshotCursor, error) {
|
||||||
|
if err := validateIntInRange(id, 1, math.MaxInt); err != nil {
|
||||||
|
return PlayerSnapshotCursor{}, ValidationError{
|
||||||
|
Model: playerSnapshotCursorModelName,
|
||||||
|
Field: "id",
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := validateServerKey(serverKey); err != nil {
|
||||||
|
return PlayerSnapshotCursor{}, ValidationError{
|
||||||
|
Model: playerSnapshotCursorModelName,
|
||||||
|
Field: "serverKey",
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PlayerSnapshotCursor{
|
||||||
|
id: id,
|
||||||
|
serverKey: serverKey,
|
||||||
|
date: date,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//nolint:gocyclo
|
||||||
|
func decodePlayerSnapshotCursor(encoded string) (PlayerSnapshotCursor, error) {
|
||||||
|
m, err := decodeCursor(encoded)
|
||||||
|
if err != nil {
|
||||||
|
return PlayerSnapshotCursor{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := m.int("id")
|
||||||
|
if err != nil {
|
||||||
|
return PlayerSnapshotCursor{}, ErrInvalidCursor
|
||||||
|
}
|
||||||
|
|
||||||
|
serverKey, err := m.string("serverKey")
|
||||||
|
if err != nil {
|
||||||
|
return PlayerSnapshotCursor{}, ErrInvalidCursor
|
||||||
|
}
|
||||||
|
|
||||||
|
date, err := m.time("date")
|
||||||
|
if err != nil {
|
||||||
|
return PlayerSnapshotCursor{}, ErrInvalidCursor
|
||||||
|
}
|
||||||
|
|
||||||
|
psc, err := NewPlayerSnapshotCursor(
|
||||||
|
id,
|
||||||
|
serverKey,
|
||||||
|
date,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return PlayerSnapshotCursor{}, ErrInvalidCursor
|
||||||
|
}
|
||||||
|
|
||||||
|
return psc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (psc PlayerSnapshotCursor) ID() int {
|
||||||
|
return psc.id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (psc PlayerSnapshotCursor) ServerKey() string {
|
||||||
|
return psc.serverKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func (psc PlayerSnapshotCursor) Date() time.Time {
|
||||||
|
return psc.date
|
||||||
|
}
|
||||||
|
|
||||||
|
func (psc PlayerSnapshotCursor) IsZero() bool {
|
||||||
|
return psc == PlayerSnapshotCursor{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (psc PlayerSnapshotCursor) Encode() string {
|
||||||
|
if psc.IsZero() {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return encodeCursor([]keyValuePair{
|
||||||
|
{"id", psc.id},
|
||||||
|
{"serverKey", psc.serverKey},
|
||||||
|
{"date", psc.date},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
type ListPlayerSnapshotsParams struct {
|
type ListPlayerSnapshotsParams struct {
|
||||||
serverKeys []string
|
serverKeys []string
|
||||||
|
playerIDs []int
|
||||||
sort []PlayerSnapshotSort
|
sort []PlayerSnapshotSort
|
||||||
|
cursor PlayerSnapshotCursor
|
||||||
limit int
|
limit int
|
||||||
offset int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const listPlayerSnapshotsParamsModelName = "ListPlayerSnapshotsParams"
|
const (
|
||||||
|
PlayerSnapshotListMaxLimit = 500
|
||||||
|
listPlayerSnapshotsParamsModelName = "ListPlayerSnapshotsParams"
|
||||||
|
)
|
||||||
|
|
||||||
func NewListPlayerSnapshotsParams() ListPlayerSnapshotsParams {
|
func NewListPlayerSnapshotsParams() ListPlayerSnapshotsParams {
|
||||||
return ListPlayerSnapshotsParams{
|
return ListPlayerSnapshotsParams{
|
||||||
|
@ -267,6 +371,27 @@ func (params *ListPlayerSnapshotsParams) SetServerKeys(serverKeys []string) erro
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (params *ListPlayerSnapshotsParams) PlayerIDs() []int {
|
||||||
|
return params.playerIDs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (params *ListPlayerSnapshotsParams) SetPlayerIDs(playerIDs []int) error {
|
||||||
|
for i, id := range playerIDs {
|
||||||
|
if err := validateIntInRange(id, 1, math.MaxInt); err != nil {
|
||||||
|
return SliceElementValidationError{
|
||||||
|
Model: listPlayerSnapshotsParamsModelName,
|
||||||
|
Field: "playerIDs",
|
||||||
|
Index: i,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
params.playerIDs = playerIDs
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (params *ListPlayerSnapshotsParams) Sort() []PlayerSnapshotSort {
|
func (params *ListPlayerSnapshotsParams) Sort() []PlayerSnapshotSort {
|
||||||
return params.sort
|
return params.sort
|
||||||
}
|
}
|
||||||
|
@ -290,6 +415,30 @@ func (params *ListPlayerSnapshotsParams) SetSort(sort []PlayerSnapshotSort) erro
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (params *ListPlayerSnapshotsParams) Cursor() PlayerSnapshotCursor {
|
||||||
|
return params.cursor
|
||||||
|
}
|
||||||
|
|
||||||
|
func (params *ListPlayerSnapshotsParams) SetCursor(cursor PlayerSnapshotCursor) error {
|
||||||
|
params.cursor = cursor
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (params *ListPlayerSnapshotsParams) SetEncodedCursor(encoded string) error {
|
||||||
|
decoded, err := decodePlayerSnapshotCursor(encoded)
|
||||||
|
if err != nil {
|
||||||
|
return ValidationError{
|
||||||
|
Model: listPlayerSnapshotsParamsModelName,
|
||||||
|
Field: "cursor",
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
params.cursor = decoded
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (params *ListPlayerSnapshotsParams) Limit() int {
|
func (params *ListPlayerSnapshotsParams) Limit() int {
|
||||||
return params.limit
|
return params.limit
|
||||||
}
|
}
|
||||||
|
@ -308,20 +457,56 @@ func (params *ListPlayerSnapshotsParams) SetLimit(limit int) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (params *ListPlayerSnapshotsParams) Offset() int {
|
type ListPlayerSnapshotsResult struct {
|
||||||
return params.offset
|
snapshots PlayerSnapshots
|
||||||
|
self PlayerSnapshotCursor
|
||||||
|
next PlayerSnapshotCursor
|
||||||
}
|
}
|
||||||
|
|
||||||
func (params *ListPlayerSnapshotsParams) SetOffset(offset int) error {
|
const listPlayerSnapshotsResultModelName = "ListPlayerSnapshotsResult"
|
||||||
if err := validateIntInRange(offset, 0, math.MaxInt); err != nil {
|
|
||||||
return ValidationError{
|
func NewListPlayerSnapshotsResult(
|
||||||
Model: listPlayerSnapshotsParamsModelName,
|
snapshots PlayerSnapshots,
|
||||||
Field: "offset",
|
next PlayerSnapshot,
|
||||||
Err: err,
|
) (ListPlayerSnapshotsResult, error) {
|
||||||
|
var err error
|
||||||
|
res := ListPlayerSnapshotsResult{
|
||||||
|
snapshots: snapshots,
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(snapshots) > 0 {
|
||||||
|
res.self, err = snapshots[0].ToCursor()
|
||||||
|
if err != nil {
|
||||||
|
return ListPlayerSnapshotsResult{}, ValidationError{
|
||||||
|
Model: listPlayerSnapshotsResultModelName,
|
||||||
|
Field: "self",
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
params.offset = offset
|
if !next.IsZero() {
|
||||||
|
res.next, err = next.ToCursor()
|
||||||
|
if err != nil {
|
||||||
|
return ListPlayerSnapshotsResult{}, ValidationError{
|
||||||
|
Model: listPlayerSnapshotsResultModelName,
|
||||||
|
Field: "next",
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (res ListPlayerSnapshotsResult) PlayerSnapshots() PlayerSnapshots {
|
||||||
|
return res.snapshots
|
||||||
|
}
|
||||||
|
|
||||||
|
func (res ListPlayerSnapshotsResult) Self() PlayerSnapshotCursor {
|
||||||
|
return res.self
|
||||||
|
}
|
||||||
|
|
||||||
|
func (res ListPlayerSnapshotsResult) Next() PlayerSnapshotCursor {
|
||||||
|
return res.next
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
|
"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
|
||||||
"gitea.dwysokinski.me/twhelp/corev3/internal/domain/domaintest"
|
"gitea.dwysokinski.me/twhelp/corev3/internal/domain/domaintest"
|
||||||
|
"github.com/brianvoe/gofakeit/v7"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
@ -109,6 +110,87 @@ func TestPlayerSnapshotSort_IsInConflict(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewPlayerSnapshotCursor(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
validPlayerSnapshotCursor := domaintest.NewPlayerSnapshotCursor(t)
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
id int
|
||||||
|
serverKey string
|
||||||
|
date time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type test struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
expectedErr error
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []test{
|
||||||
|
{
|
||||||
|
name: "OK",
|
||||||
|
args: args{
|
||||||
|
id: validPlayerSnapshotCursor.ID(),
|
||||||
|
serverKey: validPlayerSnapshotCursor.ServerKey(),
|
||||||
|
date: validPlayerSnapshotCursor.Date(),
|
||||||
|
},
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ERR: id < 1",
|
||||||
|
args: args{
|
||||||
|
id: 0,
|
||||||
|
serverKey: validPlayerSnapshotCursor.ServerKey(),
|
||||||
|
date: validPlayerSnapshotCursor.Date(),
|
||||||
|
},
|
||||||
|
expectedErr: domain.ValidationError{
|
||||||
|
Model: "PlayerSnapshotCursor",
|
||||||
|
Field: "id",
|
||||||
|
Err: domain.MinGreaterEqualError{
|
||||||
|
Min: 1,
|
||||||
|
Current: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, serverKeyTest := range newServerKeyValidationTests() {
|
||||||
|
tests = append(tests, test{
|
||||||
|
name: serverKeyTest.name,
|
||||||
|
args: args{
|
||||||
|
id: validPlayerSnapshotCursor.ID(),
|
||||||
|
serverKey: serverKeyTest.key,
|
||||||
|
},
|
||||||
|
expectedErr: domain.ValidationError{
|
||||||
|
Model: "PlayerSnapshotCursor",
|
||||||
|
Field: "serverKey",
|
||||||
|
Err: serverKeyTest.expectedErr,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
psc, err := domain.NewPlayerSnapshotCursor(
|
||||||
|
tt.args.id,
|
||||||
|
tt.args.serverKey,
|
||||||
|
tt.args.date,
|
||||||
|
)
|
||||||
|
require.ErrorIs(t, err, tt.expectedErr)
|
||||||
|
if tt.expectedErr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.Equal(t, tt.args.id, psc.ID())
|
||||||
|
assert.Equal(t, tt.args.serverKey, psc.ServerKey())
|
||||||
|
assert.Equal(t, tt.args.date, psc.Date())
|
||||||
|
assert.NotEmpty(t, psc.Encode())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestListPlayerSnapshotsParams_SetServerKeys(t *testing.T) {
|
func TestListPlayerSnapshotsParams_SetServerKeys(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
@ -252,6 +334,86 @@ func TestListPlayerSnapshotsParams_SetSort(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestListPlayerSnapshotsParams_SetEncodedCursor(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
validCursor := domaintest.NewPlayerSnapshotCursor(t)
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
cursor string
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
expectedCursor domain.PlayerSnapshotCursor
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "OK",
|
||||||
|
args: args{
|
||||||
|
cursor: validCursor.Encode(),
|
||||||
|
},
|
||||||
|
expectedCursor: validCursor,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ERR: len(cursor) < 1",
|
||||||
|
args: args{
|
||||||
|
cursor: "",
|
||||||
|
},
|
||||||
|
expectedErr: domain.ValidationError{
|
||||||
|
Model: "ListPlayerSnapshotsParams",
|
||||||
|
Field: "cursor",
|
||||||
|
Err: domain.LenOutOfRangeError{
|
||||||
|
Min: 1,
|
||||||
|
Max: 1000,
|
||||||
|
Current: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ERR: len(cursor) > 1000",
|
||||||
|
args: args{
|
||||||
|
cursor: gofakeit.LetterN(1001),
|
||||||
|
},
|
||||||
|
expectedErr: domain.ValidationError{
|
||||||
|
Model: "ListPlayerSnapshotsParams",
|
||||||
|
Field: "cursor",
|
||||||
|
Err: domain.LenOutOfRangeError{
|
||||||
|
Min: 1,
|
||||||
|
Max: 1000,
|
||||||
|
Current: 1001,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ERR: malformed base64",
|
||||||
|
args: args{
|
||||||
|
cursor: "112345",
|
||||||
|
},
|
||||||
|
expectedErr: domain.ValidationError{
|
||||||
|
Model: "ListPlayerSnapshotsParams",
|
||||||
|
Field: "cursor",
|
||||||
|
Err: domain.ErrInvalidCursor,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
params := domain.NewListPlayerSnapshotsParams()
|
||||||
|
|
||||||
|
require.ErrorIs(t, params.SetEncodedCursor(tt.args.cursor), tt.expectedErr)
|
||||||
|
if tt.expectedErr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.Equal(t, tt.args.cursor, params.Cursor().Encode())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestListPlayerSnapshotsParams_SetLimit(t *testing.T) {
|
func TestListPlayerSnapshotsParams_SetLimit(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
@ -315,51 +477,49 @@ func TestListPlayerSnapshotsParams_SetLimit(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestListPlayerSnapshotsParams_SetOffset(t *testing.T) {
|
func TestNewListPlayerSnapshotsResult(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
type args struct {
|
snapshots := domain.PlayerSnapshots{
|
||||||
offset int
|
domaintest.NewPlayerSnapshot(t),
|
||||||
|
domaintest.NewPlayerSnapshot(t),
|
||||||
|
domaintest.NewPlayerSnapshot(t),
|
||||||
}
|
}
|
||||||
|
next := domaintest.NewPlayerSnapshot(t)
|
||||||
|
|
||||||
tests := []struct {
|
t.Run("OK: with next", func(t *testing.T) {
|
||||||
name string
|
t.Parallel()
|
||||||
args args
|
|
||||||
expectedErr error
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "OK",
|
|
||||||
args: args{
|
|
||||||
offset: 100,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "ERR: offset < 0",
|
|
||||||
args: args{
|
|
||||||
offset: -1,
|
|
||||||
},
|
|
||||||
expectedErr: domain.ValidationError{
|
|
||||||
Model: "ListPlayerSnapshotsParams",
|
|
||||||
Field: "offset",
|
|
||||||
Err: domain.MinGreaterEqualError{
|
|
||||||
Min: 0,
|
|
||||||
Current: -1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
res, err := domain.NewListPlayerSnapshotsResult(snapshots, next)
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
require.NoError(t, err)
|
||||||
t.Parallel()
|
assert.Equal(t, snapshots, res.PlayerSnapshots())
|
||||||
|
assert.Equal(t, snapshots[0].ID(), res.Self().ID())
|
||||||
|
assert.Equal(t, snapshots[0].ServerKey(), res.Self().ServerKey())
|
||||||
|
assert.Equal(t, snapshots[0].Date(), res.Self().Date())
|
||||||
|
assert.Equal(t, next.ID(), res.Next().ID())
|
||||||
|
assert.Equal(t, next.ServerKey(), res.Next().ServerKey())
|
||||||
|
assert.Equal(t, next.Date(), res.Next().Date())
|
||||||
|
})
|
||||||
|
|
||||||
params := domain.NewListPlayerSnapshotsParams()
|
t.Run("OK: without next", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
require.ErrorIs(t, params.SetOffset(tt.args.offset), tt.expectedErr)
|
res, err := domain.NewListPlayerSnapshotsResult(snapshots, domain.PlayerSnapshot{})
|
||||||
if tt.expectedErr != nil {
|
require.NoError(t, err)
|
||||||
return
|
assert.Equal(t, snapshots, res.PlayerSnapshots())
|
||||||
}
|
assert.Equal(t, snapshots[0].ID(), res.Self().ID())
|
||||||
assert.Equal(t, tt.args.offset, params.Offset())
|
assert.Equal(t, snapshots[0].ServerKey(), res.Self().ServerKey())
|
||||||
})
|
assert.Equal(t, snapshots[0].Date(), res.Self().Date())
|
||||||
}
|
assert.True(t, res.Next().IsZero())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("OK: 0 snapshots", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
res, err := domain.NewListPlayerSnapshotsResult(nil, domain.PlayerSnapshot{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Zero(t, res.PlayerSnapshots())
|
||||||
|
assert.True(t, res.Self().IsZero())
|
||||||
|
assert.True(t, res.Next().IsZero())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -316,14 +316,10 @@ func TestSnapshotCreation(t *testing.T) {
|
||||||
cnt := 0
|
cnt := 0
|
||||||
|
|
||||||
for {
|
for {
|
||||||
snapshots, err := playerSnapshotRepo.List(ctx, listSnapshotsParams)
|
res, err := playerSnapshotRepo.List(ctx, listSnapshotsParams)
|
||||||
require.NoError(collect, err)
|
require.NoError(collect, err)
|
||||||
|
|
||||||
if len(snapshots) == 0 {
|
for _, ps := range res.PlayerSnapshots() {
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ps := range snapshots {
|
|
||||||
cnt++
|
cnt++
|
||||||
msg := fmt.Sprintf("PlayerID=%d,ServerKey=%s", ps.PlayerID(), ps.ServerKey())
|
msg := fmt.Sprintf("PlayerID=%d,ServerKey=%s", ps.PlayerID(), ps.ServerKey())
|
||||||
|
|
||||||
|
@ -353,7 +349,11 @@ func TestSnapshotCreation(t *testing.T) {
|
||||||
assert.WithinDuration(collect, time.Now(), ps.Date(), 24*time.Hour, msg)
|
assert.WithinDuration(collect, time.Now(), ps.Date(), 24*time.Hour, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
require.NoError(collect, listSnapshotsParams.SetOffset(listSnapshotsParams.Offset()+listSnapshotsParams.Limit()))
|
if res.Next().IsZero() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
require.NoError(collect, listSnapshotsParams.SetCursor(res.Next()))
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:testifylint
|
//nolint:testifylint
|
||||||
|
|
Loading…
Reference in New Issue