feat: tribe snapshots/player snapshots/ennoblements cleanup (#34)
ci/woodpecker/push/govulncheck Pipeline was successful Details
ci/woodpecker/push/test Pipeline was successful Details

Reviewed-on: twhelp/corev3#34
This commit is contained in:
Dawid Wysokiński 2024-03-24 08:49:01 +00:00
parent 55c7a0c405
commit 4819ec39cd
28 changed files with 582 additions and 94 deletions

View File

@ -125,6 +125,7 @@ var cmdConsumer = &cli.Command{
c.String(rmqFlagTopicServerSyncedEvent.Name), c.String(rmqFlagTopicServerSyncedEvent.Name),
c.String(rmqFlagTopicVillagesSyncedEvent.Name), c.String(rmqFlagTopicVillagesSyncedEvent.Name),
c.String(rmqFlagTopicCreateTribeSnapshotsCmd.Name), c.String(rmqFlagTopicCreateTribeSnapshotsCmd.Name),
c.String(rmqFlagTopicCleanUpDataCmd.Name),
) )
consumer.Register(router) consumer.Register(router)
@ -188,6 +189,7 @@ var cmdConsumer = &cli.Command{
marshaler, marshaler,
c.String(rmqFlagTopicServerSyncedEvent.Name), c.String(rmqFlagTopicServerSyncedEvent.Name),
c.String(rmqFlagTopicCreatePlayerSnapshotsCmd.Name), c.String(rmqFlagTopicCreatePlayerSnapshotsCmd.Name),
c.String(rmqFlagTopicCleanUpDataCmd.Name),
) )
consumer.Register(router) consumer.Register(router)
@ -273,6 +275,7 @@ var cmdConsumer = &cli.Command{
logger, logger,
marshaler, marshaler,
c.String(rmqFlagTopicSyncEnnoblementsCmd.Name), c.String(rmqFlagTopicSyncEnnoblementsCmd.Name),
c.String(rmqFlagTopicCleanUpDataCmd.Name),
) )
consumer.Register(router) consumer.Register(router)

View File

@ -5,6 +5,7 @@ import (
"database/sql" "database/sql"
"errors" "errors"
"fmt" "fmt"
"time"
"gitea.dwysokinski.me/twhelp/corev3/internal/bun/bunmodel" "gitea.dwysokinski.me/twhelp/corev3/internal/bun/bunmodel"
"gitea.dwysokinski.me/twhelp/corev3/internal/domain" "gitea.dwysokinski.me/twhelp/corev3/internal/domain"
@ -108,6 +109,19 @@ func (repo *EnnoblementBunRepository) ListWithRelations(
return domain.NewListEnnoblementsWithRelationsResult(separateListResultAndNext(converted, params.Limit())) return domain.NewListEnnoblementsWithRelationsResult(separateListResultAndNext(converted, params.Limit()))
} }
func (repo *EnnoblementBunRepository) Delete(ctx context.Context, serverKey string, createdAtLTE time.Time) error {
if _, err := repo.db.NewDelete().
Model(&bunmodel.Ennoblement{}).
Where("server_key = ?", serverKey).
Where("created_at <= ?", createdAtLTE).
Returning("NULL").
Exec(ctx); err != nil {
return fmt.Errorf("couldn't delete ennoblements: %w", err)
}
return nil
}
type listEnnoblementsParamsApplier struct { type listEnnoblementsParamsApplier struct {
params domain.ListEnnoblementsParams params domain.ListEnnoblementsParams
} }

View File

@ -107,6 +107,19 @@ func (repo *PlayerSnapshotBunRepository) ListWithRelations(
return domain.NewListPlayerSnapshotsWithRelationsResult(separateListResultAndNext(converted, params.Limit())) return domain.NewListPlayerSnapshotsWithRelationsResult(separateListResultAndNext(converted, params.Limit()))
} }
func (repo *PlayerSnapshotBunRepository) Delete(ctx context.Context, serverKey string, dateLTE time.Time) error {
if _, err := repo.db.NewDelete().
Model(&bunmodel.PlayerSnapshot{}).
Where("server_key = ?", serverKey).
Where("date <= ?", dateLTE).
Returning("NULL").
Exec(ctx); err != nil {
return fmt.Errorf("couldn't delete player snapshots: %w", err)
}
return nil
}
type listPlayerSnapshotsParamsApplier struct { type listPlayerSnapshotsParamsApplier struct {
params domain.ListPlayerSnapshotsParams params domain.ListPlayerSnapshotsParams
} }

View File

@ -103,6 +103,19 @@ func (repo *TribeSnapshotBunRepository) ListWithRelations(
return domain.NewListTribeSnapshotsWithRelationsResult(separateListResultAndNext(converted, params.Limit())) return domain.NewListTribeSnapshotsWithRelationsResult(separateListResultAndNext(converted, params.Limit()))
} }
func (repo *TribeSnapshotBunRepository) Delete(ctx context.Context, serverKey string, dateLTE time.Time) error {
if _, err := repo.db.NewDelete().
Model(&bunmodel.TribeSnapshot{}).
Where("server_key = ?", serverKey).
Where("date <= ?", dateLTE).
Returning("NULL").
Exec(ctx); err != nil {
return fmt.Errorf("couldn't delete tribe snapshots: %w", err)
}
return nil
}
type listTribeSnapshotsParamsApplier struct { type listTribeSnapshotsParamsApplier struct {
params domain.ListTribeSnapshotsParams params domain.ListTribeSnapshotsParams
} }

View File

@ -138,7 +138,7 @@ func testEnnoblementRepository(t *testing.T, newRepos func(t *testing.T) reposit
assertResult: func(t *testing.T, _ domain.ListEnnoblementsParams, res domain.ListEnnoblementsResult) { assertResult: func(t *testing.T, _ domain.ListEnnoblementsParams, res domain.ListEnnoblementsResult) {
t.Helper() t.Helper()
ennoblements := res.Ennoblements() ennoblements := res.Ennoblements()
assert.NotEmpty(t, len(ennoblements)) assert.NotEmpty(t, ennoblements)
assert.True(t, slices.IsSortedFunc(ennoblements, func(a, b domain.Ennoblement) int { assert.True(t, slices.IsSortedFunc(ennoblements, func(a, b domain.Ennoblement) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -165,7 +165,7 @@ func testEnnoblementRepository(t *testing.T, newRepos func(t *testing.T) reposit
assertResult: func(t *testing.T, _ domain.ListEnnoblementsParams, res domain.ListEnnoblementsResult) { assertResult: func(t *testing.T, _ domain.ListEnnoblementsParams, res domain.ListEnnoblementsResult) {
t.Helper() t.Helper()
ennoblements := res.Ennoblements() ennoblements := res.Ennoblements()
assert.NotEmpty(t, len(ennoblements)) assert.NotEmpty(t, ennoblements)
assert.True(t, slices.IsSortedFunc(ennoblements, func(a, b domain.Ennoblement) int { assert.True(t, slices.IsSortedFunc(ennoblements, func(a, b domain.Ennoblement) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey())*-1, cmp.Compare(a.ServerKey(), b.ServerKey())*-1,
@ -188,7 +188,7 @@ func testEnnoblementRepository(t *testing.T, newRepos func(t *testing.T) reposit
assertResult: func(t *testing.T, _ domain.ListEnnoblementsParams, res domain.ListEnnoblementsResult) { assertResult: func(t *testing.T, _ domain.ListEnnoblementsParams, res domain.ListEnnoblementsResult) {
t.Helper() t.Helper()
ennoblements := res.Ennoblements() ennoblements := res.Ennoblements()
assert.NotEmpty(t, len(ennoblements)) assert.NotEmpty(t, ennoblements)
assert.True(t, slices.IsSortedFunc(ennoblements, func(a, b domain.Ennoblement) int { assert.True(t, slices.IsSortedFunc(ennoblements, func(a, b domain.Ennoblement) int {
return cmp.Compare(a.ID(), b.ID()) return cmp.Compare(a.ID(), b.ID())
})) }))
@ -207,7 +207,7 @@ func testEnnoblementRepository(t *testing.T, newRepos func(t *testing.T) reposit
assertResult: func(t *testing.T, _ domain.ListEnnoblementsParams, res domain.ListEnnoblementsResult) { assertResult: func(t *testing.T, _ domain.ListEnnoblementsParams, res domain.ListEnnoblementsResult) {
t.Helper() t.Helper()
ennoblements := res.Ennoblements() ennoblements := res.Ennoblements()
assert.NotEmpty(t, len(ennoblements)) assert.NotEmpty(t, ennoblements)
assert.True(t, slices.IsSortedFunc(ennoblements, func(a, b domain.Ennoblement) int { assert.True(t, slices.IsSortedFunc(ennoblements, func(a, b domain.Ennoblement) int {
return cmp.Compare(a.ID(), b.ID()) * -1 return cmp.Compare(a.ID(), b.ID()) * -1
})) }))
@ -483,7 +483,7 @@ func testEnnoblementRepository(t *testing.T, newRepos func(t *testing.T) reposit
serverKeys := params.ServerKeys() serverKeys := params.ServerKeys()
ennoblements := res.Ennoblements() ennoblements := res.Ennoblements()
assert.NotEmpty(t, len(ennoblements)) assert.NotEmpty(t, ennoblements)
for _, e := range ennoblements { for _, e := range ennoblements {
assert.GreaterOrEqual(t, e.ID(), params.Cursor().ID()) assert.GreaterOrEqual(t, e.ID(), params.Cursor().ID())
assert.True(t, slices.Contains(serverKeys, e.ServerKey())) assert.True(t, slices.Contains(serverKeys, e.ServerKey()))
@ -517,7 +517,7 @@ func testEnnoblementRepository(t *testing.T, newRepos func(t *testing.T) reposit
assertResult: func(t *testing.T, params domain.ListEnnoblementsParams, res domain.ListEnnoblementsResult) { assertResult: func(t *testing.T, params domain.ListEnnoblementsParams, res domain.ListEnnoblementsResult) {
t.Helper() t.Helper()
ennoblements := res.Ennoblements() ennoblements := res.Ennoblements()
assert.NotEmpty(t, len(ennoblements)) assert.NotEmpty(t, ennoblements)
assert.True(t, slices.IsSortedFunc(ennoblements, func(a, b domain.Ennoblement) int { assert.True(t, slices.IsSortedFunc(ennoblements, func(a, b domain.Ennoblement) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -554,7 +554,7 @@ func testEnnoblementRepository(t *testing.T, newRepos func(t *testing.T) reposit
assertResult: func(t *testing.T, params domain.ListEnnoblementsParams, res domain.ListEnnoblementsResult) { assertResult: func(t *testing.T, params domain.ListEnnoblementsParams, res domain.ListEnnoblementsResult) {
t.Helper() t.Helper()
ennoblements := res.Ennoblements() ennoblements := res.Ennoblements()
assert.NotEmpty(t, len(ennoblements)) assert.NotEmpty(t, ennoblements)
assert.True(t, slices.IsSortedFunc(ennoblements, func(a, b domain.Ennoblement) int { assert.True(t, slices.IsSortedFunc(ennoblements, func(a, b domain.Ennoblement) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -619,4 +619,38 @@ func testEnnoblementRepository(t *testing.T, newRepos func(t *testing.T) reposit
}) })
} }
}) })
t.Run("Delete", func(t *testing.T) {
t.Parallel()
t.Run("OK", func(t *testing.T) {
t.Parallel()
repos := newRepos(t)
params := domain.NewListEnnoblementsParams()
require.NoError(t, params.SetSort([]domain.EnnoblementSort{
domain.EnnoblementSortServerKeyASC,
domain.EnnoblementSortCreatedAtASC,
domain.EnnoblementSortIDASC,
}))
res, err := repos.ennoblement.List(ctx, params)
require.NoError(t, err)
require.NotEmpty(t, res.Ennoblements())
randEnnoblement := res.Ennoblements()[0]
require.NoError(t, repos.ennoblement.Delete(ctx, randEnnoblement.ServerKey(), randEnnoblement.CreatedAt()))
require.NoError(t, params.SetServerKeys([]string{randEnnoblement.ServerKey()}))
res, err = repos.ennoblement.List(ctx, params)
require.NoError(t, err)
assert.NotEmpty(t, res.Ennoblements())
for _, s := range res.Ennoblements() {
assert.True(t, s.CreatedAt().After(randEnnoblement.CreatedAt()))
}
})
})
} }

View File

@ -144,7 +144,7 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
) { ) {
t.Helper() t.Helper()
playerSnapshots := res.PlayerSnapshots() playerSnapshots := res.PlayerSnapshots()
assert.NotEmpty(t, len(playerSnapshots)) assert.NotEmpty(t, 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(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -174,7 +174,7 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
) { ) {
t.Helper() t.Helper()
playerSnapshots := res.PlayerSnapshots() playerSnapshots := res.PlayerSnapshots()
assert.NotEmpty(t, len(playerSnapshots)) assert.NotEmpty(t, 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(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -200,7 +200,7 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
) { ) {
t.Helper() t.Helper()
playerSnapshots := res.PlayerSnapshots() playerSnapshots := res.PlayerSnapshots()
assert.NotEmpty(t, len(playerSnapshots)) assert.NotEmpty(t, 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())
})) }))
@ -223,7 +223,7 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
) { ) {
t.Helper() t.Helper()
playerSnapshots := res.PlayerSnapshots() playerSnapshots := res.PlayerSnapshots()
assert.NotEmpty(t, len(playerSnapshots)) assert.NotEmpty(t, 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
})) }))
@ -321,7 +321,7 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
serverKeys := params.ServerKeys() serverKeys := params.ServerKeys()
playerSnapshots := res.PlayerSnapshots() playerSnapshots := res.PlayerSnapshots()
assert.NotEmpty(t, len(playerSnapshots)) assert.NotEmpty(t, playerSnapshots)
for _, ps := range playerSnapshots { for _, ps := range playerSnapshots {
assert.GreaterOrEqual(t, ps.ID(), params.Cursor().ID()) assert.GreaterOrEqual(t, ps.ID(), params.Cursor().ID())
assert.True(t, slices.Contains(serverKeys, ps.ServerKey())) assert.True(t, slices.Contains(serverKeys, ps.ServerKey()))
@ -355,7 +355,7 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
assertResult: func(t *testing.T, params domain.ListPlayerSnapshotsParams, res domain.ListPlayerSnapshotsResult) { assertResult: func(t *testing.T, params domain.ListPlayerSnapshotsParams, res domain.ListPlayerSnapshotsResult) {
t.Helper() t.Helper()
playerSnapshots := res.PlayerSnapshots() playerSnapshots := res.PlayerSnapshots()
assert.NotEmpty(t, len(playerSnapshots)) assert.NotEmpty(t, 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(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -392,7 +392,7 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
assertResult: func(t *testing.T, params domain.ListPlayerSnapshotsParams, res domain.ListPlayerSnapshotsResult) { assertResult: func(t *testing.T, params domain.ListPlayerSnapshotsParams, res domain.ListPlayerSnapshotsResult) {
t.Helper() t.Helper()
playerSnapshots := res.PlayerSnapshots() playerSnapshots := res.PlayerSnapshots()
assert.NotEmpty(t, len(playerSnapshots)) assert.NotEmpty(t, 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(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -456,4 +456,38 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
}) })
} }
}) })
t.Run("Delete", func(t *testing.T) {
t.Parallel()
t.Run("OK", func(t *testing.T) {
t.Parallel()
repos := newRepos(t)
params := domain.NewListPlayerSnapshotsParams()
require.NoError(t, params.SetSort([]domain.PlayerSnapshotSort{
domain.PlayerSnapshotSortServerKeyASC,
domain.PlayerSnapshotSortDateASC,
domain.PlayerSnapshotSortIDASC,
}))
res, err := repos.playerSnapshot.List(ctx, params)
require.NoError(t, err)
require.NotEmpty(t, res.PlayerSnapshots())
randSnapshot := res.PlayerSnapshots()[0]
require.NoError(t, repos.playerSnapshot.Delete(ctx, randSnapshot.ServerKey(), randSnapshot.Date()))
require.NoError(t, params.SetServerKeys([]string{randSnapshot.ServerKey()}))
res, err = repos.playerSnapshot.List(ctx, params)
require.NoError(t, err)
assert.NotEmpty(t, res.PlayerSnapshots())
for _, ps := range res.PlayerSnapshots() {
assert.True(t, ps.Date().After(randSnapshot.Date()))
}
})
})
} }

View File

@ -120,7 +120,7 @@ func testPlayerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) { assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) {
t.Helper() t.Helper()
players := res.Players() players := res.Players()
assert.NotEmpty(t, len(players)) assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int { assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -142,7 +142,7 @@ func testPlayerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) { assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) {
t.Helper() t.Helper()
players := res.Players() players := res.Players()
assert.NotEmpty(t, len(players)) assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int { assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -166,7 +166,7 @@ func testPlayerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) { assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) {
t.Helper() t.Helper()
players := res.Players() players := res.Players()
assert.NotEmpty(t, len(players)) assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int { assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.OD().ScoreAtt(), b.OD().ScoreAtt())*-1, cmp.Compare(a.OD().ScoreAtt(), b.OD().ScoreAtt())*-1,
@ -191,7 +191,7 @@ func testPlayerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) { assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) {
t.Helper() t.Helper()
players := res.Players() players := res.Players()
assert.NotEmpty(t, len(players)) assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int { assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.OD().ScoreDef(), b.OD().ScoreDef())*-1, cmp.Compare(a.OD().ScoreDef(), b.OD().ScoreDef())*-1,
@ -216,7 +216,7 @@ func testPlayerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) { assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) {
t.Helper() t.Helper()
players := res.Players() players := res.Players()
assert.NotEmpty(t, len(players)) assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int { assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.OD().ScoreSup(), b.OD().ScoreSup())*-1, cmp.Compare(a.OD().ScoreSup(), b.OD().ScoreSup())*-1,
@ -241,7 +241,7 @@ func testPlayerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) { assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) {
t.Helper() t.Helper()
players := res.Players() players := res.Players()
assert.NotEmpty(t, len(players)) assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int { assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.OD().ScoreTotal(), b.OD().ScoreTotal())*-1, cmp.Compare(a.OD().ScoreTotal(), b.OD().ScoreTotal())*-1,
@ -266,7 +266,7 @@ func testPlayerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) { assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) {
t.Helper() t.Helper()
players := res.Players() players := res.Players()
assert.NotEmpty(t, len(players)) assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int { assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.Points(), b.Points())*-1, cmp.Compare(a.Points(), b.Points())*-1,
@ -291,7 +291,7 @@ func testPlayerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) { assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) {
t.Helper() t.Helper()
players := res.Players() players := res.Players()
assert.NotEmpty(t, len(players)) assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int { assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or( return cmp.Or(
a.DeletedAt().Compare(b.DeletedAt()), a.DeletedAt().Compare(b.DeletedAt()),
@ -316,7 +316,7 @@ func testPlayerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) { assertResult: func(t *testing.T, _ domain.ListPlayersParams, res domain.ListPlayersResult) {
t.Helper() t.Helper()
players := res.Players() players := res.Players()
assert.NotEmpty(t, len(players)) assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int { assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or( return cmp.Or(
a.DeletedAt().Compare(b.DeletedAt())*-1, a.DeletedAt().Compare(b.DeletedAt())*-1,
@ -487,7 +487,7 @@ func testPlayerRepository(t *testing.T, newRepos func(t *testing.T) repositories
serverKeys := params.ServerKeys() serverKeys := params.ServerKeys()
players := res.Players() players := res.Players()
assert.NotEmpty(t, len(players)) assert.NotEmpty(t, players)
for _, p := range players { for _, p := range players {
assert.GreaterOrEqual(t, p.ID(), params.Cursor().ID()) assert.GreaterOrEqual(t, p.ID(), params.Cursor().ID())
assert.True(t, slices.Contains(serverKeys, p.ServerKey())) assert.True(t, slices.Contains(serverKeys, p.ServerKey()))
@ -521,7 +521,7 @@ func testPlayerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, params domain.ListPlayersParams, res domain.ListPlayersResult) { assertResult: func(t *testing.T, params domain.ListPlayersParams, res domain.ListPlayersResult) {
t.Helper() t.Helper()
players := res.Players() players := res.Players()
assert.NotEmpty(t, len(players)) assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int { assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -558,7 +558,7 @@ func testPlayerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, params domain.ListPlayersParams, res domain.ListPlayersResult) { assertResult: func(t *testing.T, params domain.ListPlayersParams, res domain.ListPlayersResult) {
t.Helper() t.Helper()
players := res.Players() players := res.Players()
assert.NotEmpty(t, len(players)) assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int { assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),

View File

@ -125,7 +125,7 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, _ domain.ListServersParams, res domain.ListServersResult) { assertResult: func(t *testing.T, _ domain.ListServersParams, res domain.ListServersResult) {
t.Helper() t.Helper()
servers := res.Servers() servers := res.Servers()
assert.NotEmpty(t, len(servers)) assert.NotEmpty(t, 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())
})) }))
@ -144,7 +144,7 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, _ domain.ListServersParams, res domain.ListServersResult) { assertResult: func(t *testing.T, _ domain.ListServersParams, res domain.ListServersResult) {
t.Helper() t.Helper()
servers := res.Servers() servers := res.Servers()
assert.NotEmpty(t, len(servers)) assert.NotEmpty(t, 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() {
return 1 return 1
@ -169,7 +169,7 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, _ domain.ListServersParams, res domain.ListServersResult) { assertResult: func(t *testing.T, _ domain.ListServersParams, res domain.ListServersResult) {
t.Helper() t.Helper()
servers := res.Servers() servers := res.Servers()
assert.NotEmpty(t, len(servers)) assert.NotEmpty(t, 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() {
return -1 return -1
@ -255,7 +255,7 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, _ domain.ListServersParams, res domain.ListServersResult) { assertResult: func(t *testing.T, _ domain.ListServersParams, res domain.ListServersResult) {
t.Helper() t.Helper()
servers := res.Servers() servers := res.Servers()
assert.NotEmpty(t, len(servers)) assert.NotEmpty(t, servers)
for _, s := range servers { for _, s := range servers {
assert.True(t, s.Special(), s.Key()) assert.True(t, s.Special(), s.Key())
} }
@ -275,7 +275,7 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, _ domain.ListServersParams, res domain.ListServersResult) { assertResult: func(t *testing.T, _ domain.ListServersParams, res domain.ListServersResult) {
t.Helper() t.Helper()
servers := res.Servers() servers := res.Servers()
assert.NotEmpty(t, len(servers)) assert.NotEmpty(t, servers)
for _, s := range servers { for _, s := range servers {
assert.False(t, s.Open(), s.Key()) assert.False(t, s.Open(), s.Key())
} }
@ -295,7 +295,7 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, _ domain.ListServersParams, res domain.ListServersResult) { assertResult: func(t *testing.T, _ domain.ListServersParams, res domain.ListServersResult) {
t.Helper() t.Helper()
servers := res.Servers() servers := res.Servers()
assert.NotEmpty(t, len(servers)) assert.NotEmpty(t, servers)
for _, s := range servers { for _, s := range servers {
assert.True(t, s.PlayerSnapshotsCreatedAt().Before(snapshotsCreatedAtLT)) assert.True(t, s.PlayerSnapshotsCreatedAt().Before(snapshotsCreatedAtLT))
} }
@ -315,7 +315,7 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, _ domain.ListServersParams, res domain.ListServersResult) { assertResult: func(t *testing.T, _ domain.ListServersParams, res domain.ListServersResult) {
t.Helper() t.Helper()
servers := res.Servers() servers := res.Servers()
assert.NotEmpty(t, len(servers)) assert.NotEmpty(t, servers)
for _, s := range servers { for _, s := range servers {
assert.True(t, s.TribeSnapshotsCreatedAt().Before(snapshotsCreatedAtLT)) assert.True(t, s.TribeSnapshotsCreatedAt().Before(snapshotsCreatedAtLT))
} }
@ -342,7 +342,7 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult) { assertResult: func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult) {
t.Helper() t.Helper()
servers := res.Servers() servers := res.Servers()
assert.NotEmpty(t, len(servers)) assert.NotEmpty(t, 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())
})) }))
@ -372,7 +372,7 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult) { assertResult: func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult) {
t.Helper() t.Helper()
servers := res.Servers() servers := res.Servers()
assert.NotEmpty(t, len(servers)) assert.NotEmpty(t, 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() {
return 1 return 1
@ -410,7 +410,7 @@ func testServerRepository(t *testing.T, newRepos func(t *testing.T) repositories
assertResult: func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult) { assertResult: func(t *testing.T, params domain.ListServersParams, res domain.ListServersResult) {
t.Helper() t.Helper()
servers := res.Servers() servers := res.Servers()
assert.NotEmpty(t, len(servers)) assert.NotEmpty(t, 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() {
return -1 return -1

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"os" "os"
"testing" "testing"
"time"
"gitea.dwysokinski.me/twhelp/corev3/internal/adapter" "gitea.dwysokinski.me/twhelp/corev3/internal/adapter"
"gitea.dwysokinski.me/twhelp/corev3/internal/bun/buntest" "gitea.dwysokinski.me/twhelp/corev3/internal/bun/buntest"
@ -52,6 +53,7 @@ type ennoblementRepository interface {
ctx context.Context, ctx context.Context,
params domain.ListEnnoblementsParams, params domain.ListEnnoblementsParams,
) (domain.ListEnnoblementsWithRelationsResult, error) ) (domain.ListEnnoblementsWithRelationsResult, error)
Delete(ctx context.Context, serverKey string, createdAtLTE time.Time) error
} }
type tribeChangeRepository interface { type tribeChangeRepository interface {
@ -70,6 +72,7 @@ type tribeSnapshotRepository interface {
ctx context.Context, ctx context.Context,
params domain.ListTribeSnapshotsParams, params domain.ListTribeSnapshotsParams,
) (domain.ListTribeSnapshotsWithRelationsResult, error) ) (domain.ListTribeSnapshotsWithRelationsResult, error)
Delete(ctx context.Context, serverKey string, dateLTE time.Time) error
} }
type playerSnapshotRepository interface { type playerSnapshotRepository interface {
@ -79,6 +82,7 @@ type playerSnapshotRepository interface {
ctx context.Context, ctx context.Context,
params domain.ListPlayerSnapshotsParams, params domain.ListPlayerSnapshotsParams,
) (domain.ListPlayerSnapshotsWithRelationsResult, error) ) (domain.ListPlayerSnapshotsWithRelationsResult, error)
Delete(ctx context.Context, serverKey string, dateLTE time.Time) error
} }
type repositories struct { type repositories struct {

View File

@ -156,7 +156,7 @@ func testTribeChangeRepository(t *testing.T, newRepos func(t *testing.T) reposit
assertResult: func(t *testing.T, _ domain.ListTribeChangesParams, res domain.ListTribeChangesResult) { assertResult: func(t *testing.T, _ domain.ListTribeChangesParams, res domain.ListTribeChangesResult) {
t.Helper() t.Helper()
tribeChanges := res.TribeChanges() tribeChanges := res.TribeChanges()
assert.NotEmpty(t, len(tribeChanges)) assert.NotEmpty(t, tribeChanges)
assert.True(t, slices.IsSortedFunc(tribeChanges, func(a, b domain.TribeChange) int { assert.True(t, slices.IsSortedFunc(tribeChanges, func(a, b domain.TribeChange) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -182,7 +182,7 @@ func testTribeChangeRepository(t *testing.T, newRepos func(t *testing.T) reposit
assertResult: func(t *testing.T, _ domain.ListTribeChangesParams, res domain.ListTribeChangesResult) { assertResult: func(t *testing.T, _ domain.ListTribeChangesParams, res domain.ListTribeChangesResult) {
t.Helper() t.Helper()
tribeChanges := res.TribeChanges() tribeChanges := res.TribeChanges()
assert.NotEmpty(t, len(tribeChanges)) assert.NotEmpty(t, tribeChanges)
assert.True(t, slices.IsSortedFunc(tribeChanges, func(a, b domain.TribeChange) int { assert.True(t, slices.IsSortedFunc(tribeChanges, func(a, b domain.TribeChange) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -204,7 +204,7 @@ func testTribeChangeRepository(t *testing.T, newRepos func(t *testing.T) reposit
assertResult: func(t *testing.T, _ domain.ListTribeChangesParams, res domain.ListTribeChangesResult) { assertResult: func(t *testing.T, _ domain.ListTribeChangesParams, res domain.ListTribeChangesResult) {
t.Helper() t.Helper()
tribeChanges := res.TribeChanges() tribeChanges := res.TribeChanges()
assert.NotEmpty(t, len(tribeChanges)) assert.NotEmpty(t, tribeChanges)
assert.True(t, slices.IsSortedFunc(tribeChanges, func(a, b domain.TribeChange) int { assert.True(t, slices.IsSortedFunc(tribeChanges, func(a, b domain.TribeChange) int {
return cmp.Compare(a.ID(), b.ID()) return cmp.Compare(a.ID(), b.ID())
})) }))
@ -223,7 +223,7 @@ func testTribeChangeRepository(t *testing.T, newRepos func(t *testing.T) reposit
assertResult: func(t *testing.T, _ domain.ListTribeChangesParams, res domain.ListTribeChangesResult) { assertResult: func(t *testing.T, _ domain.ListTribeChangesParams, res domain.ListTribeChangesResult) {
t.Helper() t.Helper()
tribeChanges := res.TribeChanges() tribeChanges := res.TribeChanges()
assert.NotEmpty(t, len(tribeChanges)) assert.NotEmpty(t, tribeChanges)
assert.True(t, slices.IsSortedFunc(tribeChanges, func(a, b domain.TribeChange) int { assert.True(t, slices.IsSortedFunc(tribeChanges, func(a, b domain.TribeChange) int {
return cmp.Compare(a.ID(), b.ID()) * -1 return cmp.Compare(a.ID(), b.ID()) * -1
})) }))

View File

@ -141,7 +141,7 @@ func testTribeSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repos
) { ) {
t.Helper() t.Helper()
tribeSnapshots := res.TribeSnapshots() tribeSnapshots := res.TribeSnapshots()
assert.NotEmpty(t, len(tribeSnapshots)) assert.NotEmpty(t, tribeSnapshots)
assert.True(t, slices.IsSortedFunc(tribeSnapshots, func(a, b domain.TribeSnapshot) int { assert.True(t, slices.IsSortedFunc(tribeSnapshots, func(a, b domain.TribeSnapshot) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -172,7 +172,7 @@ func testTribeSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repos
) { ) {
t.Helper() t.Helper()
tribeSnapshots := res.TribeSnapshots() tribeSnapshots := res.TribeSnapshots()
assert.NotEmpty(t, len(tribeSnapshots)) assert.NotEmpty(t, tribeSnapshots)
assert.True(t, slices.IsSortedFunc(tribeSnapshots, func(a, b domain.TribeSnapshot) int { assert.True(t, slices.IsSortedFunc(tribeSnapshots, func(a, b domain.TribeSnapshot) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -199,7 +199,7 @@ func testTribeSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repos
) { ) {
t.Helper() t.Helper()
tribeSnapshots := res.TribeSnapshots() tribeSnapshots := res.TribeSnapshots()
assert.NotEmpty(t, len(tribeSnapshots)) assert.NotEmpty(t, tribeSnapshots)
assert.True(t, slices.IsSortedFunc(tribeSnapshots, func(a, b domain.TribeSnapshot) int { assert.True(t, slices.IsSortedFunc(tribeSnapshots, func(a, b domain.TribeSnapshot) int {
return cmp.Compare(a.ID(), b.ID()) return cmp.Compare(a.ID(), b.ID())
})) }))
@ -222,7 +222,7 @@ func testTribeSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repos
) { ) {
t.Helper() t.Helper()
tribeSnapshots := res.TribeSnapshots() tribeSnapshots := res.TribeSnapshots()
assert.NotEmpty(t, len(tribeSnapshots)) assert.NotEmpty(t, tribeSnapshots)
assert.True(t, slices.IsSortedFunc(tribeSnapshots, func(a, b domain.TribeSnapshot) int { assert.True(t, slices.IsSortedFunc(tribeSnapshots, func(a, b domain.TribeSnapshot) int {
return cmp.Compare(a.ID(), b.ID()) * -1 return cmp.Compare(a.ID(), b.ID()) * -1
})) }))
@ -320,7 +320,7 @@ func testTribeSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repos
serverKeys := params.ServerKeys() serverKeys := params.ServerKeys()
tribeSnapshots := res.TribeSnapshots() tribeSnapshots := res.TribeSnapshots()
assert.NotEmpty(t, len(tribeSnapshots)) assert.NotEmpty(t, tribeSnapshots)
for _, ts := range tribeSnapshots { for _, ts := range tribeSnapshots {
assert.GreaterOrEqual(t, ts.ID(), params.Cursor().ID()) assert.GreaterOrEqual(t, ts.ID(), params.Cursor().ID())
assert.True(t, slices.Contains(serverKeys, ts.ServerKey())) assert.True(t, slices.Contains(serverKeys, ts.ServerKey()))
@ -354,7 +354,7 @@ func testTribeSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repos
assertResult: func(t *testing.T, params domain.ListTribeSnapshotsParams, res domain.ListTribeSnapshotsResult) { assertResult: func(t *testing.T, params domain.ListTribeSnapshotsParams, res domain.ListTribeSnapshotsResult) {
t.Helper() t.Helper()
tribeSnapshots := res.TribeSnapshots() tribeSnapshots := res.TribeSnapshots()
assert.NotEmpty(t, len(tribeSnapshots)) assert.NotEmpty(t, tribeSnapshots)
assert.True(t, slices.IsSortedFunc(tribeSnapshots, func(a, b domain.TribeSnapshot) int { assert.True(t, slices.IsSortedFunc(tribeSnapshots, func(a, b domain.TribeSnapshot) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -391,7 +391,7 @@ func testTribeSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repos
assertResult: func(t *testing.T, params domain.ListTribeSnapshotsParams, res domain.ListTribeSnapshotsResult) { assertResult: func(t *testing.T, params domain.ListTribeSnapshotsParams, res domain.ListTribeSnapshotsResult) {
t.Helper() t.Helper()
tribeSnapshots := res.TribeSnapshots() tribeSnapshots := res.TribeSnapshots()
assert.NotEmpty(t, len(tribeSnapshots)) assert.NotEmpty(t, tribeSnapshots)
assert.True(t, slices.IsSortedFunc(tribeSnapshots, func(a, b domain.TribeSnapshot) int { assert.True(t, slices.IsSortedFunc(tribeSnapshots, func(a, b domain.TribeSnapshot) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -453,4 +453,38 @@ func testTribeSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repos
}) })
} }
}) })
t.Run("Delete", func(t *testing.T) {
t.Parallel()
t.Run("OK", func(t *testing.T) {
t.Parallel()
repos := newRepos(t)
params := domain.NewListTribeSnapshotsParams()
require.NoError(t, params.SetSort([]domain.TribeSnapshotSort{
domain.TribeSnapshotSortServerKeyASC,
domain.TribeSnapshotSortDateASC,
domain.TribeSnapshotSortIDASC,
}))
res, err := repos.tribeSnapshot.List(ctx, params)
require.NoError(t, err)
require.NotEmpty(t, res.TribeSnapshots())
randSnapshot := res.TribeSnapshots()[0]
require.NoError(t, repos.tribeSnapshot.Delete(ctx, randSnapshot.ServerKey(), randSnapshot.Date()))
require.NoError(t, params.SetServerKeys([]string{randSnapshot.ServerKey()}))
res, err = repos.tribeSnapshot.List(ctx, params)
require.NoError(t, err)
assert.NotEmpty(t, res.TribeSnapshots())
for _, ts := range res.TribeSnapshots() {
assert.True(t, ts.Date().After(randSnapshot.Date()))
}
})
})
} }

View File

@ -183,7 +183,7 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
assertResult: func(t *testing.T, _ domain.ListTribesParams, res domain.ListTribesResult) { assertResult: func(t *testing.T, _ domain.ListTribesParams, res domain.ListTribesResult) {
t.Helper() t.Helper()
tribes := res.Tribes() tribes := res.Tribes()
assert.NotEmpty(t, len(tribes)) assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int { assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -205,7 +205,7 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
assertResult: func(t *testing.T, _ domain.ListTribesParams, res domain.ListTribesResult) { assertResult: func(t *testing.T, _ domain.ListTribesParams, res domain.ListTribesResult) {
t.Helper() t.Helper()
tribes := res.Tribes() tribes := res.Tribes()
assert.NotEmpty(t, len(tribes)) assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int { assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -229,7 +229,7 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
assertResult: func(t *testing.T, _ domain.ListTribesParams, res domain.ListTribesResult) { assertResult: func(t *testing.T, _ domain.ListTribesParams, res domain.ListTribesResult) {
t.Helper() t.Helper()
tribes := res.Tribes() tribes := res.Tribes()
assert.NotEmpty(t, len(tribes)) assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int { assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.OD().ScoreAtt(), b.OD().ScoreAtt())*-1, cmp.Compare(a.OD().ScoreAtt(), b.OD().ScoreAtt())*-1,
@ -254,7 +254,7 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
assertResult: func(t *testing.T, _ domain.ListTribesParams, res domain.ListTribesResult) { assertResult: func(t *testing.T, _ domain.ListTribesParams, res domain.ListTribesResult) {
t.Helper() t.Helper()
tribes := res.Tribes() tribes := res.Tribes()
assert.NotEmpty(t, len(tribes)) assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int { assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.OD().ScoreDef(), b.OD().ScoreDef())*-1, cmp.Compare(a.OD().ScoreDef(), b.OD().ScoreDef())*-1,
@ -279,7 +279,7 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
assertResult: func(t *testing.T, _ domain.ListTribesParams, res domain.ListTribesResult) { assertResult: func(t *testing.T, _ domain.ListTribesParams, res domain.ListTribesResult) {
t.Helper() t.Helper()
tribes := res.Tribes() tribes := res.Tribes()
assert.NotEmpty(t, len(tribes)) assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int { assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.OD().ScoreTotal(), b.OD().ScoreTotal())*-1, cmp.Compare(a.OD().ScoreTotal(), b.OD().ScoreTotal())*-1,
@ -304,7 +304,7 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
assertResult: func(t *testing.T, _ domain.ListTribesParams, res domain.ListTribesResult) { assertResult: func(t *testing.T, _ domain.ListTribesParams, res domain.ListTribesResult) {
t.Helper() t.Helper()
tribes := res.Tribes() tribes := res.Tribes()
assert.NotEmpty(t, len(tribes)) assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int { assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.Points(), b.Points())*-1, cmp.Compare(a.Points(), b.Points())*-1,
@ -329,7 +329,7 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
assertResult: func(t *testing.T, _ domain.ListTribesParams, res domain.ListTribesResult) { assertResult: func(t *testing.T, _ domain.ListTribesParams, res domain.ListTribesResult) {
t.Helper() t.Helper()
tribes := res.Tribes() tribes := res.Tribes()
assert.NotEmpty(t, len(tribes)) assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int { assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.Dominance(), b.Dominance()), cmp.Compare(a.Dominance(), b.Dominance()),
@ -354,7 +354,7 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
assertResult: func(t *testing.T, _ domain.ListTribesParams, res domain.ListTribesResult) { assertResult: func(t *testing.T, _ domain.ListTribesParams, res domain.ListTribesResult) {
t.Helper() t.Helper()
tribes := res.Tribes() tribes := res.Tribes()
assert.NotEmpty(t, len(tribes)) assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int { assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or( return cmp.Or(
a.DeletedAt().Compare(b.DeletedAt()), a.DeletedAt().Compare(b.DeletedAt()),
@ -379,7 +379,7 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
assertResult: func(t *testing.T, _ domain.ListTribesParams, res domain.ListTribesResult) { assertResult: func(t *testing.T, _ domain.ListTribesParams, res domain.ListTribesResult) {
t.Helper() t.Helper()
tribes := res.Tribes() tribes := res.Tribes()
assert.NotEmpty(t, len(tribes)) assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int { assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or( return cmp.Or(
a.DeletedAt().Compare(b.DeletedAt())*-1, a.DeletedAt().Compare(b.DeletedAt())*-1,
@ -516,7 +516,7 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
serverKeys := params.ServerKeys() serverKeys := params.ServerKeys()
tribes := res.Tribes() tribes := res.Tribes()
assert.NotEmpty(t, len(tribes)) assert.NotEmpty(t, tribes)
for _, tr := range res.Tribes() { for _, tr := range res.Tribes() {
assert.GreaterOrEqual(t, tr.ID(), params.Cursor().ID()) assert.GreaterOrEqual(t, tr.ID(), params.Cursor().ID())
assert.True(t, slices.Contains(serverKeys, tr.ServerKey())) assert.True(t, slices.Contains(serverKeys, tr.ServerKey()))
@ -550,7 +550,7 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
assertResult: func(t *testing.T, params domain.ListTribesParams, res domain.ListTribesResult) { assertResult: func(t *testing.T, params domain.ListTribesParams, res domain.ListTribesResult) {
t.Helper() t.Helper()
tribes := res.Tribes() tribes := res.Tribes()
assert.NotEmpty(t, len(tribes)) assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int { assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -587,7 +587,7 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
assertResult: func(t *testing.T, params domain.ListTribesParams, res domain.ListTribesResult) { assertResult: func(t *testing.T, params domain.ListTribesParams, res domain.ListTribesResult) {
t.Helper() t.Helper()
tribes := res.Tribes() tribes := res.Tribes()
assert.NotEmpty(t, len(tribes)) assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int { assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()), cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -625,7 +625,7 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
assertResult: func(t *testing.T, params domain.ListTribesParams, res domain.ListTribesResult) { assertResult: func(t *testing.T, params domain.ListTribesParams, res domain.ListTribesResult) {
t.Helper() t.Helper()
tribes := res.Tribes() tribes := res.Tribes()
assert.NotEmpty(t, len(tribes)) assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int { assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.Points(), b.Points())*-1, cmp.Compare(a.Points(), b.Points())*-1,
@ -665,7 +665,7 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
assertResult: func(t *testing.T, params domain.ListTribesParams, res domain.ListTribesResult) { assertResult: func(t *testing.T, params domain.ListTribesParams, res domain.ListTribesResult) {
t.Helper() t.Helper()
tribes := res.Tribes() tribes := res.Tribes()
assert.NotEmpty(t, len(tribes)) assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int { assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or( return cmp.Or(
a.DeletedAt().Compare(b.DeletedAt()), a.DeletedAt().Compare(b.DeletedAt()),

View File

@ -16,6 +16,7 @@ type EnnoblementRepository interface {
ctx context.Context, ctx context.Context,
params domain.ListEnnoblementsParams, params domain.ListEnnoblementsParams,
) (domain.ListEnnoblementsWithRelationsResult, error) ) (domain.ListEnnoblementsWithRelationsResult, error)
Delete(ctx context.Context, serverKey string, createdAtLTE time.Time) error
} }
type EnnoblementService struct { type EnnoblementService struct {
@ -136,3 +137,19 @@ func (svc *EnnoblementService) ListWithRelations(
) (domain.ListEnnoblementsWithRelationsResult, error) { ) (domain.ListEnnoblementsWithRelationsResult, error) {
return svc.repo.ListWithRelations(ctx, params) return svc.repo.ListWithRelations(ctx, params)
} }
func (svc *EnnoblementService) CleanUp(ctx context.Context, payload domain.CleanUpDataCmdPayload) error {
if !payload.CanCleanUpEnnoblements() {
return nil
}
if err := svc.repo.Delete(
ctx,
payload.Server().Key(),
time.Now().Add(-domain.EnnoblementRetentionForClosedServers),
); err != nil {
return fmt.Errorf("%s: %w", payload.Server().Key(), err)
}
return nil
}

View File

@ -3,6 +3,7 @@ package app
import ( import (
"context" "context"
"fmt" "fmt"
"time"
"gitea.dwysokinski.me/twhelp/corev3/internal/domain" "gitea.dwysokinski.me/twhelp/corev3/internal/domain"
) )
@ -15,6 +16,7 @@ type PlayerSnapshotRepository interface {
ctx context.Context, ctx context.Context,
params domain.ListPlayerSnapshotsParams, params domain.ListPlayerSnapshotsParams,
) (domain.ListPlayerSnapshotsWithRelationsResult, error) ) (domain.ListPlayerSnapshotsWithRelationsResult, error)
Delete(ctx context.Context, serverKey string, dateLTE time.Time) error
} }
type PlayerSnapshotService struct { type PlayerSnapshotService struct {
@ -103,3 +105,19 @@ func (svc *PlayerSnapshotService) ListWithRelations(
) (domain.ListPlayerSnapshotsWithRelationsResult, error) { ) (domain.ListPlayerSnapshotsWithRelationsResult, error) {
return svc.repo.ListWithRelations(ctx, params) return svc.repo.ListWithRelations(ctx, params)
} }
func (svc *PlayerSnapshotService) CleanUp(ctx context.Context, payload domain.CleanUpDataCmdPayload) error {
if !payload.CanCleanUpPlayerSnapshots() {
return nil
}
if err := svc.repo.Delete(
ctx,
payload.Server().Key(),
time.Now().Add(-domain.PlayerSnapshotRetentionForClosedServers),
); err != nil {
return fmt.Errorf("%s: %w", payload.Server().Key(), err)
}
return nil
}

View File

@ -3,6 +3,7 @@ package app
import ( import (
"context" "context"
"fmt" "fmt"
"time"
"gitea.dwysokinski.me/twhelp/corev3/internal/domain" "gitea.dwysokinski.me/twhelp/corev3/internal/domain"
) )
@ -15,6 +16,7 @@ type TribeSnapshotRepository interface {
ctx context.Context, ctx context.Context,
params domain.ListTribeSnapshotsParams, params domain.ListTribeSnapshotsParams,
) (domain.ListTribeSnapshotsWithRelationsResult, error) ) (domain.ListTribeSnapshotsWithRelationsResult, error)
Delete(ctx context.Context, serverKey string, dateLTE time.Time) error
} }
type TribeSnapshotService struct { type TribeSnapshotService struct {
@ -103,3 +105,19 @@ func (svc *TribeSnapshotService) ListWithRelations(
) (domain.ListTribeSnapshotsWithRelationsResult, error) { ) (domain.ListTribeSnapshotsWithRelationsResult, error) {
return svc.repo.ListWithRelations(ctx, params) return svc.repo.ListWithRelations(ctx, params)
} }
func (svc *TribeSnapshotService) CleanUp(ctx context.Context, payload domain.CleanUpDataCmdPayload) error {
if !payload.CanCleanUpTribeSnapshots() {
return nil
}
if err := svc.repo.Delete(
ctx,
payload.Server().Key(),
time.Now().Add(-domain.TribeSnapshotRetentionForClosedServers),
); err != nil {
return fmt.Errorf("%s: %w", payload.Server().Key(), err)
}
return nil
}

View File

@ -5,17 +5,17 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
type CleanUpDataCmdPayloadServerConfig struct { type CleanUpDataCmdPayloadConfig struct {
ServerOptions []func(cfg *ServerConfig) ServerOptions []func(cfg *ServerConfig)
} }
func NewCleanUpDataCmdPayloadServer( func NewCleanUpDataCmdPayload(
tb TestingTB, tb TestingTB,
opts ...func(cfg *CleanUpDataCmdPayloadServerConfig), opts ...func(cfg *CleanUpDataCmdPayloadConfig),
) domain.CleanUpDataCmdPayloadServer { ) domain.CleanUpDataCmdPayload {
tb.Helper() tb.Helper()
cfg := &CleanUpDataCmdPayloadServerConfig{} cfg := &CleanUpDataCmdPayloadConfig{}
for _, opt := range opts { for _, opt := range opts {
opt(cfg) opt(cfg)
@ -37,5 +37,8 @@ func NewCleanUpDataCmdPayloadServer(
) )
require.NoError(tb, err) require.NoError(tb, err)
return payloadServer payload, err := domain.NewCleanUpDataCmdPayload(payloadServer)
require.NoError(tb, err)
return payload
} }

View File

@ -37,21 +37,33 @@ func NewServerCursor(tb TestingTB, opts ...func(cfg *ServerCursorConfig)) domain
} }
type ServerConfig struct { type ServerConfig struct {
Key string Key string
VersionCode string VersionCode string
URL *url.URL URL *url.URL
Open bool Open bool
Special bool Special bool
PlayerDataSyncedAt time.Time
PlayerSnapshotsCreatedAt time.Time
TribeDataSyncedAt time.Time
TribeSnapshotsCreatedAt time.Time
VillageDataSyncedAt time.Time
EnnoblementDataSyncedAt time.Time
} }
func NewServer(tb TestingTB, opts ...func(cfg *ServerConfig)) domain.Server { func NewServer(tb TestingTB, opts ...func(cfg *ServerConfig)) domain.Server {
tb.Helper() tb.Helper()
cfg := &ServerConfig{ cfg := &ServerConfig{
Key: RandServerKey(), Key: RandServerKey(),
VersionCode: RandVersionCode(), VersionCode: RandVersionCode(),
Open: true, Open: true,
Special: false, Special: false,
PlayerDataSyncedAt: time.Time{},
PlayerSnapshotsCreatedAt: time.Time{},
TribeDataSyncedAt: time.Time{},
TribeSnapshotsCreatedAt: time.Time{},
VillageDataSyncedAt: time.Time{},
EnnoblementDataSyncedAt: time.Time{},
} }
for _, opt := range opts { for _, opt := range opts {
@ -81,12 +93,12 @@ func NewServer(tb TestingTB, opts ...func(cfg *ServerConfig)) domain.Server {
NewBuildingInfo(tb), NewBuildingInfo(tb),
NewUnitInfo(tb), NewUnitInfo(tb),
time.Now(), time.Now(),
time.Time{}, cfg.PlayerDataSyncedAt,
time.Time{}, cfg.PlayerSnapshotsCreatedAt,
time.Time{}, cfg.TribeDataSyncedAt,
time.Time{}, cfg.TribeSnapshotsCreatedAt,
time.Time{}, cfg.VillageDataSyncedAt,
time.Time{}, cfg.EnnoblementDataSyncedAt,
) )
require.NoError(tb, err) require.NoError(tb, err)

View File

@ -6,6 +6,8 @@ import (
"time" "time"
) )
const EnnoblementRetentionForClosedServers = 365 * 24 * time.Hour
type Ennoblement struct { type Ennoblement struct {
id int id int
serverKey string serverKey string

View File

@ -731,3 +731,21 @@ func NewCleanUpDataCmdPayload(server CleanUpDataCmdPayloadServer) (CleanUpDataCm
func (p CleanUpDataCmdPayload) Server() CleanUpDataCmdPayloadServer { func (p CleanUpDataCmdPayload) Server() CleanUpDataCmdPayloadServer {
return p.server return p.server
} }
func (p CleanUpDataCmdPayload) CanCleanUpPlayerSnapshots() bool {
return !p.server.Open() &&
!p.server.Special() &&
p.server.PlayerSnapshotsCreatedAt().Before(time.Now().Add(-30*24*time.Hour) /* 30 days */)
}
func (p CleanUpDataCmdPayload) CanCleanUpTribeSnapshots() bool {
return !p.server.Open() &&
!p.server.Special() &&
p.server.TribeSnapshotsCreatedAt().Before(time.Now().Add(-30*24*time.Hour) /* 30 days */)
}
func (p CleanUpDataCmdPayload) CanCleanUpEnnoblements() bool {
return !p.server.Open() &&
!p.server.Special() &&
p.server.EnnoblementDataSyncedAt().Before(time.Now().Add(-30*24*time.Hour) /* 30 days */)
}

View File

@ -256,9 +256,105 @@ func TestNewCleanUpDataCmdPayloadServer(t *testing.T) {
func TestNewCleanUpDataCmdPayload(t *testing.T) { func TestNewCleanUpDataCmdPayload(t *testing.T) {
t.Parallel() t.Parallel()
server := domaintest.NewCleanUpDataCmdPayloadServer(t) server := domaintest.NewCleanUpDataCmdPayload(t).Server()
payload, err := domain.NewCleanUpDataCmdPayload(server) payload, err := domain.NewCleanUpDataCmdPayload(server)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, server, payload.Server()) assert.Equal(t, server, payload.Server())
} }
func TestCleanUpDataCmdPayload_CanCleanUpPlayerSnapshots(t *testing.T) {
t.Parallel()
validServerOpt := func(cfg *domaintest.ServerConfig) {
cfg.Special = false
cfg.Open = false
cfg.PlayerSnapshotsCreatedAt = time.Now().Add(-30*24*time.Hour - time.Minute)
}
assert.True(t, domaintest.NewCleanUpDataCmdPayload(t, func(cfg *domaintest.CleanUpDataCmdPayloadConfig) {
cfg.ServerOptions = append(cfg.ServerOptions, validServerOpt)
}).CanCleanUpPlayerSnapshots(), "special=false open=false playerSnapshotsCreatedAt<now-30 days")
assert.False(t, domaintest.NewCleanUpDataCmdPayload(t, func(cfg *domaintest.CleanUpDataCmdPayloadConfig) {
cfg.ServerOptions = append(cfg.ServerOptions, validServerOpt, func(cfg *domaintest.ServerConfig) {
cfg.Special = true
})
}).CanCleanUpPlayerSnapshots(), "special=true open=false playerSnapshotsCreatedAt<now-30 days")
assert.False(t, domaintest.NewCleanUpDataCmdPayload(t, func(cfg *domaintest.CleanUpDataCmdPayloadConfig) {
cfg.ServerOptions = append(cfg.ServerOptions, validServerOpt, func(cfg *domaintest.ServerConfig) {
cfg.Open = true
})
}).CanCleanUpPlayerSnapshots(), "special=false open=true playerSnapshotsCreatedAt<now-30 days")
assert.False(t, domaintest.NewCleanUpDataCmdPayload(t, func(cfg *domaintest.CleanUpDataCmdPayloadConfig) {
cfg.ServerOptions = append(cfg.ServerOptions, validServerOpt, func(cfg *domaintest.ServerConfig) {
cfg.PlayerSnapshotsCreatedAt = time.Now().Add(-30*24*time.Hour + time.Minute)
})
}).CanCleanUpPlayerSnapshots(), "special=false open=false playerSnapshotsCreatedAt>now-30 days")
}
func TestCleanUpDataCmdPayload_CanCleanUpTribeSnapshots(t *testing.T) {
t.Parallel()
validServerOpt := func(cfg *domaintest.ServerConfig) {
cfg.Special = false
cfg.Open = false
cfg.TribeSnapshotsCreatedAt = time.Now().Add(-30*24*time.Hour - time.Minute)
}
assert.True(t, domaintest.NewCleanUpDataCmdPayload(t, func(cfg *domaintest.CleanUpDataCmdPayloadConfig) {
cfg.ServerOptions = append(cfg.ServerOptions, validServerOpt)
}).CanCleanUpTribeSnapshots(), "special=false open=false tribeSnapshotsCreatedAt<now-30 days")
assert.False(t, domaintest.NewCleanUpDataCmdPayload(t, func(cfg *domaintest.CleanUpDataCmdPayloadConfig) {
cfg.ServerOptions = append(cfg.ServerOptions, validServerOpt, func(cfg *domaintest.ServerConfig) {
cfg.Special = true
})
}).CanCleanUpTribeSnapshots(), "special=true open=false tribeSnapshotsCreatedAt<now-30 days")
assert.False(t, domaintest.NewCleanUpDataCmdPayload(t, func(cfg *domaintest.CleanUpDataCmdPayloadConfig) {
cfg.ServerOptions = append(cfg.ServerOptions, validServerOpt, func(cfg *domaintest.ServerConfig) {
cfg.Open = true
})
}).CanCleanUpTribeSnapshots(), "special=false open=true tribeSnapshotsCreatedAt<now-30 days")
assert.False(t, domaintest.NewCleanUpDataCmdPayload(t, func(cfg *domaintest.CleanUpDataCmdPayloadConfig) {
cfg.ServerOptions = append(cfg.ServerOptions, validServerOpt, func(cfg *domaintest.ServerConfig) {
cfg.TribeSnapshotsCreatedAt = time.Now().Add(-30*24*time.Hour + time.Minute)
})
}).CanCleanUpTribeSnapshots(), "special=false open=false tribeSnapshotsCreatedAt>now-30 days")
}
func TestCleanUpDataCmdPayload_CanCleanUpEnnoblements(t *testing.T) {
t.Parallel()
validServerOpt := func(cfg *domaintest.ServerConfig) {
cfg.Special = false
cfg.Open = false
cfg.EnnoblementDataSyncedAt = time.Now().Add(-30*24*time.Hour - time.Minute)
}
assert.True(t, domaintest.NewCleanUpDataCmdPayload(t, func(cfg *domaintest.CleanUpDataCmdPayloadConfig) {
cfg.ServerOptions = append(cfg.ServerOptions, validServerOpt)
}).CanCleanUpEnnoblements(), "special=false open=false ennoblementDataSyncedAt<now-30 days")
assert.False(t, domaintest.NewCleanUpDataCmdPayload(t, func(cfg *domaintest.CleanUpDataCmdPayloadConfig) {
cfg.ServerOptions = append(cfg.ServerOptions, validServerOpt, func(cfg *domaintest.ServerConfig) {
cfg.Special = true
})
}).CanCleanUpEnnoblements(), "special=true open=false ennoblementDataSyncedAt<now-30 days")
assert.False(t, domaintest.NewCleanUpDataCmdPayload(t, func(cfg *domaintest.CleanUpDataCmdPayloadConfig) {
cfg.ServerOptions = append(cfg.ServerOptions, validServerOpt, func(cfg *domaintest.ServerConfig) {
cfg.Open = true
})
}).CanCleanUpEnnoblements(), "special=false open=true ennoblementDataSyncedAt<now-30 days")
assert.False(t, domaintest.NewCleanUpDataCmdPayload(t, func(cfg *domaintest.CleanUpDataCmdPayloadConfig) {
cfg.ServerOptions = append(cfg.ServerOptions, validServerOpt, func(cfg *domaintest.ServerConfig) {
cfg.EnnoblementDataSyncedAt = time.Now().Add(-30*24*time.Hour + time.Minute)
})
}).CanCleanUpEnnoblements(), "special=false open=false ennoblementDataSyncedAt>now-30 days")
}

View File

@ -6,6 +6,8 @@ import (
"time" "time"
) )
const PlayerSnapshotRetentionForClosedServers = 180 * 24 * time.Hour
type PlayerSnapshot struct { type PlayerSnapshot struct {
id int id int
playerID int playerID int

View File

@ -6,6 +6,8 @@ import (
"time" "time"
) )
const TribeSnapshotRetentionForClosedServers = 180 * 24 * time.Hour
type TribeSnapshot struct { type TribeSnapshot struct {
id int id int
tribeID int tribeID int

View File

@ -179,6 +179,7 @@ func TestDataSync(t *testing.T) {
serverEventSynced, serverEventSynced,
villageEventSynced, villageEventSynced,
"", "",
"",
), ),
port.NewPlayerWatermillConsumer( port.NewPlayerWatermillConsumer(
playerSvc, playerSvc,
@ -188,6 +189,7 @@ func TestDataSync(t *testing.T) {
marshaler, marshaler,
serverEventSynced, serverEventSynced,
"", "",
"",
), ),
port.NewVillageWatermillConsumer(villageSvc, villageSub, nopLogger, marshaler, serverEventSynced), port.NewVillageWatermillConsumer(villageSvc, villageSub, nopLogger, marshaler, serverEventSynced),
) )

View File

@ -150,7 +150,7 @@ func TestEnnoblementSync(t *testing.T) {
"", "",
"", "",
), ),
port.NewEnnoblementWatermillConsumer(ennoblementSvc, ennoblementSub, nopLogger, marshaler, ennoblementCmdSync), port.NewEnnoblementWatermillConsumer(ennoblementSvc, ennoblementSub, nopLogger, marshaler, ennoblementCmdSync, ""),
) )
for _, stage := range []uint{1, 2} { for _, stage := range []uint{1, 2} {

View File

@ -129,6 +129,7 @@ func TestSnapshotCreation(t *testing.T) {
marshaler, marshaler,
"", "",
playerSnapshotCmdCreate, playerSnapshotCmdCreate,
"",
), ),
port.NewTribeWatermillConsumer( port.NewTribeWatermillConsumer(
nil, nil,
@ -139,6 +140,7 @@ func TestSnapshotCreation(t *testing.T) {
"", "",
"", "",
tribeSnapshotCmdCreate, tribeSnapshotCmdCreate,
"",
), ),
) )

View File

@ -9,11 +9,12 @@ import (
) )
type EnnoblementWatermillConsumer struct { type EnnoblementWatermillConsumer struct {
svc *app.EnnoblementService svc *app.EnnoblementService
subscriber message.Subscriber subscriber message.Subscriber
logger watermill.LoggerAdapter logger watermill.LoggerAdapter
marshaler watermillmsg.Marshaler marshaler watermillmsg.Marshaler
cmdSyncTopic string cmdSyncTopic string
cmdCleanUpTopic string
} }
func NewEnnoblementWatermillConsumer( func NewEnnoblementWatermillConsumer(
@ -22,13 +23,15 @@ func NewEnnoblementWatermillConsumer(
logger watermill.LoggerAdapter, logger watermill.LoggerAdapter,
marshaler watermillmsg.Marshaler, marshaler watermillmsg.Marshaler,
cmdSyncTopic string, cmdSyncTopic string,
cmdCleanUpTopic string,
) *EnnoblementWatermillConsumer { ) *EnnoblementWatermillConsumer {
return &EnnoblementWatermillConsumer{ return &EnnoblementWatermillConsumer{
svc: svc, svc: svc,
subscriber: subscriber, subscriber: subscriber,
logger: logger, logger: logger,
marshaler: marshaler, marshaler: marshaler,
cmdSyncTopic: cmdSyncTopic, cmdSyncTopic: cmdSyncTopic,
cmdCleanUpTopic: cmdCleanUpTopic,
} }
} }
@ -39,6 +42,12 @@ func (c *EnnoblementWatermillConsumer) Register(router *message.Router) {
c.subscriber, c.subscriber,
c.sync, c.sync,
) )
router.AddNoPublisherHandler(
"EnnoblementConsumer.cleanUp",
c.cmdCleanUpTopic,
c.subscriber,
c.cleanUp,
)
} }
func (c *EnnoblementWatermillConsumer) sync(msg *message.Message) error { func (c *EnnoblementWatermillConsumer) sync(msg *message.Message) error {
@ -65,3 +74,43 @@ func (c *EnnoblementWatermillConsumer) sync(msg *message.Message) error {
return c.svc.Sync(msg.Context(), payload) return c.svc.Sync(msg.Context(), payload)
} }
func (c *EnnoblementWatermillConsumer) cleanUp(msg *message.Message) error {
var rawPayload watermillmsg.CleanUpDataCmdPayload
if err := c.marshaler.Unmarshal(msg, &rawPayload); err != nil {
c.logger.Error("couldn't unmarshal payload", err, watermill.LogFields{
"handler": message.HandlerNameFromCtx(msg.Context()),
})
return nil
}
payloadServer, err := domain.NewCleanUpDataCmdPayloadServer(
rawPayload.Server.Key,
rawPayload.Server.VersionCode,
rawPayload.Server.Open,
rawPayload.Server.Special,
rawPayload.Server.PlayerDataSyncedAt,
rawPayload.Server.PlayerSnapshotsCreatedAt,
rawPayload.Server.TribeDataSyncedAt,
rawPayload.Server.TribeSnapshotsCreatedAt,
rawPayload.Server.VillageDataSyncedAt,
rawPayload.Server.EnnoblementDataSyncedAt,
)
if err != nil {
c.logger.Error("couldn't construct domain.CleanUpDataCmdPayloadServer", err, watermill.LogFields{
"handler": message.HandlerNameFromCtx(msg.Context()),
})
return nil
}
payload, err := domain.NewCleanUpDataCmdPayload(payloadServer)
if err != nil {
c.logger.Error("couldn't construct domain.CleanUpDataCmdPayload", err, watermill.LogFields{
"handler": message.HandlerNameFromCtx(msg.Context()),
})
return nil
}
return c.svc.CleanUp(msg.Context(), payload)
}

View File

@ -16,6 +16,7 @@ type PlayerWatermillConsumer struct {
marshaler watermillmsg.Marshaler marshaler watermillmsg.Marshaler
eventServerSyncedTopic string eventServerSyncedTopic string
cmdCreateSnapshotsTopic string cmdCreateSnapshotsTopic string
cmdCleanUpTopic string
} }
func NewPlayerWatermillConsumer( func NewPlayerWatermillConsumer(
@ -26,6 +27,7 @@ func NewPlayerWatermillConsumer(
marshaler watermillmsg.Marshaler, marshaler watermillmsg.Marshaler,
eventServerSyncedTopic string, eventServerSyncedTopic string,
cmdCreateSnapshotsTopic string, cmdCreateSnapshotsTopic string,
cmdCleanUpTopic string,
) *PlayerWatermillConsumer { ) *PlayerWatermillConsumer {
return &PlayerWatermillConsumer{ return &PlayerWatermillConsumer{
svc: svc, svc: svc,
@ -35,6 +37,7 @@ func NewPlayerWatermillConsumer(
marshaler: marshaler, marshaler: marshaler,
eventServerSyncedTopic: eventServerSyncedTopic, eventServerSyncedTopic: eventServerSyncedTopic,
cmdCreateSnapshotsTopic: cmdCreateSnapshotsTopic, cmdCreateSnapshotsTopic: cmdCreateSnapshotsTopic,
cmdCleanUpTopic: cmdCleanUpTopic,
} }
} }
@ -51,6 +54,12 @@ func (c *PlayerWatermillConsumer) Register(router *message.Router) {
c.subscriber, c.subscriber,
c.createSnapshots, c.createSnapshots,
) )
router.AddNoPublisherHandler(
"PlayerConsumer.cleanUp",
c.cmdCleanUpTopic,
c.subscriber,
c.cleanUp,
)
} }
func (c *PlayerWatermillConsumer) sync(msg *message.Message) error { func (c *PlayerWatermillConsumer) sync(msg *message.Message) error {
@ -99,3 +108,43 @@ func (c *PlayerWatermillConsumer) createSnapshots(msg *message.Message) error {
return c.snapshotSvc.Create(msg.Context(), payload) return c.snapshotSvc.Create(msg.Context(), payload)
} }
func (c *PlayerWatermillConsumer) cleanUp(msg *message.Message) error {
var rawPayload watermillmsg.CleanUpDataCmdPayload
if err := c.marshaler.Unmarshal(msg, &rawPayload); err != nil {
c.logger.Error("couldn't unmarshal payload", err, watermill.LogFields{
"handler": message.HandlerNameFromCtx(msg.Context()),
})
return nil
}
payloadServer, err := domain.NewCleanUpDataCmdPayloadServer(
rawPayload.Server.Key,
rawPayload.Server.VersionCode,
rawPayload.Server.Open,
rawPayload.Server.Special,
rawPayload.Server.PlayerDataSyncedAt,
rawPayload.Server.PlayerSnapshotsCreatedAt,
rawPayload.Server.TribeDataSyncedAt,
rawPayload.Server.TribeSnapshotsCreatedAt,
rawPayload.Server.VillageDataSyncedAt,
rawPayload.Server.EnnoblementDataSyncedAt,
)
if err != nil {
c.logger.Error("couldn't construct domain.CleanUpDataCmdPayloadServer", err, watermill.LogFields{
"handler": message.HandlerNameFromCtx(msg.Context()),
})
return nil
}
payload, err := domain.NewCleanUpDataCmdPayload(payloadServer)
if err != nil {
c.logger.Error("couldn't construct domain.CleanUpDataCmdPayload", err, watermill.LogFields{
"handler": message.HandlerNameFromCtx(msg.Context()),
})
return nil
}
return c.snapshotSvc.CleanUp(msg.Context(), payload)
}

View File

@ -17,6 +17,7 @@ type TribeWatermillConsumer struct {
eventServerSyncedTopic string eventServerSyncedTopic string
eventVillagesSyncedTopic string eventVillagesSyncedTopic string
cmdCreateSnapshotsTopic string cmdCreateSnapshotsTopic string
cmdCleanUpTopic string
} }
func NewTribeWatermillConsumer( func NewTribeWatermillConsumer(
@ -28,6 +29,7 @@ func NewTribeWatermillConsumer(
eventServerSyncedTopic string, eventServerSyncedTopic string,
eventVillagesSyncedTopic string, eventVillagesSyncedTopic string,
cmdCreateSnapshotsTopic string, cmdCreateSnapshotsTopic string,
cmdCleanUpTopic string,
) *TribeWatermillConsumer { ) *TribeWatermillConsumer {
return &TribeWatermillConsumer{ return &TribeWatermillConsumer{
svc: svc, svc: svc,
@ -38,6 +40,7 @@ func NewTribeWatermillConsumer(
eventServerSyncedTopic: eventServerSyncedTopic, eventServerSyncedTopic: eventServerSyncedTopic,
eventVillagesSyncedTopic: eventVillagesSyncedTopic, eventVillagesSyncedTopic: eventVillagesSyncedTopic,
cmdCreateSnapshotsTopic: cmdCreateSnapshotsTopic, cmdCreateSnapshotsTopic: cmdCreateSnapshotsTopic,
cmdCleanUpTopic: cmdCleanUpTopic,
} }
} }
@ -60,6 +63,12 @@ func (c *TribeWatermillConsumer) Register(router *message.Router) {
c.subscriber, c.subscriber,
c.createSnapshots, c.createSnapshots,
) )
router.AddNoPublisherHandler(
"TribeConsumer.cleanUp",
c.cmdCleanUpTopic,
c.subscriber,
c.cleanUp,
)
} }
func (c *TribeWatermillConsumer) sync(msg *message.Message) error { func (c *TribeWatermillConsumer) sync(msg *message.Message) error {
@ -137,3 +146,43 @@ func (c *TribeWatermillConsumer) createSnapshots(msg *message.Message) error {
return c.snapshotSvc.Create(msg.Context(), payload) return c.snapshotSvc.Create(msg.Context(), payload)
} }
func (c *TribeWatermillConsumer) cleanUp(msg *message.Message) error {
var rawPayload watermillmsg.CleanUpDataCmdPayload
if err := c.marshaler.Unmarshal(msg, &rawPayload); err != nil {
c.logger.Error("couldn't unmarshal payload", err, watermill.LogFields{
"handler": message.HandlerNameFromCtx(msg.Context()),
})
return nil
}
payloadServer, err := domain.NewCleanUpDataCmdPayloadServer(
rawPayload.Server.Key,
rawPayload.Server.VersionCode,
rawPayload.Server.Open,
rawPayload.Server.Special,
rawPayload.Server.PlayerDataSyncedAt,
rawPayload.Server.PlayerSnapshotsCreatedAt,
rawPayload.Server.TribeDataSyncedAt,
rawPayload.Server.TribeSnapshotsCreatedAt,
rawPayload.Server.VillageDataSyncedAt,
rawPayload.Server.EnnoblementDataSyncedAt,
)
if err != nil {
c.logger.Error("couldn't construct domain.CleanUpDataCmdPayloadServer", err, watermill.LogFields{
"handler": message.HandlerNameFromCtx(msg.Context()),
})
return nil
}
payload, err := domain.NewCleanUpDataCmdPayload(payloadServer)
if err != nil {
c.logger.Error("couldn't construct domain.CleanUpDataCmdPayload", err, watermill.LogFields{
"handler": message.HandlerNameFromCtx(msg.Context()),
})
return nil
}
return c.snapshotSvc.CleanUp(msg.Context(), payload)
}