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

View File

@ -5,6 +5,7 @@ import (
"database/sql"
"errors"
"fmt"
"time"
"gitea.dwysokinski.me/twhelp/corev3/internal/bun/bunmodel"
"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
@ -108,6 +109,19 @@ func (repo *EnnoblementBunRepository) ListWithRelations(
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 {
params domain.ListEnnoblementsParams
}

View File

@ -107,6 +107,19 @@ func (repo *PlayerSnapshotBunRepository) ListWithRelations(
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 {
params domain.ListPlayerSnapshotsParams
}

View File

@ -103,6 +103,19 @@ func (repo *TribeSnapshotBunRepository) ListWithRelations(
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 {
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) {
t.Helper()
ennoblements := res.Ennoblements()
assert.NotEmpty(t, len(ennoblements))
assert.NotEmpty(t, ennoblements)
assert.True(t, slices.IsSortedFunc(ennoblements, func(a, b domain.Ennoblement) int {
return cmp.Or(
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) {
t.Helper()
ennoblements := res.Ennoblements()
assert.NotEmpty(t, len(ennoblements))
assert.NotEmpty(t, ennoblements)
assert.True(t, slices.IsSortedFunc(ennoblements, func(a, b domain.Ennoblement) int {
return cmp.Or(
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) {
t.Helper()
ennoblements := res.Ennoblements()
assert.NotEmpty(t, len(ennoblements))
assert.NotEmpty(t, ennoblements)
assert.True(t, slices.IsSortedFunc(ennoblements, func(a, b domain.Ennoblement) int {
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) {
t.Helper()
ennoblements := res.Ennoblements()
assert.NotEmpty(t, len(ennoblements))
assert.NotEmpty(t, ennoblements)
assert.True(t, slices.IsSortedFunc(ennoblements, func(a, b domain.Ennoblement) int {
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()
ennoblements := res.Ennoblements()
assert.NotEmpty(t, len(ennoblements))
assert.NotEmpty(t, ennoblements)
for _, e := range ennoblements {
assert.GreaterOrEqual(t, e.ID(), params.Cursor().ID())
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) {
t.Helper()
ennoblements := res.Ennoblements()
assert.NotEmpty(t, len(ennoblements))
assert.NotEmpty(t, ennoblements)
assert.True(t, slices.IsSortedFunc(ennoblements, func(a, b domain.Ennoblement) int {
return cmp.Or(
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) {
t.Helper()
ennoblements := res.Ennoblements()
assert.NotEmpty(t, len(ennoblements))
assert.NotEmpty(t, ennoblements)
assert.True(t, slices.IsSortedFunc(ennoblements, func(a, b domain.Ennoblement) int {
return cmp.Or(
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()
playerSnapshots := res.PlayerSnapshots()
assert.NotEmpty(t, len(playerSnapshots))
assert.NotEmpty(t, playerSnapshots)
assert.True(t, slices.IsSortedFunc(playerSnapshots, func(a, b domain.PlayerSnapshot) int {
return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -174,7 +174,7 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
) {
t.Helper()
playerSnapshots := res.PlayerSnapshots()
assert.NotEmpty(t, len(playerSnapshots))
assert.NotEmpty(t, playerSnapshots)
assert.True(t, slices.IsSortedFunc(playerSnapshots, func(a, b domain.PlayerSnapshot) int {
return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -200,7 +200,7 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
) {
t.Helper()
playerSnapshots := res.PlayerSnapshots()
assert.NotEmpty(t, len(playerSnapshots))
assert.NotEmpty(t, playerSnapshots)
assert.True(t, slices.IsSortedFunc(playerSnapshots, func(a, b domain.PlayerSnapshot) int {
return cmp.Compare(a.ID(), b.ID())
}))
@ -223,7 +223,7 @@ func testPlayerSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repo
) {
t.Helper()
playerSnapshots := res.PlayerSnapshots()
assert.NotEmpty(t, len(playerSnapshots))
assert.NotEmpty(t, playerSnapshots)
assert.True(t, slices.IsSortedFunc(playerSnapshots, func(a, b domain.PlayerSnapshot) int {
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()
playerSnapshots := res.PlayerSnapshots()
assert.NotEmpty(t, len(playerSnapshots))
assert.NotEmpty(t, playerSnapshots)
for _, ps := range playerSnapshots {
assert.GreaterOrEqual(t, ps.ID(), params.Cursor().ID())
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) {
t.Helper()
playerSnapshots := res.PlayerSnapshots()
assert.NotEmpty(t, len(playerSnapshots))
assert.NotEmpty(t, playerSnapshots)
assert.True(t, slices.IsSortedFunc(playerSnapshots, func(a, b domain.PlayerSnapshot) int {
return cmp.Or(
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) {
t.Helper()
playerSnapshots := res.PlayerSnapshots()
assert.NotEmpty(t, len(playerSnapshots))
assert.NotEmpty(t, playerSnapshots)
assert.True(t, slices.IsSortedFunc(playerSnapshots, func(a, b domain.PlayerSnapshot) int {
return cmp.Or(
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) {
t.Helper()
players := res.Players()
assert.NotEmpty(t, len(players))
assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or(
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) {
t.Helper()
players := res.Players()
assert.NotEmpty(t, len(players))
assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or(
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) {
t.Helper()
players := res.Players()
assert.NotEmpty(t, len(players))
assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or(
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) {
t.Helper()
players := res.Players()
assert.NotEmpty(t, len(players))
assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or(
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) {
t.Helper()
players := res.Players()
assert.NotEmpty(t, len(players))
assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or(
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) {
t.Helper()
players := res.Players()
assert.NotEmpty(t, len(players))
assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or(
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) {
t.Helper()
players := res.Players()
assert.NotEmpty(t, len(players))
assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or(
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) {
t.Helper()
players := res.Players()
assert.NotEmpty(t, len(players))
assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or(
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) {
t.Helper()
players := res.Players()
assert.NotEmpty(t, len(players))
assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or(
a.DeletedAt().Compare(b.DeletedAt())*-1,
@ -487,7 +487,7 @@ func testPlayerRepository(t *testing.T, newRepos func(t *testing.T) repositories
serverKeys := params.ServerKeys()
players := res.Players()
assert.NotEmpty(t, len(players))
assert.NotEmpty(t, players)
for _, p := range players {
assert.GreaterOrEqual(t, p.ID(), params.Cursor().ID())
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) {
t.Helper()
players := res.Players()
assert.NotEmpty(t, len(players))
assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or(
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) {
t.Helper()
players := res.Players()
assert.NotEmpty(t, len(players))
assert.NotEmpty(t, players)
assert.True(t, slices.IsSortedFunc(players, func(a, b domain.Player) int {
return cmp.Or(
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) {
t.Helper()
servers := res.Servers()
assert.NotEmpty(t, len(servers))
assert.NotEmpty(t, servers)
assert.True(t, slices.IsSortedFunc(servers, func(a, b domain.Server) int {
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) {
t.Helper()
servers := res.Servers()
assert.NotEmpty(t, len(servers))
assert.NotEmpty(t, servers)
assert.True(t, slices.IsSortedFunc(servers, func(a, b domain.Server) int {
if a.Open() && !b.Open() {
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) {
t.Helper()
servers := res.Servers()
assert.NotEmpty(t, len(servers))
assert.NotEmpty(t, servers)
assert.True(t, slices.IsSortedFunc(servers, func(a, b domain.Server) int {
if a.Open() && !b.Open() {
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) {
t.Helper()
servers := res.Servers()
assert.NotEmpty(t, len(servers))
assert.NotEmpty(t, servers)
for _, s := range servers {
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) {
t.Helper()
servers := res.Servers()
assert.NotEmpty(t, len(servers))
assert.NotEmpty(t, servers)
for _, s := range servers {
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) {
t.Helper()
servers := res.Servers()
assert.NotEmpty(t, len(servers))
assert.NotEmpty(t, servers)
for _, s := range servers {
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) {
t.Helper()
servers := res.Servers()
assert.NotEmpty(t, len(servers))
assert.NotEmpty(t, servers)
for _, s := range servers {
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) {
t.Helper()
servers := res.Servers()
assert.NotEmpty(t, len(servers))
assert.NotEmpty(t, servers)
assert.True(t, slices.IsSortedFunc(servers, func(a, b domain.Server) int {
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) {
t.Helper()
servers := res.Servers()
assert.NotEmpty(t, len(servers))
assert.NotEmpty(t, servers)
assert.True(t, slices.IsSortedFunc(servers, func(a, b domain.Server) int {
if a.Open() && !b.Open() {
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) {
t.Helper()
servers := res.Servers()
assert.NotEmpty(t, len(servers))
assert.NotEmpty(t, servers)
assert.True(t, slices.IsSortedFunc(servers, func(a, b domain.Server) int {
if a.Open() && !b.Open() {
return -1

View File

@ -4,6 +4,7 @@ import (
"context"
"os"
"testing"
"time"
"gitea.dwysokinski.me/twhelp/corev3/internal/adapter"
"gitea.dwysokinski.me/twhelp/corev3/internal/bun/buntest"
@ -52,6 +53,7 @@ type ennoblementRepository interface {
ctx context.Context,
params domain.ListEnnoblementsParams,
) (domain.ListEnnoblementsWithRelationsResult, error)
Delete(ctx context.Context, serverKey string, createdAtLTE time.Time) error
}
type tribeChangeRepository interface {
@ -70,6 +72,7 @@ type tribeSnapshotRepository interface {
ctx context.Context,
params domain.ListTribeSnapshotsParams,
) (domain.ListTribeSnapshotsWithRelationsResult, error)
Delete(ctx context.Context, serverKey string, dateLTE time.Time) error
}
type playerSnapshotRepository interface {
@ -79,6 +82,7 @@ type playerSnapshotRepository interface {
ctx context.Context,
params domain.ListPlayerSnapshotsParams,
) (domain.ListPlayerSnapshotsWithRelationsResult, error)
Delete(ctx context.Context, serverKey string, dateLTE time.Time) error
}
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) {
t.Helper()
tribeChanges := res.TribeChanges()
assert.NotEmpty(t, len(tribeChanges))
assert.NotEmpty(t, tribeChanges)
assert.True(t, slices.IsSortedFunc(tribeChanges, func(a, b domain.TribeChange) int {
return cmp.Or(
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) {
t.Helper()
tribeChanges := res.TribeChanges()
assert.NotEmpty(t, len(tribeChanges))
assert.NotEmpty(t, tribeChanges)
assert.True(t, slices.IsSortedFunc(tribeChanges, func(a, b domain.TribeChange) int {
return cmp.Or(
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) {
t.Helper()
tribeChanges := res.TribeChanges()
assert.NotEmpty(t, len(tribeChanges))
assert.NotEmpty(t, tribeChanges)
assert.True(t, slices.IsSortedFunc(tribeChanges, func(a, b domain.TribeChange) int {
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) {
t.Helper()
tribeChanges := res.TribeChanges()
assert.NotEmpty(t, len(tribeChanges))
assert.NotEmpty(t, tribeChanges)
assert.True(t, slices.IsSortedFunc(tribeChanges, func(a, b domain.TribeChange) int {
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()
tribeSnapshots := res.TribeSnapshots()
assert.NotEmpty(t, len(tribeSnapshots))
assert.NotEmpty(t, tribeSnapshots)
assert.True(t, slices.IsSortedFunc(tribeSnapshots, func(a, b domain.TribeSnapshot) int {
return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -172,7 +172,7 @@ func testTribeSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repos
) {
t.Helper()
tribeSnapshots := res.TribeSnapshots()
assert.NotEmpty(t, len(tribeSnapshots))
assert.NotEmpty(t, tribeSnapshots)
assert.True(t, slices.IsSortedFunc(tribeSnapshots, func(a, b domain.TribeSnapshot) int {
return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()),
@ -199,7 +199,7 @@ func testTribeSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repos
) {
t.Helper()
tribeSnapshots := res.TribeSnapshots()
assert.NotEmpty(t, len(tribeSnapshots))
assert.NotEmpty(t, tribeSnapshots)
assert.True(t, slices.IsSortedFunc(tribeSnapshots, func(a, b domain.TribeSnapshot) int {
return cmp.Compare(a.ID(), b.ID())
}))
@ -222,7 +222,7 @@ func testTribeSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repos
) {
t.Helper()
tribeSnapshots := res.TribeSnapshots()
assert.NotEmpty(t, len(tribeSnapshots))
assert.NotEmpty(t, tribeSnapshots)
assert.True(t, slices.IsSortedFunc(tribeSnapshots, func(a, b domain.TribeSnapshot) int {
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()
tribeSnapshots := res.TribeSnapshots()
assert.NotEmpty(t, len(tribeSnapshots))
assert.NotEmpty(t, tribeSnapshots)
for _, ts := range tribeSnapshots {
assert.GreaterOrEqual(t, ts.ID(), params.Cursor().ID())
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) {
t.Helper()
tribeSnapshots := res.TribeSnapshots()
assert.NotEmpty(t, len(tribeSnapshots))
assert.NotEmpty(t, tribeSnapshots)
assert.True(t, slices.IsSortedFunc(tribeSnapshots, func(a, b domain.TribeSnapshot) int {
return cmp.Or(
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) {
t.Helper()
tribeSnapshots := res.TribeSnapshots()
assert.NotEmpty(t, len(tribeSnapshots))
assert.NotEmpty(t, tribeSnapshots)
assert.True(t, slices.IsSortedFunc(tribeSnapshots, func(a, b domain.TribeSnapshot) int {
return cmp.Or(
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) {
t.Helper()
tribes := res.Tribes()
assert.NotEmpty(t, len(tribes))
assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or(
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) {
t.Helper()
tribes := res.Tribes()
assert.NotEmpty(t, len(tribes))
assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or(
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) {
t.Helper()
tribes := res.Tribes()
assert.NotEmpty(t, len(tribes))
assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or(
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) {
t.Helper()
tribes := res.Tribes()
assert.NotEmpty(t, len(tribes))
assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or(
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) {
t.Helper()
tribes := res.Tribes()
assert.NotEmpty(t, len(tribes))
assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or(
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) {
t.Helper()
tribes := res.Tribes()
assert.NotEmpty(t, len(tribes))
assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or(
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) {
t.Helper()
tribes := res.Tribes()
assert.NotEmpty(t, len(tribes))
assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or(
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) {
t.Helper()
tribes := res.Tribes()
assert.NotEmpty(t, len(tribes))
assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or(
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) {
t.Helper()
tribes := res.Tribes()
assert.NotEmpty(t, len(tribes))
assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or(
a.DeletedAt().Compare(b.DeletedAt())*-1,
@ -516,7 +516,7 @@ func testTribeRepository(t *testing.T, newRepos func(t *testing.T) repositories)
serverKeys := params.ServerKeys()
tribes := res.Tribes()
assert.NotEmpty(t, len(tribes))
assert.NotEmpty(t, tribes)
for _, tr := range res.Tribes() {
assert.GreaterOrEqual(t, tr.ID(), params.Cursor().ID())
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) {
t.Helper()
tribes := res.Tribes()
assert.NotEmpty(t, len(tribes))
assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or(
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) {
t.Helper()
tribes := res.Tribes()
assert.NotEmpty(t, len(tribes))
assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or(
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) {
t.Helper()
tribes := res.Tribes()
assert.NotEmpty(t, len(tribes))
assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or(
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) {
t.Helper()
tribes := res.Tribes()
assert.NotEmpty(t, len(tribes))
assert.NotEmpty(t, tribes)
assert.True(t, slices.IsSortedFunc(tribes, func(a, b domain.Tribe) int {
return cmp.Or(
a.DeletedAt().Compare(b.DeletedAt()),

View File

@ -16,6 +16,7 @@ type EnnoblementRepository interface {
ctx context.Context,
params domain.ListEnnoblementsParams,
) (domain.ListEnnoblementsWithRelationsResult, error)
Delete(ctx context.Context, serverKey string, createdAtLTE time.Time) error
}
type EnnoblementService struct {
@ -136,3 +137,19 @@ func (svc *EnnoblementService) ListWithRelations(
) (domain.ListEnnoblementsWithRelationsResult, error) {
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 (
"context"
"fmt"
"time"
"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
)
@ -15,6 +16,7 @@ type PlayerSnapshotRepository interface {
ctx context.Context,
params domain.ListPlayerSnapshotsParams,
) (domain.ListPlayerSnapshotsWithRelationsResult, error)
Delete(ctx context.Context, serverKey string, dateLTE time.Time) error
}
type PlayerSnapshotService struct {
@ -103,3 +105,19 @@ func (svc *PlayerSnapshotService) ListWithRelations(
) (domain.ListPlayerSnapshotsWithRelationsResult, error) {
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 (
"context"
"fmt"
"time"
"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
)
@ -15,6 +16,7 @@ type TribeSnapshotRepository interface {
ctx context.Context,
params domain.ListTribeSnapshotsParams,
) (domain.ListTribeSnapshotsWithRelationsResult, error)
Delete(ctx context.Context, serverKey string, dateLTE time.Time) error
}
type TribeSnapshotService struct {
@ -103,3 +105,19 @@ func (svc *TribeSnapshotService) ListWithRelations(
) (domain.ListTribeSnapshotsWithRelationsResult, error) {
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"
)
type CleanUpDataCmdPayloadServerConfig struct {
type CleanUpDataCmdPayloadConfig struct {
ServerOptions []func(cfg *ServerConfig)
}
func NewCleanUpDataCmdPayloadServer(
func NewCleanUpDataCmdPayload(
tb TestingTB,
opts ...func(cfg *CleanUpDataCmdPayloadServerConfig),
) domain.CleanUpDataCmdPayloadServer {
opts ...func(cfg *CleanUpDataCmdPayloadConfig),
) domain.CleanUpDataCmdPayload {
tb.Helper()
cfg := &CleanUpDataCmdPayloadServerConfig{}
cfg := &CleanUpDataCmdPayloadConfig{}
for _, opt := range opts {
opt(cfg)
@ -37,5 +37,8 @@ func NewCleanUpDataCmdPayloadServer(
)
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 {
Key string
VersionCode string
URL *url.URL
Open bool
Special bool
Key string
VersionCode string
URL *url.URL
Open 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 {
tb.Helper()
cfg := &ServerConfig{
Key: RandServerKey(),
VersionCode: RandVersionCode(),
Open: true,
Special: false,
Key: RandServerKey(),
VersionCode: RandVersionCode(),
Open: true,
Special: false,
PlayerDataSyncedAt: time.Time{},
PlayerSnapshotsCreatedAt: time.Time{},
TribeDataSyncedAt: time.Time{},
TribeSnapshotsCreatedAt: time.Time{},
VillageDataSyncedAt: time.Time{},
EnnoblementDataSyncedAt: time.Time{},
}
for _, opt := range opts {
@ -81,12 +93,12 @@ func NewServer(tb TestingTB, opts ...func(cfg *ServerConfig)) domain.Server {
NewBuildingInfo(tb),
NewUnitInfo(tb),
time.Now(),
time.Time{},
time.Time{},
time.Time{},
time.Time{},
time.Time{},
time.Time{},
cfg.PlayerDataSyncedAt,
cfg.PlayerSnapshotsCreatedAt,
cfg.TribeDataSyncedAt,
cfg.TribeSnapshotsCreatedAt,
cfg.VillageDataSyncedAt,
cfg.EnnoblementDataSyncedAt,
)
require.NoError(tb, err)

View File

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

View File

@ -731,3 +731,21 @@ func NewCleanUpDataCmdPayload(server CleanUpDataCmdPayloadServer) (CleanUpDataCm
func (p CleanUpDataCmdPayload) Server() CleanUpDataCmdPayloadServer {
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) {
t.Parallel()
server := domaintest.NewCleanUpDataCmdPayloadServer(t)
server := domaintest.NewCleanUpDataCmdPayload(t).Server()
payload, err := domain.NewCleanUpDataCmdPayload(server)
require.NoError(t, err)
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"
)
const PlayerSnapshotRetentionForClosedServers = 180 * 24 * time.Hour
type PlayerSnapshot struct {
id int
playerID int

View File

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

View File

@ -179,6 +179,7 @@ func TestDataSync(t *testing.T) {
serverEventSynced,
villageEventSynced,
"",
"",
),
port.NewPlayerWatermillConsumer(
playerSvc,
@ -188,6 +189,7 @@ func TestDataSync(t *testing.T) {
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} {

View File

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

View File

@ -9,11 +9,12 @@ import (
)
type EnnoblementWatermillConsumer struct {
svc *app.EnnoblementService
subscriber message.Subscriber
logger watermill.LoggerAdapter
marshaler watermillmsg.Marshaler
cmdSyncTopic string
svc *app.EnnoblementService
subscriber message.Subscriber
logger watermill.LoggerAdapter
marshaler watermillmsg.Marshaler
cmdSyncTopic string
cmdCleanUpTopic string
}
func NewEnnoblementWatermillConsumer(
@ -22,13 +23,15 @@ func NewEnnoblementWatermillConsumer(
logger watermill.LoggerAdapter,
marshaler watermillmsg.Marshaler,
cmdSyncTopic string,
cmdCleanUpTopic string,
) *EnnoblementWatermillConsumer {
return &EnnoblementWatermillConsumer{
svc: svc,
subscriber: subscriber,
logger: logger,
marshaler: marshaler,
cmdSyncTopic: cmdSyncTopic,
svc: svc,
subscriber: subscriber,
logger: logger,
marshaler: marshaler,
cmdSyncTopic: cmdSyncTopic,
cmdCleanUpTopic: cmdCleanUpTopic,
}
}
@ -39,6 +42,12 @@ func (c *EnnoblementWatermillConsumer) Register(router *message.Router) {
c.subscriber,
c.sync,
)
router.AddNoPublisherHandler(
"EnnoblementConsumer.cleanUp",
c.cmdCleanUpTopic,
c.subscriber,
c.cleanUp,
)
}
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)
}
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
eventServerSyncedTopic string
cmdCreateSnapshotsTopic string
cmdCleanUpTopic string
}
func NewPlayerWatermillConsumer(
@ -26,6 +27,7 @@ func NewPlayerWatermillConsumer(
marshaler watermillmsg.Marshaler,
eventServerSyncedTopic string,
cmdCreateSnapshotsTopic string,
cmdCleanUpTopic string,
) *PlayerWatermillConsumer {
return &PlayerWatermillConsumer{
svc: svc,
@ -35,6 +37,7 @@ func NewPlayerWatermillConsumer(
marshaler: marshaler,
eventServerSyncedTopic: eventServerSyncedTopic,
cmdCreateSnapshotsTopic: cmdCreateSnapshotsTopic,
cmdCleanUpTopic: cmdCleanUpTopic,
}
}
@ -51,6 +54,12 @@ func (c *PlayerWatermillConsumer) Register(router *message.Router) {
c.subscriber,
c.createSnapshots,
)
router.AddNoPublisherHandler(
"PlayerConsumer.cleanUp",
c.cmdCleanUpTopic,
c.subscriber,
c.cleanUp,
)
}
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)
}
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
eventVillagesSyncedTopic string
cmdCreateSnapshotsTopic string
cmdCleanUpTopic string
}
func NewTribeWatermillConsumer(
@ -28,6 +29,7 @@ func NewTribeWatermillConsumer(
eventServerSyncedTopic string,
eventVillagesSyncedTopic string,
cmdCreateSnapshotsTopic string,
cmdCleanUpTopic string,
) *TribeWatermillConsumer {
return &TribeWatermillConsumer{
svc: svc,
@ -38,6 +40,7 @@ func NewTribeWatermillConsumer(
eventServerSyncedTopic: eventServerSyncedTopic,
eventVillagesSyncedTopic: eventVillagesSyncedTopic,
cmdCreateSnapshotsTopic: cmdCreateSnapshotsTopic,
cmdCleanUpTopic: cmdCleanUpTopic,
}
}
@ -60,6 +63,12 @@ func (c *TribeWatermillConsumer) Register(router *message.Router) {
c.subscriber,
c.createSnapshots,
)
router.AddNoPublisherHandler(
"TribeConsumer.cleanUp",
c.cmdCleanUpTopic,
c.subscriber,
c.cleanUp,
)
}
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)
}
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)
}