This repository has been archived on 2024-04-06. You can view files and clone it, but cannot push or open issues or pull requests.
core-old/internal/service/ennoblement.go
Dawid Wysokiński e9c0cb716e
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
refactor: ennoblements - sort only by createdAt
2022-12-30 09:53:28 +01:00

163 lines
4.5 KiB
Go

package service
import (
"context"
"errors"
"fmt"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"gitea.dwysokinski.me/twhelp/core/internal/tw"
)
const (
ennoblementChunkSize = 1000
ennoblementMaxLimit = 200
ennoblementSortMaxLen = 1
)
var (
errEnnoblementNotFound = errors.New("ennoblement not found")
)
//counterfeiter:generate -o internal/mock/ennoblement_repository.gen.go . EnnoblementRepository
type EnnoblementRepository interface {
Create(ctx context.Context, params ...domain.CreateEnnoblementParams) error
List(ctx context.Context, params domain.ListEnnoblementsParams) ([]domain.Ennoblement, error)
ListCountWithRelations(
ctx context.Context,
params domain.ListEnnoblementsParams,
) ([]domain.EnnoblementWithRelations, int64, error)
Delete(ctx context.Context, serverKey string, createdAtLTE time.Time) error
}
//counterfeiter:generate -o internal/mock/ennoblement_getter.gen.go . EnnoblementGetter
type EnnoblementGetter interface {
GetEnnoblements(ctx context.Context, baseURL string, since time.Time) ([]tw.Ennoblement, error)
}
type Ennoblement struct {
repo EnnoblementRepository
client EnnoblementGetter
}
func NewEnnoblement(repo EnnoblementRepository, client EnnoblementGetter) *Ennoblement {
return &Ennoblement{repo: repo, client: client}
}
func (e *Ennoblement) Refresh(ctx context.Context, key, url string) error {
latestEnnoblement, err := e.getLatestEnnoblement(ctx, key)
if err != nil && !errors.Is(err, errEnnoblementNotFound) {
return fmt.Errorf("EnnoblementService.getLatestEnnoblements: %w", err)
}
var since time.Time
if err == nil {
since = latestEnnoblement.CreatedAt
}
ennoblements, err := e.client.GetEnnoblements(ctx, url, since)
if err != nil {
return fmt.Errorf("TWClient.GetEnnoblements: %w", err)
}
for i := 0; i < len(ennoblements); i += ennoblementChunkSize {
end := i + ennoblementChunkSize
if end > len(ennoblements) {
end = len(ennoblements)
}
chunk := ennoblements[i:end]
params := make([]domain.CreateEnnoblementParams, 0, len(chunk))
for _, ennoblement := range chunk {
params = append(params, domain.CreateEnnoblementParams{
VillageID: ennoblement.VillageID,
NewOwnerID: ennoblement.NewOwnerID,
NewTribeID: ennoblement.NewTribeID,
OldOwnerID: ennoblement.OldOwnerID,
OldTribeID: ennoblement.OldTribeID,
Points: ennoblement.Points,
CreatedAt: ennoblement.CreatedAt,
ServerKey: key,
})
}
if err = e.repo.Create(ctx, params...); err != nil {
return fmt.Errorf("EnnoblementRepository.Create: %w", err)
}
}
return nil
}
func (e *Ennoblement) ListCountWithRelations(
ctx context.Context,
params domain.ListEnnoblementsParams,
) ([]domain.EnnoblementWithRelations, int64, error) {
if len(params.Sort) == 0 {
params.Sort = []domain.EnnoblementSort{
{
By: domain.EnnoblementSortByCreatedAt,
Direction: domain.SortDirectionASC,
},
}
}
if len(params.Sort) > ennoblementSortMaxLen {
return nil, 0, domain.ValidationError{
Field: "sort",
Err: domain.MaxLengthError{
Max: ennoblementSortMaxLen,
},
}
}
if params.Pagination.Limit == 0 {
params.Pagination.Limit = ennoblementMaxLimit
}
if err := validatePagination(params.Pagination, ennoblementMaxLimit); err != nil {
return nil, 0, fmt.Errorf("validatePagination: %w", err)
}
ennoblements, count, err := e.repo.ListCountWithRelations(ctx, params)
if err != nil {
return nil, 0, fmt.Errorf("EnnoblementRepository.List: %w", err)
}
return ennoblements, count, nil
}
func (e *Ennoblement) getLatestEnnoblement(ctx context.Context, key string) (domain.Ennoblement, error) {
ennoblements, err := e.repo.List(ctx, domain.ListEnnoblementsParams{
ServerKeys: []string{key},
Pagination: domain.Pagination{
Limit: 1,
},
Sort: []domain.EnnoblementSort{
{By: domain.EnnoblementSortByCreatedAt, Direction: domain.SortDirectionDESC},
},
})
if err != nil {
return domain.Ennoblement{}, fmt.Errorf("EnnoblementRepository.List: %w", err)
}
if len(ennoblements) == 0 {
return domain.Ennoblement{}, errEnnoblementNotFound
}
return ennoblements[0], nil
}
func (e *Ennoblement) CleanUp(ctx context.Context, srv domain.Server) error {
if srv.Special || srv.Open || srv.EnnoblementDataUpdatedAt.After(time.Now().Add(-30*24*time.Hour) /* 30 days */) {
return nil
}
// delete ennoblements older than 1 year
if err := e.repo.Delete(ctx, srv.Key, time.Now().Add(-365*24*time.Hour)); err != nil {
return fmt.Errorf("couldn't delete old ennoblements: %w", err)
}
return nil
}