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/village.go
Dawid Wysokiński 767eb5d5f2
All checks were successful
continuous-integration/drone/push Build is passing
refactor: optimize queries and models (#107)
Reviewed-on: twhelp/core#107
2022-10-21 05:19:04 +00:00

159 lines
4.3 KiB
Go

package service
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"gitea.dwysokinski.me/twhelp/core/internal/tw"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
)
const (
villageChunkSize = 1000
villageMaxLimit = 500
)
//counterfeiter:generate -o internal/mock/village_repository.gen.go . VillageRepository
type VillageRepository interface {
CreateOrUpdate(ctx context.Context, params ...domain.CreateVillageParams) error
List(ctx context.Context, params domain.ListVillagesParams) ([]domain.VillageWithRelations, int64, error)
}
//counterfeiter:generate -o internal/mock/village_getter.gen.go . VillageGetter
type VillageGetter interface {
GetVillages(ctx context.Context, baseURL string) ([]tw.Village, error)
}
type Village struct {
repo VillageRepository
client VillageGetter
}
func NewVillage(repo VillageRepository, client VillageGetter) *Village {
return &Village{repo: repo, client: client}
}
func (v *Village) Refresh(ctx context.Context, key, url string) (domain.RefreshVillagesResult, error) {
ctx, span := tracer.Start(ctx, "Village.Refresh", trace.WithAttributes(
attribute.String("server.key", key),
attribute.String("server.url", url),
))
defer span.End()
villages, err := v.client.GetVillages(ctx, url)
if err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return domain.RefreshVillagesResult{}, fmt.Errorf("TWClient.GetVillages: %w", err)
}
res := domain.RefreshVillagesResult{
NumVillages: int64(len(villages)),
}
for i := 0; i < len(villages); i += villageChunkSize {
end := i + villageChunkSize
if end > len(villages) {
end = len(villages)
}
chunk := villages[i:end]
params := make([]domain.CreateVillageParams, 0, len(chunk))
for _, village := range chunk {
params = append(params, domain.CreateVillageParams{
ID: village.ID,
Name: village.Name,
Points: village.Points,
X: village.X,
Y: village.Y,
Continent: village.Continent,
Bonus: village.Bonus,
PlayerID: village.PlayerID,
ProfileURL: village.ProfileURL,
ServerKey: key,
})
if village.PlayerID > 0 {
res.NumPlayerVillages++
} else {
res.NumBarbarianVillages++
}
if village.Bonus > 0 {
res.NumBonusVillages++
}
}
if err := v.repo.CreateOrUpdate(ctx, params...); err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return domain.RefreshVillagesResult{}, fmt.Errorf("VillageRepository.CreateOrUpdate: %w", err)
}
}
return res, nil
}
func (v *Village) List(ctx context.Context, params domain.ListVillagesParams) ([]domain.VillageWithRelations, int64, error) {
ctx, span := tracer.Start(ctx, "Village.List")
defer span.End()
if params.Pagination.Limit == 0 {
params.Pagination.Limit = villageMaxLimit
}
if err := validatePagination(params.Pagination, villageMaxLimit); err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return nil, 0, fmt.Errorf("validatePagination: %w", err)
}
villages, count, err := v.repo.List(ctx, params)
if err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return nil, 0, fmt.Errorf("VillageRepository.List: %w", err)
}
return villages, count, nil
}
func (v *Village) GetByServerKeyAndID(
ctx context.Context,
serverKey string,
id int64,
includePlayer, includePlayerTribe bool,
) (domain.VillageWithRelations, error) {
ctx, span := tracer.Start(ctx, "Village.GetByServerKeyAndID", trace.WithAttributes(
attribute.String("server.key", serverKey),
attribute.Int64("village.id", id),
))
defer span.End()
villages, _, err := v.repo.List(ctx, domain.ListVillagesParams{
IDs: []int64{id},
ServerKeys: []string{serverKey},
IncludePlayer: includePlayer,
IncludePlayerTribe: includePlayerTribe,
Pagination: domain.Pagination{
Limit: 1,
},
})
if err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return domain.VillageWithRelations{}, fmt.Errorf("VillageRepository.List: %w", err)
}
if len(villages) == 0 {
err = domain.VillageNotFoundError{
ID: id,
}
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
return domain.VillageWithRelations{}, err
}
return villages[0], nil
}