feat(TribeConsumer): update dominance (#31)
All checks were successful
continuous-integration/drone/push Build is passing

Reviewed-on: twhelp/core#31
This commit is contained in:
Dawid Wysokiński 2022-08-13 06:06:53 +00:00
parent b0bf482129
commit f246e205b4
6 changed files with 173 additions and 5 deletions

View File

@ -4,6 +4,9 @@ import (
"context"
"testing"
"github.com/stretchr/testify/require"
"github.com/uptrace/bun/dbfixture"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/jackc/pgerrcode"
@ -248,7 +251,7 @@ func TestServer_UpdateByKey(t *testing.T) {
db := newDB(t)
repo := bundb.NewServer(db)
fixture := loadFixtures(t, db)
server := fixture.MustRow("Server.de188").(*model.Server)
server := getServerFromFixture(t, fixture, "de188")
t.Run("OK", func(t *testing.T) {
t.Parallel()
@ -359,3 +362,12 @@ func concatStringSlices(slices ...[]string) []string {
}
return res
}
func getServerFromFixture(tb testing.TB, fixture *dbfixture.Fixture, id string) model.Server {
tb.Helper()
v, err := fixture.Row("Server." + id)
require.NoError(tb, err)
s, ok := v.(*model.Server)
require.True(tb, ok)
return *s
}

View File

@ -11,6 +11,13 @@ import (
"github.com/uptrace/bun"
)
var (
ErrNumPlayerVillagesGTE = domain.NewError(
domain.WithCode(domain.ErrorCodeValidationError),
domain.WithMessage("numPlayerVillages must be greater than or equal to 0"),
)
)
type Tribe struct {
db *bun.DB
}
@ -72,6 +79,27 @@ func (t *Tribe) List(ctx context.Context, params domain.ListTribesParams) ([]dom
return result, int64(count), nil
}
func (t *Tribe) UpdateDominance(ctx context.Context, serverKey string, numPlayerVillages int64) error {
if numPlayerVillages < 0 {
return ErrNumPlayerVillagesGTE
}
q := t.db.NewUpdate().
Model(&model.Tribe{}).
Returning("NULL").
Where("server_key = ?", serverKey)
if numPlayerVillages > 0 {
q = q.Set("dominance = num_villages::double precision / ? * 100", numPlayerVillages)
} else {
q = q.Set("dominance = 0")
}
if _, err := q.Exec(ctx); err != nil {
return fmt.Errorf("couldn't update dominance (server=%s): %w", serverKey, err)
}
return nil
}
type listTribesParamsApplier struct {
params domain.ListTribesParams
}

View File

@ -270,6 +270,67 @@ func TestTribe_List(t *testing.T) {
}
}
func TestTribe_UpdateDominance(t *testing.T) {
t.Parallel()
db := newDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewTribe(db)
serverDE188 := getServerFromFixture(t, fixture, "de188")
serverPL169 := getServerFromFixture(t, fixture, "pl169")
t.Run("OK", func(t *testing.T) {
t.Parallel()
tests := []struct {
name string
serverKey string
numPlayerVillages int64
}{
{
name: "numPlayerVillages=0",
serverKey: serverDE188.Key,
numPlayerVillages: 0,
},
{
name: "numPlayerVillages=35000",
serverKey: serverPL169.Key,
numPlayerVillages: 35000,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
require.NoError(t, repo.UpdateDominance(context.Background(), tt.serverKey, tt.numPlayerVillages))
tribes, _, err := repo.List(
context.Background(),
domain.ListTribesParams{ServerKeys: []string{tt.serverKey}},
)
assert.NoError(t, err)
assert.Greater(t, len(tribes), 0)
for _, tribe := range tribes {
if tt.numPlayerVillages == 0 {
assert.Equal(t, 0.0, tribe.Dominance)
continue
}
assert.Equal(t, float64(tribe.NumVillages)/float64(tt.numPlayerVillages)*100, tribe.Dominance)
}
})
}
})
t.Run("ERR: numPlayerVillages < 0", func(t *testing.T) {
t.Parallel()
err := repo.UpdateDominance(context.Background(), serverDE188.Key, -1)
assert.ErrorIs(t, err, bundb.ErrNumPlayerVillagesGTE)
})
}
func assertCreatedTribes(tb testing.TB, params []domain.CreateTribeParams, tribes []domain.Tribe) {
tb.Helper()

View File

@ -5,13 +5,13 @@ import (
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/ThreeDotsLabs/watermill/message"
)
//counterfeiter:generate -o internal/mock/tribe_service.gen.go . TribeService
type TribeService interface {
Refresh(ctx context.Context, key, url string) (int64, error)
UpdateDominance(ctx context.Context, serverKey string, numPlayerVillages int64) error
}
type TribeConsumer struct {
@ -83,6 +83,15 @@ func (t *TribeConsumer) refresh(msg *message.Message) ([]*message.Message, error
}
func (t *TribeConsumer) updateDominance(msg *message.Message) error {
// TODO: implement this method
var payload domain.EventVillagesRefreshedPayload
if err := t.marshaler.Unmarshal(msg, &payload); err != nil {
// drop message with invalid payload
return nil
}
if err := t.svc.UpdateDominance(msg.Context(), payload.Key, payload.NumPlayerVillages); err != nil {
return fmt.Errorf("TribeService.UpdateDominance: %w", err)
}
return nil
}

View File

@ -94,3 +94,58 @@ func TestTribeConsumer_refresh(t *testing.T) {
assert.Equal(t, 0, tribeSvc.RefreshCallCount())
})
}
func TestTribeConsumer_updateDominance(t *testing.T) {
t.Parallel()
marshaler := msg.GobMarshaler{}
pubSub := newPubSub(t)
tribeSvc := &mock.FakeTribeService{}
tribeSvc.UpdateDominanceReturns(nil)
wait := make(chan struct{})
runRouter(
t,
middlewareRegisterer{
h: func(h message.HandlerFunc) message.HandlerFunc {
return func(msg *message.Message) ([]*message.Message, error) {
if message.HandlerNameFromCtx(msg.Context()) != "TribeConsumer.updateDominance" {
return h(msg)
}
result, err := h(msg)
if len(result) == 0 && err == nil {
close(wait)
}
return result, err
}
},
},
msg.NewTribeConsumer(marshaler, pubSub, pubSub, tribeSvc),
)
payload := domain.EventVillagesRefreshedPayload{
Key: "pl151",
URL: "https://pl151.plemiona.pl",
VersionCode: "pl",
NumVillages: 1500,
NumPlayerVillages: 1400,
NumBarbarianVillages: 100,
NumBonusVillages: 300,
}
ev, err := marshaler.Marshal(payload)
require.NoError(t, err)
require.NoError(t, pubSub.Publish("villages.event.refreshed", ev))
select {
case <-wait:
case <-time.After(time.Second):
t.Fatal("timeout")
}
require.Equal(t, 1, tribeSvc.UpdateDominanceCallCount())
_, serverKey, numPlayerVillages := tribeSvc.UpdateDominanceArgsForCall(0)
assert.Equal(t, payload.Key, serverKey)
assert.Equal(t, payload.NumPlayerVillages, numPlayerVillages)
}

View File

@ -9,6 +9,7 @@ import (
type TribeRepository interface {
CreateOrUpdate(ctx context.Context, params ...domain.CreateTribeParams) error
UpdateDominance(ctx context.Context, serverKey string, numVillages int64) error
}
type TribesGetter interface {
@ -45,7 +46,9 @@ func (t *Tribe) Refresh(ctx context.Context, key, url string) (int64, error) {
return int64(len(tribes)), nil
}
func (t *Tribe) UpdateDominance(ctx context.Context, key string, numVillages int64) error {
// TODO: implement this method
func (t *Tribe) UpdateDominance(ctx context.Context, serverKey string, numPlayerVillages int64) error {
if err := t.repo.UpdateDominance(ctx, serverKey, numPlayerVillages); err != nil {
return fmt.Errorf("TribeRepository.UpdateDominance: %w", err)
}
return nil
}