refactor: server - cursor pagination (#56)
Reviewed-on: twhelp/corev3#56
This commit is contained in:
parent
b6d55b1741
commit
f07451351b
|
@ -64,18 +64,25 @@ func (repo *ServerBunRepository) CreateOrUpdate(ctx context.Context, params ...d
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *ServerBunRepository) List(ctx context.Context, params domain.ListServersParams) (domain.Servers, error) {
|
func (repo *ServerBunRepository) List(
|
||||||
|
ctx context.Context,
|
||||||
|
params domain.ListServersParams,
|
||||||
|
) (domain.ListServersResult, error) {
|
||||||
var servers bunmodel.Servers
|
var servers bunmodel.Servers
|
||||||
|
|
||||||
if err := repo.baseListQuery(params).Model(&servers).Scan(ctx); err != nil && !errors.Is(err, sql.ErrNoRows) {
|
if err := repo.db.NewSelect().
|
||||||
return nil, fmt.Errorf("couldn't select servers from the db: %w", err)
|
Model(&servers).
|
||||||
|
Apply(listServersParamsApplier{params: params}.apply).
|
||||||
|
Scan(ctx); err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||||
|
return domain.ListServersResult{}, fmt.Errorf("couldn't select servers from the db: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return servers.ToDomain()
|
converted, err := servers.ToDomain()
|
||||||
}
|
if err != nil {
|
||||||
|
return domain.ListServersResult{}, err
|
||||||
|
}
|
||||||
|
|
||||||
func (repo *ServerBunRepository) baseListQuery(params domain.ListServersParams) *bun.SelectQuery {
|
return domain.NewListServersResult(separateListResultAndNext(converted, params.Limit()))
|
||||||
return repo.db.NewSelect().Apply(listServersParamsApplier{params: params}.apply)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *ServerBunRepository) Update(ctx context.Context, key string, params domain.UpdateServerParams) error {
|
func (repo *ServerBunRepository) Update(ctx context.Context, key string, params domain.UpdateServerParams) error {
|
||||||
|
@ -184,10 +191,6 @@ func (a listServersParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery {
|
||||||
q = q.Where("server.key IN (?)", bun.In(keys))
|
q = q.Where("server.key IN (?)", bun.In(keys))
|
||||||
}
|
}
|
||||||
|
|
||||||
if keyGT := a.params.KeyGT(); keyGT.Valid {
|
|
||||||
q = q.Where("server.key > ?", keyGT.Value)
|
|
||||||
}
|
|
||||||
|
|
||||||
if versionCodes := a.params.VersionCodes(); len(versionCodes) > 0 {
|
if versionCodes := a.params.VersionCodes(); len(versionCodes) > 0 {
|
||||||
q = q.Where("server.version_code IN (?)", bun.In(versionCodes))
|
q = q.Where("server.version_code IN (?)", bun.In(versionCodes))
|
||||||
}
|
}
|
||||||
|
@ -229,5 +232,29 @@ func (a listServersParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return q.Limit(a.params.Limit()).Offset(a.params.Offset())
|
if !a.params.Cursor().IsZero() {
|
||||||
|
q.WhereGroup(" AND ", func(q *bun.SelectQuery) *bun.SelectQuery {
|
||||||
|
cursorKey := a.params.Cursor().Key()
|
||||||
|
cursorOpen := a.params.Cursor().Open()
|
||||||
|
|
||||||
|
for _, s := range a.params.Sort() {
|
||||||
|
switch s {
|
||||||
|
case domain.ServerSortKeyASC:
|
||||||
|
q = q.Where("server.key >= ?", cursorKey)
|
||||||
|
case domain.ServerSortKeyDESC:
|
||||||
|
q = q.Where("server.key <= ?", cursorKey)
|
||||||
|
case domain.ServerSortOpenASC:
|
||||||
|
q = q.Where("server.open >= ?", cursorOpen)
|
||||||
|
case domain.ServerSortOpenDESC:
|
||||||
|
q = q.Where("server.open <= ?", cursorOpen)
|
||||||
|
default:
|
||||||
|
return q.Err(errors.New("unsupported sort value"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return q
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return q.Limit(a.params.Limit() + 1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,10 +89,10 @@ func testEnnoblementRepository(t *testing.T, newRepos func(t *testing.T) reposit
|
||||||
t.Run("OK", func(t *testing.T) {
|
t.Run("OK", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
servers, err := repos.server.List(ctx, domain.NewListServersParams())
|
listServersRes, err := repos.server.List(ctx, domain.NewListServersParams())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotEmpty(t, servers)
|
require.NotEmpty(t, listServersRes)
|
||||||
server := servers[0]
|
server := listServersRes.Servers()[0]
|
||||||
|
|
||||||
ennoblementsToCreate := domain.BaseEnnoblements{
|
ennoblementsToCreate := domain.BaseEnnoblements{
|
||||||
domaintest.NewBaseEnnoblement(t),
|
domaintest.NewBaseEnnoblement(t),
|
||||||
|
|
|
@ -64,10 +64,10 @@ func testPlayerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
t.Run("OK", func(t *testing.T) {
|
t.Run("OK", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
servers, err := repos.server.List(ctx, domain.NewListServersParams())
|
listServersRes, err := repos.server.List(ctx, domain.NewListServersParams())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotEmpty(t, servers)
|
require.NotEmpty(t, listServersRes)
|
||||||
server := servers[0]
|
server := listServersRes.Servers()[0]
|
||||||
|
|
||||||
playersToCreate := domain.BasePlayers{
|
playersToCreate := domain.BasePlayers{
|
||||||
domaintest.NewBasePlayer(t),
|
domaintest.NewBasePlayer(t),
|
||||||
|
@ -325,15 +325,15 @@ func testPlayerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
|
|
||||||
listServersParams := domain.NewListServersParams()
|
listServersParams := domain.NewListServersParams()
|
||||||
require.NoError(t, listServersParams.SetSpecial(domain.NullBool{Value: false, Valid: true}))
|
require.NoError(t, listServersParams.SetSpecial(domain.NullBool{Value: false, Valid: true}))
|
||||||
servers, listServersErr := repos.server.List(ctx, listServersParams)
|
listServersRes, listServersErr := repos.server.List(ctx, listServersParams)
|
||||||
require.NoError(t, listServersErr)
|
require.NoError(t, listServersErr)
|
||||||
require.NotEmpty(t, servers)
|
require.NotEmpty(t, listServersRes)
|
||||||
|
|
||||||
t.Run("OK", func(t *testing.T) {
|
t.Run("OK", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
serverKeys := make([]string, 0, len(servers))
|
serverKeys := make([]string, 0, len(listServersRes.Servers()))
|
||||||
for _, s := range servers {
|
for _, s := range listServersRes.Servers() {
|
||||||
serverKeys = append(serverKeys, s.Key())
|
serverKeys = append(serverKeys, s.Key())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,7 +386,7 @@ func testPlayerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
t.Run("OK: len(ids) == 0", func(t *testing.T) {
|
t.Run("OK: len(ids) == 0", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
require.NoError(t, repos.player.Delete(ctx, servers[0].Key()))
|
require.NoError(t, repos.player.Delete(ctx, listServersRes.Servers()[0].Key()))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package adapter_test
|
||||||
import (
|
import (
|
||||||
"cmp"
|
"cmp"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"math"
|
"math"
|
||||||
"slices"
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -39,8 +38,9 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
listParams := domain.NewListServersParams()
|
listParams := domain.NewListServersParams()
|
||||||
require.NoError(t, listParams.SetKeys(keys))
|
require.NoError(t, listParams.SetKeys(keys))
|
||||||
|
|
||||||
servers, err := repos.server.List(ctx, listParams)
|
res, err := repos.server.List(ctx, listParams)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
servers := res.Servers()
|
||||||
require.Len(t, servers, len(params))
|
require.Len(t, servers, len(params))
|
||||||
for i, p := range params {
|
for i, p := range params {
|
||||||
idx := slices.IndexFunc(servers, func(server domain.Server) bool {
|
idx := slices.IndexFunc(servers, func(server domain.Server) bool {
|
||||||
|
@ -99,11 +99,6 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
|
|
||||||
repos := newRepos(t)
|
repos := newRepos(t)
|
||||||
|
|
||||||
servers, listServersErr := repos.server.List(ctx, domain.NewListServersParams())
|
|
||||||
require.NoError(t, listServersErr)
|
|
||||||
require.NotEmpty(t, servers)
|
|
||||||
randServer := servers[0]
|
|
||||||
|
|
||||||
snapshotsCreatedAtLT := time.Date(
|
snapshotsCreatedAtLT := time.Date(
|
||||||
2022,
|
2022,
|
||||||
time.March,
|
time.March,
|
||||||
|
@ -116,11 +111,10 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
)
|
)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
params func(t *testing.T) domain.ListServersParams
|
params func(t *testing.T) domain.ListServersParams
|
||||||
assertServers func(t *testing.T, params domain.ListServersParams, servers domain.Servers)
|
assertResult func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult)
|
||||||
assertError func(t *testing.T, err error)
|
assertError func(t *testing.T, err error)
|
||||||
assertTotal func(t *testing.T, params domain.ListServersParams, total int)
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "OK: default params",
|
name: "OK: default params",
|
||||||
|
@ -128,8 +122,9 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
t.Helper()
|
t.Helper()
|
||||||
return domain.NewListServersParams()
|
return domain.NewListServersParams()
|
||||||
},
|
},
|
||||||
assertServers: func(t *testing.T, params domain.ListServersParams, servers domain.Servers) {
|
assertResult: func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
servers := res.Servers()
|
||||||
assert.NotEmpty(t, len(servers))
|
assert.NotEmpty(t, len(servers))
|
||||||
assert.True(t, slices.IsSortedFunc(servers, func(a, b domain.Server) int {
|
assert.True(t, slices.IsSortedFunc(servers, func(a, b domain.Server) int {
|
||||||
return cmp.Compare(a.Key(), b.Key())
|
return cmp.Compare(a.Key(), b.Key())
|
||||||
|
@ -139,10 +134,6 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
t.Helper()
|
t.Helper()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
},
|
},
|
||||||
assertTotal: func(t *testing.T, params domain.ListServersParams, total int) {
|
|
||||||
t.Helper()
|
|
||||||
assert.NotEmpty(t, total)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "OK: sort=[open ASC, key ASC]",
|
name: "OK: sort=[open ASC, key ASC]",
|
||||||
|
@ -152,8 +143,9 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
require.NoError(t, params.SetSort([]domain.ServerSort{domain.ServerSortOpenASC, domain.ServerSortKeyASC}))
|
require.NoError(t, params.SetSort([]domain.ServerSort{domain.ServerSortOpenASC, domain.ServerSortKeyASC}))
|
||||||
return params
|
return params
|
||||||
},
|
},
|
||||||
assertServers: func(t *testing.T, params domain.ListServersParams, servers domain.Servers) {
|
assertResult: func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
servers := res.Servers()
|
||||||
assert.NotEmpty(t, len(servers))
|
assert.NotEmpty(t, len(servers))
|
||||||
assert.True(t, slices.IsSortedFunc(servers, func(a, b domain.Server) int {
|
assert.True(t, slices.IsSortedFunc(servers, func(a, b domain.Server) int {
|
||||||
if a.Open() && !b.Open() {
|
if a.Open() && !b.Open() {
|
||||||
|
@ -171,10 +163,6 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
t.Helper()
|
t.Helper()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
},
|
},
|
||||||
assertTotal: func(t *testing.T, params domain.ListServersParams, total int) {
|
|
||||||
t.Helper()
|
|
||||||
assert.NotEmpty(t, total)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "OK: sort=[open DESC, key DESC]",
|
name: "OK: sort=[open DESC, key DESC]",
|
||||||
|
@ -184,8 +172,9 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
require.NoError(t, params.SetSort([]domain.ServerSort{domain.ServerSortOpenDESC, domain.ServerSortKeyDESC}))
|
require.NoError(t, params.SetSort([]domain.ServerSort{domain.ServerSortOpenDESC, domain.ServerSortKeyDESC}))
|
||||||
return params
|
return params
|
||||||
},
|
},
|
||||||
assertServers: func(t *testing.T, params domain.ListServersParams, servers domain.Servers) {
|
assertResult: func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
servers := res.Servers()
|
||||||
assert.NotEmpty(t, len(servers))
|
assert.NotEmpty(t, len(servers))
|
||||||
assert.True(t, slices.IsSortedFunc(servers, func(a, b domain.Server) int {
|
assert.True(t, slices.IsSortedFunc(servers, func(a, b domain.Server) int {
|
||||||
if a.Open() && !b.Open() {
|
if a.Open() && !b.Open() {
|
||||||
|
@ -203,22 +192,26 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
t.Helper()
|
t.Helper()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
},
|
},
|
||||||
assertTotal: func(t *testing.T, params domain.ListServersParams, total int) {
|
|
||||||
t.Helper()
|
|
||||||
assert.NotEmpty(t, total)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: fmt.Sprintf("OK: keys=[%s]", randServer.Key()),
|
name: "OK: keys",
|
||||||
params: func(t *testing.T) domain.ListServersParams {
|
params: func(t *testing.T) domain.ListServersParams {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
params := domain.NewListServersParams()
|
params := domain.NewListServersParams()
|
||||||
require.NoError(t, params.SetKeys([]string{randServer.Key()}))
|
|
||||||
|
res, err := repos.server.List(ctx, params)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, len(res.Servers()))
|
||||||
|
|
||||||
|
require.NoError(t, params.SetKeys([]string{res.Servers()[0].Key()}))
|
||||||
|
|
||||||
return params
|
return params
|
||||||
},
|
},
|
||||||
assertServers: func(t *testing.T, params domain.ListServersParams, servers domain.Servers) {
|
assertResult: func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
|
servers := res.Servers()
|
||||||
keys := params.Keys()
|
keys := params.Keys()
|
||||||
|
|
||||||
assert.Len(t, servers, len(keys))
|
assert.Len(t, servers, len(keys))
|
||||||
|
@ -232,22 +225,26 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
t.Helper()
|
t.Helper()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
},
|
},
|
||||||
assertTotal: func(t *testing.T, params domain.ListServersParams, total int) {
|
|
||||||
t.Helper()
|
|
||||||
assert.Equal(t, len(params.Keys()), total) //nolint:testifylint
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: fmt.Sprintf("OK: versionCodes=[%s]", randServer.VersionCode()),
|
name: "OK: versionCodes",
|
||||||
params: func(t *testing.T) domain.ListServersParams {
|
params: func(t *testing.T) domain.ListServersParams {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
params := domain.NewListServersParams()
|
params := domain.NewListServersParams()
|
||||||
require.NoError(t, params.SetVersionCodes([]string{randServer.VersionCode()}))
|
|
||||||
|
res, err := repos.server.List(ctx, params)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, len(res.Servers()))
|
||||||
|
|
||||||
|
require.NoError(t, params.SetVersionCodes([]string{res.Servers()[0].VersionCode()}))
|
||||||
|
|
||||||
return params
|
return params
|
||||||
},
|
},
|
||||||
assertServers: func(t *testing.T, params domain.ListServersParams, servers domain.Servers) {
|
assertResult: func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
|
servers := res.Servers()
|
||||||
versionCodes := params.VersionCodes()
|
versionCodes := params.VersionCodes()
|
||||||
|
|
||||||
assert.NotEmpty(t, servers)
|
assert.NotEmpty(t, servers)
|
||||||
|
@ -261,37 +258,6 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
t.Helper()
|
t.Helper()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
},
|
},
|
||||||
assertTotal: func(t *testing.T, params domain.ListServersParams, total int) {
|
|
||||||
t.Helper()
|
|
||||||
assert.Equal(t, len(params.Keys()), total) //nolint:testifylint
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: fmt.Sprintf("OK: keyGT=%s", randServer.Key()),
|
|
||||||
params: func(t *testing.T) domain.ListServersParams {
|
|
||||||
t.Helper()
|
|
||||||
params := domain.NewListServersParams()
|
|
||||||
require.NoError(t, params.SetKeyGT(domain.NullString{
|
|
||||||
Value: randServer.Key(),
|
|
||||||
Valid: true,
|
|
||||||
}))
|
|
||||||
return params
|
|
||||||
},
|
|
||||||
assertServers: func(t *testing.T, params domain.ListServersParams, servers domain.Servers) {
|
|
||||||
t.Helper()
|
|
||||||
assert.NotEmpty(t, len(servers))
|
|
||||||
for _, s := range servers {
|
|
||||||
assert.Greater(t, s.Key(), params.KeyGT().Value, s.Key())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
assertError: func(t *testing.T, err error) {
|
|
||||||
t.Helper()
|
|
||||||
require.NoError(t, err)
|
|
||||||
},
|
|
||||||
assertTotal: func(t *testing.T, params domain.ListServersParams, total int) {
|
|
||||||
t.Helper()
|
|
||||||
assert.NotEmpty(t, total)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "OK: special=true",
|
name: "OK: special=true",
|
||||||
|
@ -304,8 +270,9 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
}))
|
}))
|
||||||
return params
|
return params
|
||||||
},
|
},
|
||||||
assertServers: func(t *testing.T, params domain.ListServersParams, servers domain.Servers) {
|
assertResult: func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
servers := res.Servers()
|
||||||
assert.NotEmpty(t, len(servers))
|
assert.NotEmpty(t, len(servers))
|
||||||
for _, s := range servers {
|
for _, s := range servers {
|
||||||
assert.True(t, s.Special(), s.Key())
|
assert.True(t, s.Special(), s.Key())
|
||||||
|
@ -315,10 +282,6 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
t.Helper()
|
t.Helper()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
},
|
},
|
||||||
assertTotal: func(t *testing.T, params domain.ListServersParams, total int) {
|
|
||||||
t.Helper()
|
|
||||||
assert.NotEmpty(t, total)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "OK: open=false",
|
name: "OK: open=false",
|
||||||
|
@ -331,8 +294,9 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
}))
|
}))
|
||||||
return params
|
return params
|
||||||
},
|
},
|
||||||
assertServers: func(t *testing.T, params domain.ListServersParams, servers domain.Servers) {
|
assertResult: func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
servers := res.Servers()
|
||||||
assert.NotEmpty(t, len(servers))
|
assert.NotEmpty(t, len(servers))
|
||||||
for _, s := range servers {
|
for _, s := range servers {
|
||||||
assert.False(t, s.Open(), s.Key())
|
assert.False(t, s.Open(), s.Key())
|
||||||
|
@ -342,10 +306,6 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
t.Helper()
|
t.Helper()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
},
|
},
|
||||||
assertTotal: func(t *testing.T, params domain.ListServersParams, total int) {
|
|
||||||
t.Helper()
|
|
||||||
assert.NotEmpty(t, total)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "OK: playerSnapshotsCreatedAtLt=" + snapshotsCreatedAtLT.Format(time.RFC3339),
|
name: "OK: playerSnapshotsCreatedAtLt=" + snapshotsCreatedAtLT.Format(time.RFC3339),
|
||||||
|
@ -358,8 +318,9 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
}))
|
}))
|
||||||
return params
|
return params
|
||||||
},
|
},
|
||||||
assertServers: func(t *testing.T, params domain.ListServersParams, servers domain.Servers) {
|
assertResult: func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
servers := res.Servers()
|
||||||
assert.NotEmpty(t, len(servers))
|
assert.NotEmpty(t, len(servers))
|
||||||
for _, s := range servers {
|
for _, s := range servers {
|
||||||
assert.True(t, s.PlayerSnapshotsCreatedAt().Before(snapshotsCreatedAtLT))
|
assert.True(t, s.PlayerSnapshotsCreatedAt().Before(snapshotsCreatedAtLT))
|
||||||
|
@ -369,10 +330,6 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
t.Helper()
|
t.Helper()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
},
|
},
|
||||||
assertTotal: func(t *testing.T, params domain.ListServersParams, total int) {
|
|
||||||
t.Helper()
|
|
||||||
assert.NotEmpty(t, total)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "OK: tribeSnapshotsCreatedAtLt=" + snapshotsCreatedAtLT.Format(time.RFC3339),
|
name: "OK: tribeSnapshotsCreatedAtLt=" + snapshotsCreatedAtLT.Format(time.RFC3339),
|
||||||
|
@ -385,8 +342,9 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
}))
|
}))
|
||||||
return params
|
return params
|
||||||
},
|
},
|
||||||
assertServers: func(t *testing.T, params domain.ListServersParams, servers domain.Servers) {
|
assertResult: func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
servers := res.Servers()
|
||||||
assert.NotEmpty(t, len(servers))
|
assert.NotEmpty(t, len(servers))
|
||||||
for _, s := range servers {
|
for _, s := range servers {
|
||||||
assert.True(t, s.TribeSnapshotsCreatedAt().Before(snapshotsCreatedAtLT))
|
assert.True(t, s.TribeSnapshotsCreatedAt().Before(snapshotsCreatedAtLT))
|
||||||
|
@ -396,31 +354,108 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
t.Helper()
|
t.Helper()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
},
|
},
|
||||||
assertTotal: func(t *testing.T, params domain.ListServersParams, total int) {
|
|
||||||
t.Helper()
|
|
||||||
assert.NotEmpty(t, total)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "OK: offset=1 limit=2",
|
name: "OK: cursor sort=[open ASC, key ASC]",
|
||||||
params: func(t *testing.T) domain.ListServersParams {
|
params: func(t *testing.T) domain.ListServersParams {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
params := domain.NewListServersParams()
|
params := domain.NewListServersParams()
|
||||||
require.NoError(t, params.SetOffset(1))
|
require.NoError(t, params.SetSort([]domain.ServerSort{domain.ServerSortOpenASC, domain.ServerSortKeyASC}))
|
||||||
require.NoError(t, params.SetLimit(2))
|
|
||||||
|
res, err := repos.server.List(ctx, params)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Greater(t, len(res.Servers()), 2)
|
||||||
|
|
||||||
|
require.NoError(t, params.SetCursor(domaintest.NewServerCursor(t, func(cfg *domaintest.ServerCursorConfig) {
|
||||||
|
cfg.Key = res.Servers()[1].Key()
|
||||||
|
cfg.Open = res.Servers()[1].Open()
|
||||||
|
})))
|
||||||
|
|
||||||
return params
|
return params
|
||||||
},
|
},
|
||||||
assertServers: func(t *testing.T, params domain.ListServersParams, servers domain.Servers) {
|
assertResult: func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
assert.Len(t, servers, params.Limit())
|
servers := res.Servers()
|
||||||
|
assert.NotEmpty(t, len(servers))
|
||||||
|
assert.True(t, slices.IsSortedFunc(servers, func(a, b domain.Server) int {
|
||||||
|
if a.Open() && !b.Open() {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if !a.Open() && b.Open() {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmp.Compare(a.Key(), b.Key())
|
||||||
|
}))
|
||||||
|
for _, s := range res.Servers() {
|
||||||
|
assert.GreaterOrEqual(t, s.Key(), params.Cursor().Key(), s.Key())
|
||||||
|
}
|
||||||
},
|
},
|
||||||
assertError: func(t *testing.T, err error) {
|
assertError: func(t *testing.T, err error) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
},
|
},
|
||||||
assertTotal: func(t *testing.T, params domain.ListServersParams, total int) {
|
},
|
||||||
|
{
|
||||||
|
name: "OK: cursor sort=[open DESC, key DESC]",
|
||||||
|
params: func(t *testing.T) domain.ListServersParams {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
assert.NotEmpty(t, total)
|
|
||||||
|
params := domain.NewListServersParams()
|
||||||
|
require.NoError(t, params.SetSort([]domain.ServerSort{domain.ServerSortOpenDESC, domain.ServerSortKeyDESC}))
|
||||||
|
|
||||||
|
res, err := repos.server.List(ctx, params)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Greater(t, len(res.Servers()), 2)
|
||||||
|
|
||||||
|
require.NoError(t, params.SetCursor(domaintest.NewServerCursor(t, func(cfg *domaintest.ServerCursorConfig) {
|
||||||
|
cfg.Key = res.Servers()[1].Key()
|
||||||
|
cfg.Open = res.Servers()[1].Open()
|
||||||
|
})))
|
||||||
|
|
||||||
|
return params
|
||||||
|
},
|
||||||
|
assertResult: func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult) {
|
||||||
|
t.Helper()
|
||||||
|
servers := res.Servers()
|
||||||
|
assert.NotEmpty(t, len(servers))
|
||||||
|
assert.True(t, slices.IsSortedFunc(servers, func(a, b domain.Server) int {
|
||||||
|
if a.Open() && !b.Open() {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if !a.Open() && b.Open() {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmp.Compare(a.Key(), b.Key()) * -1
|
||||||
|
}))
|
||||||
|
for _, s := range res.Servers() {
|
||||||
|
assert.LessOrEqual(t, s.Key(), params.Cursor().Key(), s.Key())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
assertError: func(t *testing.T, err error) {
|
||||||
|
t.Helper()
|
||||||
|
require.NoError(t, err)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "OK: limit=2",
|
||||||
|
params: func(t *testing.T) domain.ListServersParams {
|
||||||
|
t.Helper()
|
||||||
|
params := domain.NewListServersParams()
|
||||||
|
require.NoError(t, params.SetLimit(2))
|
||||||
|
return params
|
||||||
|
},
|
||||||
|
assertResult: func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult) {
|
||||||
|
t.Helper()
|
||||||
|
assert.Len(t, res.Servers(), params.Limit())
|
||||||
|
},
|
||||||
|
assertError: func(t *testing.T, err error) {
|
||||||
|
t.Helper()
|
||||||
|
require.NoError(t, err)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -435,7 +470,7 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
|
|
||||||
res, err := repos.server.List(ctx, params)
|
res, err := repos.server.List(ctx, params)
|
||||||
tt.assertError(t, err)
|
tt.assertError(t, err)
|
||||||
tt.assertServers(t, params, res)
|
tt.assertResult(t, params, res)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -454,6 +489,7 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
serversBeforeUpdate, err := repos.server.List(ctx, listServersBeforeUpdateParams)
|
serversBeforeUpdate, err := repos.server.List(ctx, listServersBeforeUpdateParams)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotEmpty(t, serversBeforeUpdate)
|
require.NotEmpty(t, serversBeforeUpdate)
|
||||||
|
serverBeforeUpdate := serversBeforeUpdate.Servers()[0]
|
||||||
|
|
||||||
var updateParams domain.UpdateServerParams
|
var updateParams domain.UpdateServerParams
|
||||||
require.NoError(t, updateParams.SetConfig(domain.NullServerConfig{
|
require.NoError(t, updateParams.SetConfig(domain.NullServerConfig{
|
||||||
|
@ -517,58 +553,59 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
|
||||||
Valid: true,
|
Valid: true,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
require.NoError(t, repos.server.Update(ctx, serversBeforeUpdate[0].Key(), updateParams))
|
require.NoError(t, repos.server.Update(ctx, serverBeforeUpdate.Key(), updateParams))
|
||||||
|
|
||||||
listServersAfterUpdateParams := domain.NewListServersParams()
|
listServersAfterUpdateParams := domain.NewListServersParams()
|
||||||
require.NoError(t, listServersAfterUpdateParams.SetLimit(1))
|
require.NoError(t, listServersAfterUpdateParams.SetLimit(1))
|
||||||
require.NoError(t, listServersAfterUpdateParams.SetKeys([]string{serversBeforeUpdate[0].Key()}))
|
require.NoError(t, listServersAfterUpdateParams.SetKeys([]string{serverBeforeUpdate.Key()}))
|
||||||
|
|
||||||
serversAfterUpdate, err := repos.server.List(ctx, listServersAfterUpdateParams)
|
serversAfterUpdate, err := repos.server.List(ctx, listServersAfterUpdateParams)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotEmpty(t, serversAfterUpdate)
|
require.NotEmpty(t, serversAfterUpdate)
|
||||||
assert.Equal(t, updateParams.Config().Value, serversAfterUpdate[0].Config())
|
serverAfterUpdate := serversAfterUpdate.Servers()[0]
|
||||||
assert.Equal(t, updateParams.UnitInfo().Value, serversAfterUpdate[0].UnitInfo())
|
assert.Equal(t, updateParams.Config().Value, serverAfterUpdate.Config())
|
||||||
assert.Equal(t, updateParams.BuildingInfo().Value, serversAfterUpdate[0].BuildingInfo())
|
assert.Equal(t, updateParams.UnitInfo().Value, serverAfterUpdate.UnitInfo())
|
||||||
assert.Equal(t, updateParams.NumTribes().Value, serversAfterUpdate[0].NumTribes())
|
assert.Equal(t, updateParams.BuildingInfo().Value, serverAfterUpdate.BuildingInfo())
|
||||||
|
assert.Equal(t, updateParams.NumTribes().Value, serverAfterUpdate.NumTribes())
|
||||||
assert.WithinDuration(
|
assert.WithinDuration(
|
||||||
t,
|
t,
|
||||||
updateParams.TribeDataSyncedAt().Value,
|
updateParams.TribeDataSyncedAt().Value,
|
||||||
serversAfterUpdate[0].TribeDataSyncedAt(),
|
serverAfterUpdate.TribeDataSyncedAt(),
|
||||||
time.Minute,
|
time.Minute,
|
||||||
)
|
)
|
||||||
assert.Equal(t, updateParams.NumPlayers().Value, serversAfterUpdate[0].NumPlayers())
|
assert.Equal(t, updateParams.NumPlayers().Value, serverAfterUpdate.NumPlayers())
|
||||||
assert.WithinDuration(
|
assert.WithinDuration(
|
||||||
t,
|
t,
|
||||||
updateParams.PlayerDataSyncedAt().Value,
|
updateParams.PlayerDataSyncedAt().Value,
|
||||||
serversAfterUpdate[0].PlayerDataSyncedAt(),
|
serverAfterUpdate.PlayerDataSyncedAt(),
|
||||||
time.Minute,
|
time.Minute,
|
||||||
)
|
)
|
||||||
assert.Equal(t, updateParams.NumVillages().Value, serversAfterUpdate[0].NumVillages())
|
assert.Equal(t, updateParams.NumVillages().Value, serverAfterUpdate.NumVillages())
|
||||||
assert.Equal(t, updateParams.NumPlayerVillages().Value, serversAfterUpdate[0].NumPlayerVillages())
|
assert.Equal(t, updateParams.NumPlayerVillages().Value, serverAfterUpdate.NumPlayerVillages())
|
||||||
assert.Equal(t, updateParams.NumBarbarianVillages().Value, serversAfterUpdate[0].NumBarbarianVillages())
|
assert.Equal(t, updateParams.NumBarbarianVillages().Value, serverAfterUpdate.NumBarbarianVillages())
|
||||||
assert.Equal(t, updateParams.NumBonusVillages().Value, serversAfterUpdate[0].NumBonusVillages())
|
assert.Equal(t, updateParams.NumBonusVillages().Value, serverAfterUpdate.NumBonusVillages())
|
||||||
assert.WithinDuration(
|
assert.WithinDuration(
|
||||||
t,
|
t,
|
||||||
updateParams.VillageDataSyncedAt().Value,
|
updateParams.VillageDataSyncedAt().Value,
|
||||||
serversAfterUpdate[0].VillageDataSyncedAt(),
|
serverAfterUpdate.VillageDataSyncedAt(),
|
||||||
time.Minute,
|
time.Minute,
|
||||||
)
|
)
|
||||||
assert.WithinDuration(
|
assert.WithinDuration(
|
||||||
t,
|
t,
|
||||||
updateParams.EnnoblementDataSyncedAt().Value,
|
updateParams.EnnoblementDataSyncedAt().Value,
|
||||||
serversAfterUpdate[0].EnnoblementDataSyncedAt(),
|
serverAfterUpdate.EnnoblementDataSyncedAt(),
|
||||||
time.Minute,
|
time.Minute,
|
||||||
)
|
)
|
||||||
assert.WithinDuration(
|
assert.WithinDuration(
|
||||||
t,
|
t,
|
||||||
updateParams.TribeSnapshotsCreatedAt().Value,
|
updateParams.TribeSnapshotsCreatedAt().Value,
|
||||||
serversAfterUpdate[0].TribeSnapshotsCreatedAt(),
|
serverAfterUpdate.TribeSnapshotsCreatedAt(),
|
||||||
time.Minute,
|
time.Minute,
|
||||||
)
|
)
|
||||||
assert.WithinDuration(
|
assert.WithinDuration(
|
||||||
t,
|
t,
|
||||||
updateParams.PlayerSnapshotsCreatedAt().Value,
|
updateParams.PlayerSnapshotsCreatedAt().Value,
|
||||||
serversAfterUpdate[0].PlayerSnapshotsCreatedAt(),
|
serverAfterUpdate.PlayerSnapshotsCreatedAt(),
|
||||||
time.Minute,
|
time.Minute,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -17,7 +17,7 @@ type versionRepository interface {
|
||||||
|
|
||||||
type serverRepository interface {
|
type serverRepository interface {
|
||||||
CreateOrUpdate(ctx context.Context, params ...domain.CreateServerParams) error
|
CreateOrUpdate(ctx context.Context, params ...domain.CreateServerParams) error
|
||||||
List(ctx context.Context, params domain.ListServersParams) (domain.Servers, error)
|
List(ctx context.Context, params domain.ListServersParams) (domain.ListServersResult, error)
|
||||||
Update(ctx context.Context, key string, params domain.UpdateServerParams) error
|
Update(ctx context.Context, key string, params domain.UpdateServerParams) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,10 +63,10 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
|
||||||
t.Run("OK", func(t *testing.T) {
|
t.Run("OK", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
servers, err := repos.server.List(ctx, domain.NewListServersParams())
|
listServersRes, err := repos.server.List(ctx, domain.NewListServersParams())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotEmpty(t, servers)
|
require.NotEmpty(t, listServersRes)
|
||||||
server := servers[0]
|
server := listServersRes.Servers()[0]
|
||||||
|
|
||||||
tribesToCreate := domain.BaseTribes{
|
tribesToCreate := domain.BaseTribes{
|
||||||
domaintest.NewBaseTribe(t),
|
domaintest.NewBaseTribe(t),
|
||||||
|
@ -114,9 +114,9 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
|
||||||
Valid: true,
|
Valid: true,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
servers, listServersErr := repos.server.List(ctx, listServersParams)
|
listServersRes, listServersErr := repos.server.List(ctx, listServersParams)
|
||||||
require.NoError(t, listServersErr)
|
require.NoError(t, listServersErr)
|
||||||
require.GreaterOrEqual(t, len(servers), 2)
|
require.GreaterOrEqual(t, len(listServersRes.Servers()), 2)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -125,12 +125,12 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "numPlayerVillages=0",
|
name: "numPlayerVillages=0",
|
||||||
serverKey: servers[0].Key(),
|
serverKey: listServersRes.Servers()[0].Key(),
|
||||||
numPlayerVillages: 0,
|
numPlayerVillages: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "numPlayerVillages=35000",
|
name: "numPlayerVillages=35000",
|
||||||
serverKey: servers[1].Key(),
|
serverKey: listServersRes.Servers()[1].Key(),
|
||||||
numPlayerVillages: 35000,
|
numPlayerVillages: 35000,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -390,15 +390,15 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
|
||||||
|
|
||||||
listServersParams := domain.NewListServersParams()
|
listServersParams := domain.NewListServersParams()
|
||||||
require.NoError(t, listServersParams.SetSpecial(domain.NullBool{Value: false, Valid: true}))
|
require.NoError(t, listServersParams.SetSpecial(domain.NullBool{Value: false, Valid: true}))
|
||||||
servers, listServersErr := repos.server.List(ctx, listServersParams)
|
listServersRes, listServersErr := repos.server.List(ctx, listServersParams)
|
||||||
require.NoError(t, listServersErr)
|
require.NoError(t, listServersErr)
|
||||||
require.NotEmpty(t, servers)
|
require.NotEmpty(t, listServersRes)
|
||||||
|
|
||||||
t.Run("OK", func(t *testing.T) {
|
t.Run("OK", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
serverKeys := make([]string, 0, len(servers))
|
serverKeys := make([]string, 0, len(listServersRes.Servers()))
|
||||||
for _, s := range servers {
|
for _, s := range listServersRes.Servers() {
|
||||||
serverKeys = append(serverKeys, s.Key())
|
serverKeys = append(serverKeys, s.Key())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,7 +450,7 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
|
||||||
t.Run("OK: len(ids) == 0", func(t *testing.T) {
|
t.Run("OK: len(ids) == 0", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
require.NoError(t, repos.tribe.Delete(ctx, servers[0].Key()))
|
require.NoError(t, repos.tribe.Delete(ctx, listServersRes.Servers()[0].Key()))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,10 +56,10 @@ func testVillageRepository(t *testing.T, newRepos func(t *testing.T) repositorie
|
||||||
t.Run("OK", func(t *testing.T) {
|
t.Run("OK", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
servers, err := repos.server.List(ctx, domain.NewListServersParams())
|
listServersRes, err := repos.server.List(ctx, domain.NewListServersParams())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotEmpty(t, servers)
|
require.NotEmpty(t, listServersRes)
|
||||||
server := servers[0]
|
server := listServersRes.Servers()[0]
|
||||||
|
|
||||||
villagesToCreate := domain.BaseVillages{
|
villagesToCreate := domain.BaseVillages{
|
||||||
domaintest.NewBaseVillage(t),
|
domaintest.NewBaseVillage(t),
|
||||||
|
@ -263,15 +263,15 @@ func testVillageRepository(t *testing.T, newRepos func(t *testing.T) repositorie
|
||||||
|
|
||||||
listServersParams := domain.NewListServersParams()
|
listServersParams := domain.NewListServersParams()
|
||||||
require.NoError(t, listServersParams.SetSpecial(domain.NullBool{Value: false, Valid: true}))
|
require.NoError(t, listServersParams.SetSpecial(domain.NullBool{Value: false, Valid: true}))
|
||||||
servers, listServersErr := repos.server.List(ctx, listServersParams)
|
listServersRes, listServersErr := repos.server.List(ctx, listServersParams)
|
||||||
require.NoError(t, listServersErr)
|
require.NoError(t, listServersErr)
|
||||||
require.NotEmpty(t, servers)
|
require.NotEmpty(t, listServersRes)
|
||||||
|
|
||||||
t.Run("OK", func(t *testing.T) {
|
t.Run("OK", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
serverKeys := make([]string, 0, len(servers))
|
serverKeys := make([]string, 0, len(listServersRes.Servers()))
|
||||||
for _, s := range servers {
|
for _, s := range listServersRes.Servers() {
|
||||||
serverKeys = append(serverKeys, s.Key())
|
serverKeys = append(serverKeys, s.Key())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,7 +311,7 @@ func testVillageRepository(t *testing.T, newRepos func(t *testing.T) repositorie
|
||||||
t.Run("OK: len(ids) == 0", func(t *testing.T) {
|
t.Run("OK: len(ids) == 0", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
require.NoError(t, repos.village.Delete(ctx, servers[0].Key()))
|
require.NoError(t, repos.village.Delete(ctx, listServersRes.Servers()[0].Key()))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
|
|
||||||
type ServerRepository interface {
|
type ServerRepository interface {
|
||||||
CreateOrUpdate(ctx context.Context, params ...domain.CreateServerParams) error
|
CreateOrUpdate(ctx context.Context, params ...domain.CreateServerParams) error
|
||||||
List(ctx context.Context, params domain.ListServersParams) (domain.Servers, error)
|
List(ctx context.Context, params domain.ListServersParams) (domain.ListServersResult, error)
|
||||||
Update(ctx context.Context, key string, params domain.UpdateServerParams) error
|
Update(ctx context.Context, key string, params domain.UpdateServerParams) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,11 +101,8 @@ func (svc *ServerService) ListAllOpen(ctx context.Context, versionCode string) (
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListAll retrieves all servers from the database based on the given params in an optimal way.
|
// ListAll retrieves all servers from the database based on the given params in an optimal way.
|
||||||
// You can't specify a custom limit/offset/sort/keyGT for this operation.
|
// You can't specify a custom limit/cursor/sort for this operation.
|
||||||
func (svc *ServerService) ListAll(ctx context.Context, params domain.ListServersParams) (domain.Servers, error) {
|
func (svc *ServerService) ListAll(ctx context.Context, params domain.ListServersParams) (domain.Servers, error) {
|
||||||
if err := params.SetOffset(0); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := params.SetLimit(domain.ServerListMaxLimit); err != nil {
|
if err := params.SetLimit(domain.ServerListMaxLimit); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -116,21 +113,18 @@ func (svc *ServerService) ListAll(ctx context.Context, params domain.ListServers
|
||||||
var servers domain.Servers
|
var servers domain.Servers
|
||||||
|
|
||||||
for {
|
for {
|
||||||
ss, err := svc.repo.List(ctx, params)
|
res, err := svc.repo.List(ctx, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ss) == 0 {
|
servers = append(servers, res.Servers()...)
|
||||||
|
|
||||||
|
if res.Next().IsZero() {
|
||||||
return servers, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
servers = append(servers, ss...)
|
if err = params.SetCursor(res.Next()); err != nil {
|
||||||
|
|
||||||
if err = params.SetKeyGT(domain.NullString{
|
|
||||||
Value: ss[len(ss)-1].Key(),
|
|
||||||
Valid: true,
|
|
||||||
}); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,29 @@ func RandServerKey() string {
|
||||||
return gofakeit.LetterN(5)
|
return gofakeit.LetterN(5)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ServerCursorConfig struct {
|
||||||
|
Key string
|
||||||
|
Open bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewServerCursor(tb TestingTB, opts ...func(cfg *ServerCursorConfig)) domain.ServerCursor {
|
||||||
|
tb.Helper()
|
||||||
|
|
||||||
|
cfg := &ServerCursorConfig{
|
||||||
|
Key: RandServerKey(),
|
||||||
|
Open: gofakeit.Bool(),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
vc, err := domain.NewServerCursor(cfg.Key, cfg.Open)
|
||||||
|
require.NoError(tb, err)
|
||||||
|
|
||||||
|
return vc
|
||||||
|
}
|
||||||
|
|
||||||
type ServerConfig struct {
|
type ServerConfig struct {
|
||||||
Key string
|
Key string
|
||||||
VersionCode string
|
VersionCode string
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"net/url"
|
"net/url"
|
||||||
"slices"
|
"slices"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -200,6 +201,10 @@ func (s Server) EnnoblementDataSyncedAt() time.Time {
|
||||||
return s.ennoblementDataSyncedAt
|
return s.ennoblementDataSyncedAt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s Server) IsZero() bool {
|
||||||
|
return s == Server{}
|
||||||
|
}
|
||||||
|
|
||||||
func (s Server) Base() BaseServer {
|
func (s Server) Base() BaseServer {
|
||||||
return BaseServer{
|
return BaseServer{
|
||||||
key: s.key,
|
key: s.key,
|
||||||
|
@ -464,17 +469,77 @@ const (
|
||||||
ServerSortOpenDESC
|
ServerSortOpenDESC
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ServerCursor struct {
|
||||||
|
key string
|
||||||
|
open bool
|
||||||
|
}
|
||||||
|
|
||||||
|
const serverCursorModelName = "ServerCursor"
|
||||||
|
|
||||||
|
func NewServerCursor(key string, open bool) (ServerCursor, error) {
|
||||||
|
if err := validateServerKey(key); err != nil {
|
||||||
|
return ServerCursor{}, ValidationError{
|
||||||
|
Model: serverCursorModelName,
|
||||||
|
Field: "key",
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ServerCursor{key: key, open: open}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeServerCursor(encoded string) (ServerCursor, error) {
|
||||||
|
m, err := decodeCursor(encoded)
|
||||||
|
if err != nil {
|
||||||
|
return ServerCursor{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
open, err := strconv.ParseBool(m["open"])
|
||||||
|
if err != nil {
|
||||||
|
return ServerCursor{}, ErrInvalidCursor
|
||||||
|
}
|
||||||
|
|
||||||
|
vc, err := NewServerCursor(m["key"], open)
|
||||||
|
if err != nil {
|
||||||
|
return ServerCursor{}, ErrInvalidCursor
|
||||||
|
}
|
||||||
|
|
||||||
|
return vc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sc ServerCursor) Key() string {
|
||||||
|
return sc.key
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sc ServerCursor) Open() bool {
|
||||||
|
return sc.open
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sc ServerCursor) IsZero() bool {
|
||||||
|
return sc == ServerCursor{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sc ServerCursor) Encode() string {
|
||||||
|
if sc.IsZero() {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return encodeCursor([][2]string{
|
||||||
|
{"key", sc.key},
|
||||||
|
{"open", strconv.FormatBool(sc.open)},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
type ListServersParams struct {
|
type ListServersParams struct {
|
||||||
keys []string
|
keys []string
|
||||||
keyGT NullString
|
|
||||||
versionCodes []string
|
versionCodes []string
|
||||||
open NullBool
|
open NullBool
|
||||||
special NullBool
|
special NullBool
|
||||||
tribeSnapshotsCreatedAtLT NullTime
|
tribeSnapshotsCreatedAtLT NullTime
|
||||||
playerSnapshotsCreatedAtLT NullTime
|
playerSnapshotsCreatedAtLT NullTime
|
||||||
sort []ServerSort
|
sort []ServerSort
|
||||||
|
cursor ServerCursor
|
||||||
limit int
|
limit int
|
||||||
offset int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -502,15 +567,6 @@ func (params *ListServersParams) SetKeys(keys []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (params *ListServersParams) KeyGT() NullString {
|
|
||||||
return params.keyGT
|
|
||||||
}
|
|
||||||
|
|
||||||
func (params *ListServersParams) SetKeyGT(keyGT NullString) error {
|
|
||||||
params.keyGT = keyGT
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (params *ListServersParams) VersionCodes() []string {
|
func (params *ListServersParams) VersionCodes() []string {
|
||||||
return params.versionCodes
|
return params.versionCodes
|
||||||
}
|
}
|
||||||
|
@ -579,6 +635,30 @@ func (params *ListServersParams) SetSort(sort []ServerSort) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (params *ListServersParams) Cursor() ServerCursor {
|
||||||
|
return params.cursor
|
||||||
|
}
|
||||||
|
|
||||||
|
func (params *ListServersParams) SetCursor(cursor ServerCursor) error {
|
||||||
|
params.cursor = cursor
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (params *ListServersParams) SetEncodedCursor(encoded string) error {
|
||||||
|
decoded, err := decodeServerCursor(encoded)
|
||||||
|
if err != nil {
|
||||||
|
return ValidationError{
|
||||||
|
Model: listServersParamsModelName,
|
||||||
|
Field: "cursor",
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
params.cursor = decoded
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (params *ListServersParams) Limit() int {
|
func (params *ListServersParams) Limit() int {
|
||||||
return params.limit
|
return params.limit
|
||||||
}
|
}
|
||||||
|
@ -597,22 +677,55 @@ func (params *ListServersParams) SetLimit(limit int) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (params *ListServersParams) Offset() int {
|
type ListServersResult struct {
|
||||||
return params.offset
|
servers Servers
|
||||||
|
self ServerCursor
|
||||||
|
next ServerCursor
|
||||||
}
|
}
|
||||||
|
|
||||||
func (params *ListServersParams) SetOffset(offset int) error {
|
const listServersResultModelName = "ListServersResult"
|
||||||
if err := validateIntInRange(offset, 0, math.MaxInt); err != nil {
|
|
||||||
return ValidationError{
|
func NewListServersResult(servers Servers, next Server) (ListServersResult, error) {
|
||||||
Model: listServersParamsModelName,
|
var err error
|
||||||
Field: "offset",
|
res := ListServersResult{
|
||||||
Err: err,
|
servers: servers,
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(servers) > 0 {
|
||||||
|
res.self, err = NewServerCursor(servers[0].Key(), servers[0].Open())
|
||||||
|
if err != nil {
|
||||||
|
return ListServersResult{}, ValidationError{
|
||||||
|
Model: listServersResultModelName,
|
||||||
|
Field: "self",
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
params.offset = offset
|
if !next.IsZero() {
|
||||||
|
res.next, err = NewServerCursor(next.Key(), next.Open())
|
||||||
|
if err != nil {
|
||||||
|
return ListServersResult{}, ValidationError{
|
||||||
|
Model: listServersResultModelName,
|
||||||
|
Field: "next",
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (res ListServersResult) Servers() Servers {
|
||||||
|
return res.servers
|
||||||
|
}
|
||||||
|
|
||||||
|
func (res ListServersResult) Self() ServerCursor {
|
||||||
|
return res.self
|
||||||
|
}
|
||||||
|
|
||||||
|
func (res ListServersResult) Next() ServerCursor {
|
||||||
|
return res.next
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerNotFoundError struct {
|
type ServerNotFoundError struct {
|
||||||
|
|
|
@ -187,6 +187,65 @@ func TestUpdateServerParams_SetNumTribes(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewServerCursor(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
validServerCursor := domaintest.NewServerCursor(t)
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
key string
|
||||||
|
open bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type test struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
expectedErr error
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []test{
|
||||||
|
{
|
||||||
|
name: "OK",
|
||||||
|
args: args{
|
||||||
|
key: validServerCursor.Key(),
|
||||||
|
open: validServerCursor.Open(),
|
||||||
|
},
|
||||||
|
expectedErr: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, serverKeyTest := range newServerKeyValidationTests() {
|
||||||
|
tests = append(tests, test{
|
||||||
|
name: serverKeyTest.name,
|
||||||
|
args: args{
|
||||||
|
key: serverKeyTest.key,
|
||||||
|
},
|
||||||
|
expectedErr: domain.ValidationError{
|
||||||
|
Model: "ServerCursor",
|
||||||
|
Field: "key",
|
||||||
|
Err: serverKeyTest.expectedErr,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
tt := tt
|
||||||
|
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
sc, err := domain.NewServerCursor(tt.args.key, tt.args.open)
|
||||||
|
require.ErrorIs(t, err, tt.expectedErr)
|
||||||
|
if tt.expectedErr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.Equal(t, tt.args.key, sc.Key())
|
||||||
|
assert.Equal(t, tt.args.open, sc.Open())
|
||||||
|
assert.NotEmpty(t, sc.Encode())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestListServersParams_SetSort(t *testing.T) {
|
func TestListServersParams_SetSort(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
@ -260,6 +319,90 @@ func TestListServersParams_SetSort(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestListServersParams_SetEncodedCursor(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
validCursor := domaintest.NewServerCursor(t)
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
cursor string
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
expectedCursor domain.ServerCursor
|
||||||
|
expectedErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "OK",
|
||||||
|
args: args{
|
||||||
|
cursor: validCursor.Encode(),
|
||||||
|
},
|
||||||
|
expectedCursor: validCursor,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ERR: len(cursor) < 1",
|
||||||
|
args: args{
|
||||||
|
cursor: "",
|
||||||
|
},
|
||||||
|
expectedErr: domain.ValidationError{
|
||||||
|
Model: "ListServersParams",
|
||||||
|
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: "ListServersParams",
|
||||||
|
Field: "cursor",
|
||||||
|
Err: domain.LenOutOfRangeError{
|
||||||
|
Min: 1,
|
||||||
|
Max: 1000,
|
||||||
|
Current: 1001,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ERR: malformed base64",
|
||||||
|
args: args{
|
||||||
|
cursor: "112345",
|
||||||
|
},
|
||||||
|
expectedErr: domain.ValidationError{
|
||||||
|
Model: "ListServersParams",
|
||||||
|
Field: "cursor",
|
||||||
|
Err: domain.ErrInvalidCursor,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
tt := tt
|
||||||
|
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
params := domain.NewListServersParams()
|
||||||
|
|
||||||
|
require.ErrorIs(t, params.SetEncodedCursor(tt.args.cursor), tt.expectedErr)
|
||||||
|
if tt.expectedErr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
assert.Equal(t, tt.expectedCursor.Key(), params.Cursor().Key())
|
||||||
|
assert.Equal(t, tt.expectedCursor.Open(), params.Cursor().Open())
|
||||||
|
assert.Equal(t, tt.args.cursor, params.Cursor().Encode())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestListServersParams_SetLimit(t *testing.T) {
|
func TestListServersParams_SetLimit(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
@ -325,55 +468,48 @@ func TestListServersParams_SetLimit(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestListServersParams_SetOffset(t *testing.T) {
|
func TestNewListServersResult(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
type args struct {
|
servers := domain.Servers{
|
||||||
offset int
|
domaintest.NewServer(t),
|
||||||
|
domaintest.NewServer(t),
|
||||||
|
domaintest.NewServer(t),
|
||||||
}
|
}
|
||||||
|
next := domaintest.NewServer(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: "ListServersParams",
|
|
||||||
Field: "offset",
|
|
||||||
Err: domain.MinGreaterEqualError{
|
|
||||||
Min: 0,
|
|
||||||
Current: -1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
res, err := domain.NewListServersResult(servers, next)
|
||||||
tt := tt
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, servers, res.Servers())
|
||||||
|
assert.Equal(t, servers[0].Key(), res.Self().Key())
|
||||||
|
assert.Equal(t, servers[0].Open(), res.Self().Open())
|
||||||
|
assert.Equal(t, next.Key(), res.Next().Key())
|
||||||
|
assert.Equal(t, next.Open(), res.Next().Open())
|
||||||
|
})
|
||||||
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run("OK: without next", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
params := domain.NewListServersParams()
|
res, err := domain.NewListServersResult(servers, domain.Server{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, servers, res.Servers())
|
||||||
|
assert.Equal(t, servers[0].Key(), res.Self().Key())
|
||||||
|
assert.Equal(t, servers[0].Open(), res.Self().Open())
|
||||||
|
assert.True(t, res.Next().IsZero())
|
||||||
|
})
|
||||||
|
|
||||||
require.ErrorIs(t, params.SetOffset(tt.args.offset), tt.expectedErr)
|
t.Run("OK: 0 versions", func(t *testing.T) {
|
||||||
if tt.expectedErr != nil {
|
t.Parallel()
|
||||||
return
|
|
||||||
}
|
res, err := domain.NewListServersResult(nil, domain.Server{})
|
||||||
assert.Equal(t, tt.args.offset, params.Offset())
|
require.NoError(t, err)
|
||||||
})
|
assert.Zero(t, res.Servers())
|
||||||
}
|
assert.True(t, res.Self().IsZero())
|
||||||
|
assert.True(t, res.Next().IsZero())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type serverKeyValidationTest struct {
|
type serverKeyValidationTest struct {
|
||||||
|
|
|
@ -23,33 +23,42 @@ const (
|
||||||
cursorKeyValueSeparator = "="
|
cursorKeyValueSeparator = "="
|
||||||
)
|
)
|
||||||
|
|
||||||
func encodeCursor(m map[string]string) string {
|
func encodeCursor(s [][2]string) string {
|
||||||
if len(m) == 0 {
|
if len(s) == 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
n := len(cursorSeparator) * (len(m) - 1)
|
n := len(cursorSeparator) * (len(s) - 1)
|
||||||
for k, v := range m {
|
for _, el := range s {
|
||||||
n += len(k) + len(v) + len(cursorKeyValueSeparator)
|
n += len(el[0]) + len(el[1]) + len(cursorKeyValueSeparator)
|
||||||
}
|
}
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
b.Grow(n)
|
b.Grow(n)
|
||||||
|
|
||||||
for k, v := range m {
|
for _, el := range s {
|
||||||
if b.Len() > 0 {
|
if b.Len() > 0 {
|
||||||
_, _ = b.WriteString(cursorSeparator)
|
_, _ = b.WriteString(cursorSeparator)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _ = b.WriteString(k)
|
_, _ = b.WriteString(el[0])
|
||||||
_, _ = b.WriteString(cursorKeyValueSeparator)
|
_, _ = b.WriteString(cursorKeyValueSeparator)
|
||||||
_, _ = b.WriteString(v)
|
_, _ = b.WriteString(el[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
return base64.StdEncoding.EncodeToString(b.Bytes())
|
return base64.StdEncoding.EncodeToString(b.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
encodedCursorMinLength = 1
|
||||||
|
encodedCursorMaxLength = 1000
|
||||||
|
)
|
||||||
|
|
||||||
func decodeCursor(s string) (map[string]string, error) {
|
func decodeCursor(s string) (map[string]string, error) {
|
||||||
|
if err := validateStringLen(s, encodedCursorMinLength, encodedCursorMaxLength); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
decodedBytes, err := base64.StdEncoding.DecodeString(s)
|
decodedBytes, err := base64.StdEncoding.DecodeString(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ErrInvalidCursor
|
return nil, ErrInvalidCursor
|
||||||
|
|
|
@ -125,16 +125,7 @@ func NewVersionCursor(code string) (VersionCursor, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
encodedVersionCursorMinLength = 1
|
|
||||||
encodedVersionCursorMaxLength = 1000
|
|
||||||
)
|
|
||||||
|
|
||||||
func decodeVersionCursor(encoded string) (VersionCursor, error) {
|
func decodeVersionCursor(encoded string) (VersionCursor, error) {
|
||||||
if err := validateStringLen(encoded, encodedVersionCursorMinLength, encodedVersionCursorMaxLength); err != nil {
|
|
||||||
return VersionCursor{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
m, err := decodeCursor(encoded)
|
m, err := decodeCursor(encoded)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return VersionCursor{}, err
|
return VersionCursor{}, err
|
||||||
|
@ -161,8 +152,8 @@ func (vc VersionCursor) Encode() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return encodeCursor(map[string]string{
|
return encodeCursor([][2]string{
|
||||||
"code": vc.code,
|
{"code", vc.code},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -214,7 +214,6 @@ func TestListVersionsParams_SetEncodedCursor(t *testing.T) {
|
||||||
|
|
||||||
require.ErrorIs(t, params.SetEncodedCursor(tt.args.cursor), tt.expectedErr)
|
require.ErrorIs(t, params.SetEncodedCursor(tt.args.cursor), tt.expectedErr)
|
||||||
if tt.expectedErr != nil {
|
if tt.expectedErr != nil {
|
||||||
fmt.Println(tt.expectedErr.Error())
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
assert.Equal(t, tt.expectedCursor.Code(), params.Cursor().Code())
|
assert.Equal(t, tt.expectedCursor.Code(), params.Cursor().Code())
|
||||||
|
|
|
@ -215,19 +215,16 @@ func TestDataSync(t *testing.T) {
|
||||||
allServers := make(domain.Servers, 0, len(expectedServers))
|
allServers := make(domain.Servers, 0, len(expectedServers))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
servers, err := serverRepo.List(ctx, listParams)
|
res, err := serverRepo.List(ctx, listParams)
|
||||||
require.NoError(collect, err)
|
require.NoError(collect, err)
|
||||||
|
|
||||||
if len(servers) == 0 {
|
allServers = append(allServers, res.Servers()...)
|
||||||
|
|
||||||
|
if res.Next().IsZero() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
allServers = append(allServers, servers...)
|
require.NoError(collect, listParams.SetCursor(res.Next()))
|
||||||
|
|
||||||
require.NoError(collect, listParams.SetKeyGT(domain.NullString{
|
|
||||||
Value: servers[len(servers)-1].Key(),
|
|
||||||
Valid: true,
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !assert.Len(collect, allServers, len(expectedServers)) {
|
if !assert.Len(collect, allServers, len(expectedServers)) {
|
||||||
|
|
|
@ -173,21 +173,18 @@ func TestEnnoblementSync(t *testing.T) {
|
||||||
require.NoError(collect, listParams.SetLimit(domain.ServerListMaxLimit))
|
require.NoError(collect, listParams.SetLimit(domain.ServerListMaxLimit))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
servers, err := serverRepo.List(ctx, listParams)
|
res, err := serverRepo.List(ctx, listParams)
|
||||||
require.NoError(collect, err)
|
require.NoError(collect, err)
|
||||||
|
|
||||||
if len(servers) == 0 {
|
for _, s := range res.Servers() {
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range servers {
|
|
||||||
assert.WithinDuration(collect, time.Now(), s.EnnoblementDataSyncedAt(), time.Minute)
|
assert.WithinDuration(collect, time.Now(), s.EnnoblementDataSyncedAt(), time.Minute)
|
||||||
}
|
}
|
||||||
|
|
||||||
require.NoError(collect, listParams.SetKeyGT(domain.NullString{
|
if res.Next().IsZero() {
|
||||||
Value: servers[len(servers)-1].Key(),
|
break
|
||||||
Valid: true,
|
}
|
||||||
}))
|
|
||||||
|
require.NoError(collect, listParams.SetCursor(res.Next()))
|
||||||
}
|
}
|
||||||
}, 30*time.Second, time.Second, "servers")
|
}, 30*time.Second, time.Second, "servers")
|
||||||
|
|
||||||
|
|
|
@ -157,22 +157,19 @@ func TestSnapshotCreation(t *testing.T) {
|
||||||
require.NoError(collect, listParams.SetLimit(domain.ServerListMaxLimit))
|
require.NoError(collect, listParams.SetLimit(domain.ServerListMaxLimit))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
servers, err := serverRepo.List(ctx, listParams)
|
res, err := serverRepo.List(ctx, listParams)
|
||||||
require.NoError(collect, err)
|
require.NoError(collect, err)
|
||||||
|
|
||||||
if len(servers) == 0 {
|
for _, s := range res.Servers() {
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range servers {
|
|
||||||
assert.WithinDuration(collect, time.Now(), s.PlayerSnapshotsCreatedAt(), time.Minute, s.Key())
|
assert.WithinDuration(collect, time.Now(), s.PlayerSnapshotsCreatedAt(), time.Minute, s.Key())
|
||||||
assert.WithinDuration(collect, time.Now(), s.TribeSnapshotsCreatedAt(), time.Minute, s.Key())
|
assert.WithinDuration(collect, time.Now(), s.TribeSnapshotsCreatedAt(), time.Minute, s.Key())
|
||||||
}
|
}
|
||||||
|
|
||||||
require.NoError(collect, listParams.SetKeyGT(domain.NullString{
|
if res.Next().IsZero() {
|
||||||
Value: servers[len(servers)-1].Key(),
|
return
|
||||||
Valid: true,
|
}
|
||||||
}))
|
|
||||||
|
require.NoError(collect, listParams.SetCursor(res.Next()))
|
||||||
}
|
}
|
||||||
}, 30*time.Second, 500*time.Millisecond, "servers")
|
}, 30*time.Second, 500*time.Millisecond, "servers")
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue