core/internal/app/service_village.go

133 lines
3.5 KiB
Go

package app
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
)
type VillageRepository interface {
CreateOrUpdate(ctx context.Context, params ...domain.CreateVillageParams) error
List(ctx context.Context, params domain.ListVillagesParams) (domain.ListVillagesResult, error)
ListWithRelations(
ctx context.Context,
params domain.ListVillagesParams,
) (domain.ListVillagesWithRelationsResult, error)
Delete(ctx context.Context, serverKey string, ids ...int) error
}
type VillageService struct {
repo VillageRepository
twSvc TWService
pub VillagePublisher
}
func NewVillageService(repo VillageRepository, twSvc TWService, pub VillagePublisher) *VillageService {
return &VillageService{repo: repo, twSvc: twSvc, pub: pub}
}
func (svc *VillageService) Sync(ctx context.Context, serverSyncedPayload domain.ServerSyncedEventPayload) error {
serverKey := serverSyncedPayload.Key()
serverURL := serverSyncedPayload.URL()
villages, err := svc.twSvc.GetVillages(ctx, serverURL)
if err != nil {
return fmt.Errorf("%s: couldn't get villages: %w", serverKey, err)
}
if err = svc.createOrUpdate(ctx, serverKey, villages); err != nil {
return fmt.Errorf("%s: couldn't create/update villages: %w", serverKey, err)
}
if err = svc.delete(ctx, serverKey, villages); err != nil {
return fmt.Errorf("%s: couldn't delete villages: %w", serverKey, err)
}
villagesSyncedPayload, err := domain.NewVillagesSyncedEventPayloadFromVillages(
serverKey,
serverURL,
serverSyncedPayload.VersionCode(),
villages,
)
if err != nil {
return fmt.Errorf("%s: couldn't construct domain.PlayersSyncedEventPayload: %w", serverKey, err)
}
if err = svc.pub.EventSynced(ctx, villagesSyncedPayload); err != nil {
return fmt.Errorf("%s: %w", serverKey, err)
}
return nil
}
const villageCreateOrUpdateChunkSize = domain.VillageListMaxLimit
func (svc *VillageService) createOrUpdate(ctx context.Context, serverKey string, villages domain.BaseVillages) error {
for i := 0; i < len(villages); i += villageCreateOrUpdateChunkSize {
end := i + villageCreateOrUpdateChunkSize
if end > len(villages) {
end = len(villages)
}
createParams, err := domain.NewCreateVillageParams(serverKey, villages[i:end])
if err != nil {
return err
}
if err = svc.repo.CreateOrUpdate(ctx, createParams...); err != nil {
return err
}
}
return nil
}
func (svc *VillageService) delete(ctx context.Context, serverKey string, villages domain.BaseVillages) error {
listParams := domain.NewListVillagesParams()
if err := listParams.SetServerKeys([]string{serverKey}); err != nil {
return err
}
if err := listParams.SetSort([]domain.VillageSort{domain.VillageSortIDASC}); err != nil {
return err
}
if err := listParams.SetLimit(domain.VillageListMaxLimit); err != nil {
return err
}
var toDelete []int
for {
res, err := svc.repo.List(ctx, listParams)
if err != nil {
return err
}
toDelete = append(toDelete, res.Villages().Delete(serverKey, villages)...)
if res.Next().IsZero() {
break
}
if err = listParams.SetCursor(res.Next()); err != nil {
return err
}
}
return svc.repo.Delete(ctx, serverKey, toDelete...)
}
func (svc *VillageService) List(
ctx context.Context,
params domain.ListVillagesParams,
) (domain.ListVillagesResult, error) {
return svc.repo.List(ctx, params)
}
func (svc *VillageService) ListWithRelations(
ctx context.Context,
params domain.ListVillagesParams,
) (domain.ListVillagesWithRelationsResult, error) {
return svc.repo.ListWithRelations(ctx, params)
}