core/internal/app/service_player_snapshot.go

124 lines
3.2 KiB
Go

package app
import (
"context"
"fmt"
"time"
"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
)
type PlayerSnapshotRepository interface {
// Create persists player snapshots in a store (e.g. Postgres).
// Duplicates are ignored.
Create(ctx context.Context, params ...domain.CreatePlayerSnapshotParams) error
ListWithRelations(
ctx context.Context,
params domain.ListPlayerSnapshotsParams,
) (domain.ListPlayerSnapshotsWithRelationsResult, error)
Delete(ctx context.Context, serverKey string, dateLTE time.Time) error
}
type PlayerSnapshotService struct {
repo PlayerSnapshotRepository
playerSvc *PlayerService
pub SnapshotPublisher
}
func NewPlayerSnapshotService(
repo PlayerSnapshotRepository,
playerSvc *PlayerService,
pub SnapshotPublisher,
) *PlayerSnapshotService {
return &PlayerSnapshotService{repo: repo, playerSvc: playerSvc, pub: pub}
}
//nolint:gocyclo
func (svc *PlayerSnapshotService) Create(
ctx context.Context,
createSnapshotsCmdPayload domain.CreateSnapshotsCmdPayload,
) error {
serverKey := createSnapshotsCmdPayload.ServerKey()
date := createSnapshotsCmdPayload.Date()
listPlayersParams := domain.NewListPlayersParams()
if err := listPlayersParams.SetServerKeys([]string{serverKey}); err != nil {
return fmt.Errorf("%s: %w", serverKey, err)
}
if err := listPlayersParams.SetDeleted(domain.NullBool{
V: false,
Valid: true,
}); err != nil {
return fmt.Errorf("%s: %w", serverKey, err)
}
if err := listPlayersParams.SetSort([]domain.PlayerSort{domain.PlayerSortIDASC}); err != nil {
return fmt.Errorf("%s: %w", serverKey, err)
}
if err := listPlayersParams.SetLimit(domain.PlayerListMaxLimit); err != nil {
return fmt.Errorf("%s: %w", serverKey, err)
}
for {
res, err := svc.playerSvc.List(ctx, listPlayersParams)
if err != nil {
return fmt.Errorf("%s: %w", serverKey, err)
}
players := res.Players()
if len(players) == 0 {
break
}
params, err := domain.NewCreatePlayerSnapshotParams(players, date)
if err != nil {
return fmt.Errorf("%s: %w", serverKey, err)
}
if err = svc.repo.Create(ctx, params...); err != nil {
return fmt.Errorf("%s: %w", serverKey, err)
}
if res.Next().IsZero() {
break
}
if err = listPlayersParams.SetCursor(res.Next()); err != nil {
return fmt.Errorf("%s: %w", serverKey, err)
}
}
payload, err := domain.NewSnapshotsCreatedEventPayload(serverKey, createSnapshotsCmdPayload.VersionCode())
if err != nil {
return fmt.Errorf("%s: couldn't construct domain.SnapshotsCreatedEventPayload: %w", serverKey, err)
}
if err = svc.pub.EventCreated(ctx, payload); err != nil {
return fmt.Errorf("%s: %w", serverKey, err)
}
return nil
}
func (svc *PlayerSnapshotService) ListWithRelations(
ctx context.Context,
params domain.ListPlayerSnapshotsParams,
) (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
}