119 lines
3.1 KiB
Go
119 lines
3.1 KiB
Go
|
package app
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"time"
|
||
|
|
||
|
"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
|
||
|
)
|
||
|
|
||
|
type EnnoblementRepository interface {
|
||
|
Create(ctx context.Context, params ...domain.CreateEnnoblementParams) error
|
||
|
List(ctx context.Context, params domain.ListEnnoblementsParams) (domain.Ennoblements, error)
|
||
|
}
|
||
|
|
||
|
type EnnoblementService struct {
|
||
|
repo EnnoblementRepository
|
||
|
twSvc TWService
|
||
|
pub EnnoblementPublisher
|
||
|
}
|
||
|
|
||
|
func NewEnnoblementService(repo EnnoblementRepository, twSvc TWService, pub EnnoblementPublisher) *EnnoblementService {
|
||
|
return &EnnoblementService{repo: repo, twSvc: twSvc, pub: pub}
|
||
|
}
|
||
|
|
||
|
func (svc *EnnoblementService) Sync(
|
||
|
ctx context.Context,
|
||
|
syncEnnoblementsCmdPayload domain.SyncEnnoblementsCmdPayload,
|
||
|
) error {
|
||
|
serverURL := syncEnnoblementsCmdPayload.ServerURL()
|
||
|
serverKey := syncEnnoblementsCmdPayload.ServerKey()
|
||
|
|
||
|
latestEnnoblement, err := svc.getLatestEnnoblement(ctx, serverKey)
|
||
|
if err != nil && !errors.Is(err, errEnnoblementNotFound) {
|
||
|
return fmt.Errorf("%s: %w", serverKey, err)
|
||
|
}
|
||
|
|
||
|
var since time.Time
|
||
|
if err == nil {
|
||
|
since = latestEnnoblement.CreatedAt()
|
||
|
}
|
||
|
|
||
|
ennoblements, err := svc.twSvc.GetEnnoblements(ctx, serverURL, since)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("%s: couldn't get ennoblements: %w", serverKey, err)
|
||
|
}
|
||
|
|
||
|
if err = svc.create(ctx, serverKey, ennoblements); err != nil {
|
||
|
return fmt.Errorf("%s: couldn't create ennoblements: %w", serverKey, err)
|
||
|
}
|
||
|
|
||
|
payload, err := domain.NewEnnoblementsSyncedEventPayload(
|
||
|
serverKey,
|
||
|
serverURL,
|
||
|
syncEnnoblementsCmdPayload.VersionCode(),
|
||
|
)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("%s: couldn't construct domain.EnnoblementsSyncedEventPayload %w", serverKey, err)
|
||
|
}
|
||
|
|
||
|
if err = svc.pub.EventSynced(ctx, payload); err != nil {
|
||
|
return fmt.Errorf("%s: %w", serverKey, err)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
var errEnnoblementNotFound = errors.New("ennoblement not found")
|
||
|
|
||
|
func (svc *EnnoblementService) getLatestEnnoblement(ctx context.Context, serverKey string) (domain.Ennoblement, error) {
|
||
|
params := domain.NewListEnnoblementsParams()
|
||
|
if err := params.SetLimit(1); err != nil {
|
||
|
return domain.Ennoblement{}, err
|
||
|
}
|
||
|
if err := params.SetServerKeys([]string{serverKey}); err != nil {
|
||
|
return domain.Ennoblement{}, err
|
||
|
}
|
||
|
if err := params.SetSort([]domain.EnnoblementSort{domain.EnnoblementSortCreatedAtDESC}); err != nil {
|
||
|
return domain.Ennoblement{}, err
|
||
|
}
|
||
|
|
||
|
ennoblements, err := svc.repo.List(ctx, params)
|
||
|
if err != nil {
|
||
|
return domain.Ennoblement{}, err
|
||
|
}
|
||
|
if len(ennoblements) == 0 {
|
||
|
return domain.Ennoblement{}, errEnnoblementNotFound
|
||
|
}
|
||
|
|
||
|
return ennoblements[0], nil
|
||
|
}
|
||
|
|
||
|
const ennoblementCreateChunkSize = 500
|
||
|
|
||
|
func (svc *EnnoblementService) create(
|
||
|
ctx context.Context,
|
||
|
serverKey string,
|
||
|
ennoblements domain.BaseEnnoblements,
|
||
|
) error {
|
||
|
for i := 0; i < len(ennoblements); i += ennoblementCreateChunkSize {
|
||
|
end := i + ennoblementCreateChunkSize
|
||
|
if end > len(ennoblements) {
|
||
|
end = len(ennoblements)
|
||
|
}
|
||
|
|
||
|
createParams, err := domain.NewCreateEnnoblementParams(serverKey, ennoblements[i:end])
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if err = svc.repo.Create(ctx, createParams...); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|