refactor: introduce adapters
All checks were successful
continuous-integration/drone/pr Build is passing

This commit is contained in:
Dawid Wysokiński 2023-07-17 07:31:24 +02:00
parent 46563024e9
commit ace0b78bc0
Signed by: Kichiyaki
GPG Key ID: B5445E357FB8B892
61 changed files with 783 additions and 680 deletions

View File

@ -9,7 +9,7 @@ import (
"gitea.dwysokinski.me/twhelp/core/internal/msg"
"gitea.dwysokinski.me/twhelp/core/cmd/twhelp/internal"
"gitea.dwysokinski.me/twhelp/core/internal/bundb"
"gitea.dwysokinski.me/twhelp/core/internal/adapter"
"gitea.dwysokinski.me/twhelp/core/internal/service"
"github.com/ThreeDotsLabs/watermill"
"github.com/ThreeDotsLabs/watermill-amqp/v2/pkg/amqp"
@ -61,7 +61,7 @@ func newServerCommand() *cli.Command {
marshaler msg.CommandEventMarshaler,
bunDB *bun.DB,
) error {
svc := service.NewServer(bundb.NewServer(bunDB), internal.NewTWClient(c.App.Version))
svc := service.NewServer(adapter.NewServerBun(bunDB), internal.NewTWClient(c.App.Version))
msg.NewServerConsumer(marshaler, publisher, subscriber, logger, svc).Register(router)
return nil
},
@ -86,8 +86,8 @@ func newTribeCommand() *cli.Command {
marshaler msg.CommandEventMarshaler,
bunDB *bun.DB,
) error {
svc := service.NewTribe(bundb.NewTribe(bunDB), internal.NewTWClient(c.App.Version))
snapshotSvc := service.NewTribeSnapshot(bundb.NewTribeSnapshot(bunDB), svc)
svc := service.NewTribe(adapter.NewTribeBun(bunDB), internal.NewTWClient(c.App.Version))
snapshotSvc := service.NewTribeSnapshot(adapter.NewTribeSnapshotBun(bunDB), svc)
msg.NewTribeConsumer(
marshaler,
publisher,
@ -119,9 +119,9 @@ func newPlayerCommand() *cli.Command {
marshaler msg.CommandEventMarshaler,
bunDB *bun.DB,
) error {
tribeChangeSvc := service.NewTribeChange(bundb.NewTribeChange(bunDB))
svc := service.NewPlayer(bundb.NewPlayer(bunDB), tribeChangeSvc, internal.NewTWClient(c.App.Version))
snapshotSvc := service.NewPlayerSnapshot(bundb.NewPlayerSnapshot(bunDB), svc)
tribeChangeSvc := service.NewTribeChange(adapter.NewTribeChangeBun(bunDB))
svc := service.NewPlayer(adapter.NewPlayerBun(bunDB), tribeChangeSvc, internal.NewTWClient(c.App.Version))
snapshotSvc := service.NewPlayerSnapshot(adapter.NewPlayerSnapshotBun(bunDB), svc)
msg.NewPlayerConsumer(
marshaler,
publisher,
@ -153,7 +153,7 @@ func newVillageCommand() *cli.Command {
marshaler msg.CommandEventMarshaler,
bunDB *bun.DB,
) error {
svc := service.NewVillage(bundb.NewVillage(bunDB), internal.NewTWClient(c.App.Version))
svc := service.NewVillage(adapter.NewVillageBun(bunDB), internal.NewTWClient(c.App.Version))
msg.NewVillageConsumer(marshaler, publisher, subscriber, logger, svc).Register(router)
return nil
},
@ -178,7 +178,7 @@ func newEnnoblementCommand() *cli.Command {
marshaler msg.CommandEventMarshaler,
bunDB *bun.DB,
) error {
svc := service.NewEnnoblement(bundb.NewEnnoblement(bunDB), internal.NewTWClient(c.App.Version))
svc := service.NewEnnoblement(adapter.NewEnnoblementBun(bunDB), internal.NewTWClient(c.App.Version))
msg.NewEnnoblementConsumer(marshaler, publisher, subscriber, logger, svc).Register(router)
return nil
},

View File

@ -8,7 +8,7 @@ import (
"gitea.dwysokinski.me/twhelp/core/internal/msg"
"gitea.dwysokinski.me/twhelp/core/cmd/twhelp/internal"
"gitea.dwysokinski.me/twhelp/core/internal/bundb"
"gitea.dwysokinski.me/twhelp/core/internal/adapter"
"gitea.dwysokinski.me/twhelp/core/internal/service"
"github.com/garsue/watermillzap"
"github.com/urfave/cli/v2"
@ -151,14 +151,14 @@ func runJob(c *cli.Context, timeout time.Duration, f runJobFunc) error {
client := internal.NewTWClient(c.App.Version)
versionSvc := service.NewVersion(bundb.NewVersion(db))
serverSvc := service.NewServer(bundb.NewServer(db), client)
tribeChangeSvc := service.NewTribeChange(bundb.NewTribeChange(db))
tribeSvc := service.NewTribe(bundb.NewTribe(db), client)
tribeSnapshotSvc := service.NewTribeSnapshot(bundb.NewTribeSnapshot(db), tribeSvc)
playerSvc := service.NewPlayer(bundb.NewPlayer(db), tribeChangeSvc, client)
playerSnapshotSvc := service.NewPlayerSnapshot(bundb.NewPlayerSnapshot(db), playerSvc)
ennoblementSvc := service.NewEnnoblement(bundb.NewEnnoblement(db), client)
versionSvc := service.NewVersion(adapter.NewVersionBun(db))
serverSvc := service.NewServer(adapter.NewServerBun(db), client)
tribeChangeSvc := service.NewTribeChange(adapter.NewTribeChangeBun(db))
tribeSvc := service.NewTribe(adapter.NewTribeBun(db), client)
tribeSnapshotSvc := service.NewTribeSnapshot(adapter.NewTribeSnapshotBun(db), tribeSvc)
playerSvc := service.NewPlayer(adapter.NewPlayerBun(db), tribeChangeSvc, client)
playerSnapshotSvc := service.NewPlayerSnapshot(adapter.NewPlayerSnapshotBun(db), playerSvc)
ennoblementSvc := service.NewEnnoblement(adapter.NewEnnoblementBun(db), client)
return f(ctx, service.NewJob(
versionSvc,

View File

@ -15,7 +15,7 @@ import (
"github.com/kelseyhightower/envconfig"
"github.com/realclientip/realclientip-go"
"gitea.dwysokinski.me/twhelp/core/internal/bundb"
"gitea.dwysokinski.me/twhelp/core/internal/adapter"
"gitea.dwysokinski.me/twhelp/core/internal/service"
"github.com/uptrace/bun"
@ -84,15 +84,15 @@ func newServer(appVersion string, logger *zap.Logger, db *bun.DB) (*http.Server,
client := internal.NewTWClient(appVersion)
// repos
versionRepo := bundb.NewVersion(db)
serverRepo := bundb.NewServer(db)
tribeRepo := bundb.NewTribe(db)
playerRepo := bundb.NewPlayer(db)
villageRepo := bundb.NewVillage(db)
ennoblementRepo := bundb.NewEnnoblement(db)
tribeChangeRepo := bundb.NewTribeChange(db)
playerSnapshotRepo := bundb.NewPlayerSnapshot(db)
tribeSnapshotRepo := bundb.NewTribeSnapshot(db)
versionRepo := adapter.NewVersionBun(db)
serverRepo := adapter.NewServerBun(db)
tribeRepo := adapter.NewTribeBun(db)
playerRepo := adapter.NewPlayerBun(db)
villageRepo := adapter.NewVillageBun(db)
ennoblementRepo := adapter.NewEnnoblementBun(db)
tribeChangeRepo := adapter.NewTribeChangeBun(db)
playerSnapshotRepo := adapter.NewPlayerSnapshotBun(db)
tribeSnapshotRepo := adapter.NewTribeSnapshotBun(db)
// services
versionSvc := service.NewVersion(versionRepo)
@ -131,7 +131,7 @@ func newServer(appVersion string, logger *zap.Logger, db *bun.DB) (*http.Server,
Schemes: apiCfg.SwaggerSchemes,
}),
))
r.Mount(metaPrefix, meta.New(bundb.NewChecker(db)))
r.Mount(metaPrefix, meta.New(adapter.NewCheckerBun(db)))
return &http.Server{
Addr: ":" + defaultPort,

View File

@ -0,0 +1,77 @@
package adapter_test
import (
"flag"
"log"
"net/url"
"os"
"testing"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/bundbtest"
"github.com/ory/dockertest/v3"
"github.com/pressly/goose/v3"
"github.com/uptrace/bun"
)
var (
dbDSN = os.Getenv("TESTS_DB_DSN")
)
func TestMain(m *testing.M) {
setUpGoose()
// https://github.com/golang/go/blob/7cfa7d69259590319524c3715df4a39b39924bc3/src/testing/testing.go#L224
flag.Parse()
if dbDSN != "" || testing.Short() {
os.Exit(m.Run())
}
pool, err := dockertest.NewPool("")
if err != nil {
log.Fatalf("couldn't construct pool: %s", err)
}
pool.MaxWait = 30 * time.Second
if err = pool.Client.Ping(); err != nil {
log.Fatalf("couldn't connect to Docker: %s", err)
}
var resources []*dockertest.Resource
if dbDSN == "" {
resource, dsn := newPostgres(pool)
dbDSN = dsn.String()
resources = append(resources, resource)
}
code := m.Run()
for _, r := range resources {
_ = pool.Purge(r)
}
os.Exit(code)
}
func setUpGoose() {
goose.SetBaseFS(os.DirFS("../../migrations"))
goose.SetLogger(goose.NopLogger())
if err := goose.SetDialect("postgres"); err != nil {
log.Fatal(err)
}
}
func newPostgres(pool *dockertest.Pool) (*dockertest.Resource, *url.URL) {
resource, dsn, err := bundbtest.NewPostgres(pool, 240)
if err != nil {
log.Fatal(err)
}
return resource, dsn
}
func newBunDB(tb testing.TB) *bun.DB {
tb.Helper()
return bundbtest.NewDB(tb, dbDSN)
}

View File

@ -1,4 +1,4 @@
package bundb
package adapter
import (
"context"

View File

@ -0,0 +1,23 @@
package adapter
import (
"context"
"github.com/uptrace/bun"
)
type CheckerBun struct {
db *bun.DB
}
func NewCheckerBun(db *bun.DB) *CheckerBun {
return &CheckerBun{db: db}
}
func (c *CheckerBun) Name() string {
return "db:ping"
}
func (c *CheckerBun) Check(ctx context.Context) error {
return c.db.PingContext(ctx)
}

View File

@ -0,0 +1,25 @@
package adapter_test
import (
"context"
"testing"
"gitea.dwysokinski.me/twhelp/core/internal/adapter"
"github.com/stretchr/testify/assert"
)
func TestChecker_Name(t *testing.T) {
t.Parallel()
assert.Equal(t, "db:ping", adapter.NewCheckerBun(nil).Name())
}
func TestChecker_Check(t *testing.T) {
t.Parallel()
if testing.Short() {
t.Skip("skipping long-running test")
}
assert.NoError(t, adapter.NewCheckerBun(newBunDB(t)).Check(context.Background()))
}

View File

@ -1,4 +1,4 @@
package bundb
package adapter
import (
"context"
@ -7,7 +7,7 @@ import (
"fmt"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/uptrace/bun"
)
@ -16,22 +16,22 @@ var (
ennoblementOrders = []string{"ennoblement.server_key ASC"}
)
type Ennoblement struct {
type EnnoblementBun struct {
db *bun.DB
}
func NewEnnoblement(db *bun.DB) *Ennoblement {
return &Ennoblement{db: db}
func NewEnnoblementBun(db *bun.DB) *EnnoblementBun {
return &EnnoblementBun{db: db}
}
func (e *Ennoblement) Create(ctx context.Context, params ...domain.CreateEnnoblementParams) error {
func (e *EnnoblementBun) Create(ctx context.Context, params ...domain.CreateEnnoblementParams) error {
if len(params) == 0 {
return nil
}
ennoblements := make([]model.Ennoblement, 0, len(params))
ennoblements := make([]bunmodel.Ennoblement, 0, len(params))
for _, p := range params {
ennoblements = append(ennoblements, model.NewEnnoblement(p))
ennoblements = append(ennoblements, bunmodel.NewEnnoblement(p))
}
if _, err := e.db.NewInsert().
Model(&ennoblements).
@ -44,8 +44,8 @@ func (e *Ennoblement) Create(ctx context.Context, params ...domain.CreateEnnoble
return nil
}
func (e *Ennoblement) List(ctx context.Context, params domain.ListEnnoblementsParams) ([]domain.Ennoblement, error) {
var ennoblements []model.Ennoblement
func (e *EnnoblementBun) List(ctx context.Context, params domain.ListEnnoblementsParams) ([]domain.Ennoblement, error) {
var ennoblements []bunmodel.Ennoblement
if err := e.db.NewSelect().
Model(&ennoblements).
@ -63,23 +63,23 @@ func (e *Ennoblement) List(ctx context.Context, params domain.ListEnnoblementsPa
return result, nil
}
func (e *Ennoblement) ListCountWithRelations(
func (e *EnnoblementBun) ListCountWithRelations(
ctx context.Context,
params domain.ListEnnoblementsParams,
) ([]domain.EnnoblementWithRelations, int64, error) {
var ennoblements []model.Ennoblement
var ennoblements []bunmodel.Ennoblement
paramsApplier := listEnnoblementsParamsApplier{params}
cntQ := e.db.NewSelect().
Model(&model.Ennoblement{}).
Model(&bunmodel.Ennoblement{}).
Apply(paramsApplier.applyFilters)
q := e.db.NewSelect().
Model(&ennoblements).
Where("ennoblement.id IN (?)", e.db.NewSelect().
Column("id").
Model(&model.Ennoblement{}).
Model(&bunmodel.Ennoblement{}).
Order(ennoblementOrders...).
Apply(paramsApplier.apply)).
Order(ennoblementOrders...).
@ -113,9 +113,9 @@ func (e *Ennoblement) ListCountWithRelations(
return result, int64(count), nil
}
func (e *Ennoblement) Delete(ctx context.Context, serverKey string, createdAtLTE time.Time) error {
func (e *EnnoblementBun) Delete(ctx context.Context, serverKey string, createdAtLTE time.Time) error {
if _, err := e.db.NewDelete().
Model(&model.Ennoblement{}).
Model(&bunmodel.Ennoblement{}).
Where("server_key = ?", serverKey).
Where("created_at <= ?", createdAtLTE).
Returning("NULL").

View File

@ -1,4 +1,4 @@
package bundb_test
package adapter_test
import (
"context"
@ -9,10 +9,9 @@ import (
"github.com/google/go-cmp/cmp"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/bundbtest"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"gitea.dwysokinski.me/twhelp/core/internal/bundb"
"gitea.dwysokinski.me/twhelp/core/internal/adapter"
"github.com/stretchr/testify/assert"
)
@ -23,9 +22,9 @@ func TestEnnoblement_Create(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewEnnoblement(db)
repo := adapter.NewEnnoblementBun(db)
t.Run("OK", func(t *testing.T) {
t.Parallel()
@ -150,9 +149,9 @@ func TestEnnoblement_List(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewEnnoblement(db)
repo := adapter.NewEnnoblementBun(db)
ennoblements := fixture.Ennoblements(t)
type expectedEnnoblement struct {
@ -481,9 +480,9 @@ func TestEnnoblement_Delete(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewEnnoblement(db)
repo := adapter.NewEnnoblementBun(db)
ennoblementsBeforeDelete, err := repo.List(context.Background(), domain.ListEnnoblementsParams{})
assert.NoError(t, err)

View File

@ -1,11 +1,11 @@
package bundb_test
package adapter_test
import (
"context"
"os"
"testing"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/bundbtest"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/bundbtest"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/stretchr/testify/require"
"github.com/uptrace/bun"
@ -19,8 +19,10 @@ func loadFixtures(tb testing.TB, bunDB *bun.DB) *bunfixture {
tb.Helper()
fixture := bundbtest.NewFixture(bunDB)
err := fixture.Load(context.Background(), os.DirFS("testdata"), "fixture.yml")
require.NoError(tb, err, "couldn't load fixtures")
return &bunfixture{fixture}
}

View File

@ -1,4 +1,4 @@
package bundb
package adapter
import (
"context"
@ -7,7 +7,7 @@ import (
"fmt"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/uptrace/bun"
)
@ -17,22 +17,22 @@ var (
playerOrders = []string{"player.server_key ASC"}
)
type Player struct {
type PlayerBun struct {
db *bun.DB
}
func NewPlayer(db *bun.DB) *Player {
return &Player{db: db}
func NewPlayerBun(db *bun.DB) *PlayerBun {
return &PlayerBun{db: db}
}
func (p *Player) CreateOrUpdate(ctx context.Context, params ...domain.CreatePlayerParams) error {
func (p *PlayerBun) CreateOrUpdate(ctx context.Context, params ...domain.CreatePlayerParams) error {
if len(params) == 0 {
return nil
}
players := make([]model.Player, 0, len(params))
players := make([]bunmodel.Player, 0, len(params))
for _, param := range params {
players = append(players, model.NewPlayer(param))
players = append(players, bunmodel.NewPlayer(param))
}
if _, err := p.db.NewInsert().
Model(&players).
@ -60,13 +60,13 @@ func (p *Player) CreateOrUpdate(ctx context.Context, params ...domain.CreatePlay
return nil
}
func (p *Player) Delete(ctx context.Context, serverKey string, ids ...int64) error {
func (p *PlayerBun) Delete(ctx context.Context, serverKey string, ids ...int64) error {
if len(ids) == 0 {
return nil
}
if _, err := p.db.NewUpdate().
Model(&model.Player{}).
Model(&bunmodel.Player{}).
Where("deleted_at IS NULL").
Where("id IN (?)", bun.In(ids)).
Where("server_key = ?", serverKey).
@ -80,8 +80,8 @@ func (p *Player) Delete(ctx context.Context, serverKey string, ids ...int64) err
return nil
}
func (p *Player) List(ctx context.Context, params domain.ListPlayersParams) ([]domain.Player, error) {
var players []model.Player
func (p *PlayerBun) List(ctx context.Context, params domain.ListPlayersParams) ([]domain.Player, error) {
var players []bunmodel.Player
if err := p.db.NewSelect().
Model(&players).
@ -99,19 +99,19 @@ func (p *Player) List(ctx context.Context, params domain.ListPlayersParams) ([]d
return result, nil
}
func (p *Player) ListCountWithRelations(ctx context.Context, params domain.ListPlayersParams) ([]domain.PlayerWithRelations, int64, error) {
var players []model.Player
func (p *PlayerBun) ListCountWithRelations(ctx context.Context, params domain.ListPlayersParams) ([]domain.PlayerWithRelations, int64, error) {
var players []bunmodel.Player
paramsApplier := listPlayersParamsApplier{params}
subQ := p.db.NewSelect().
Column("id", "server_key").
Model(&model.Player{}).
Model(&bunmodel.Player{}).
Order(playerOrders...).
Apply(paramsApplier.apply)
cntQ := p.db.NewSelect().
Model(&model.Player{}).
Model(&bunmodel.Player{}).
Apply(paramsApplier.applyFilters)
q := p.db.NewSelect().

View File

@ -1,4 +1,4 @@
package bundb
package adapter
import (
"context"
@ -7,7 +7,7 @@ import (
"fmt"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/uptrace/bun"
)
@ -16,22 +16,22 @@ var (
playerSnapshotOrders = []string{"ps.server_key ASC"}
)
type PlayerSnapshot struct {
type PlayerSnapshotBun struct {
db *bun.DB
}
func NewPlayerSnapshot(db *bun.DB) *PlayerSnapshot {
return &PlayerSnapshot{db: db}
func NewPlayerSnapshotBun(db *bun.DB) *PlayerSnapshotBun {
return &PlayerSnapshotBun{db: db}
}
func (p *PlayerSnapshot) Create(ctx context.Context, params ...domain.CreatePlayerSnapshotParams) error {
func (p *PlayerSnapshotBun) Create(ctx context.Context, params ...domain.CreatePlayerSnapshotParams) error {
if len(params) == 0 {
return nil
}
snapshots := make([]model.PlayerSnapshot, 0, len(params))
snapshots := make([]bunmodel.PlayerSnapshot, 0, len(params))
for _, param := range params {
snapshots = append(snapshots, model.NewPlayerSnapshot(param))
snapshots = append(snapshots, bunmodel.NewPlayerSnapshot(param))
}
if _, err := p.db.NewInsert().
@ -44,8 +44,8 @@ func (p *PlayerSnapshot) Create(ctx context.Context, params ...domain.CreatePlay
return nil
}
func (p *PlayerSnapshot) List(ctx context.Context, params domain.ListPlayerSnapshotsParams) ([]domain.PlayerSnapshot, error) {
var snapshots []model.PlayerSnapshot
func (p *PlayerSnapshotBun) List(ctx context.Context, params domain.ListPlayerSnapshotsParams) ([]domain.PlayerSnapshot, error) {
var snapshots []bunmodel.PlayerSnapshot
if err := p.db.NewSelect().
Model(&snapshots).
@ -63,22 +63,22 @@ func (p *PlayerSnapshot) List(ctx context.Context, params domain.ListPlayerSnaps
return result, nil
}
func (p *PlayerSnapshot) ListCountWithRelations(
func (p *PlayerSnapshotBun) ListCountWithRelations(
ctx context.Context,
params domain.ListPlayerSnapshotsParams,
) ([]domain.PlayerSnapshotWithRelations, int64, error) {
var snapshots []model.PlayerSnapshot
var snapshots []bunmodel.PlayerSnapshot
paramsApplier := listPlayerSnapshotsParamsApplier{params}
subQ := p.db.NewSelect().
Column("id").
Model(&model.PlayerSnapshot{}).
Model(&bunmodel.PlayerSnapshot{}).
Order(playerSnapshotOrders...).
Apply(paramsApplier.apply)
cntQ := p.db.NewSelect().
Model(&model.PlayerSnapshot{}).
Model(&bunmodel.PlayerSnapshot{}).
Apply(paramsApplier.applyFilters)
q := p.db.NewSelect().
@ -103,9 +103,9 @@ func (p *PlayerSnapshot) ListCountWithRelations(
return result, int64(count), nil
}
func (p *PlayerSnapshot) Delete(ctx context.Context, serverKey string, createdAtLTE time.Time) error {
func (p *PlayerSnapshotBun) Delete(ctx context.Context, serverKey string, createdAtLTE time.Time) error {
if _, err := p.db.NewDelete().
Model(&model.PlayerSnapshot{}).
Model(&bunmodel.PlayerSnapshot{}).
Where("server_key = ?", serverKey).
Where("created_at <= ?", createdAtLTE).
Returning("NULL").

View File

@ -1,12 +1,11 @@
package bundb_test
package adapter_test
import (
"context"
"testing"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/bundb"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/bundbtest"
"gitea.dwysokinski.me/twhelp/core/internal/adapter"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
@ -22,9 +21,9 @@ func TestPlayerSnapshot_Create(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewPlayerSnapshot(db)
repo := adapter.NewPlayerSnapshotBun(db)
t.Run("OK", func(t *testing.T) {
t.Parallel()
@ -191,9 +190,9 @@ func TestPlayerSnapshot_List(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewPlayerSnapshot(db)
repo := adapter.NewPlayerSnapshotBun(db)
snapshots := fixture.PlayerSnapshots(t)
type expectedSnapshots struct {
@ -450,9 +449,9 @@ func TestPlayerSnapshot_Delete(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewPlayerSnapshot(db)
repo := adapter.NewPlayerSnapshotBun(db)
snapshotsBeforeDelete, err := repo.List(context.Background(), domain.ListPlayerSnapshotsParams{})
assert.NoError(t, err)

View File

@ -1,4 +1,4 @@
package bundb_test
package adapter_test
import (
"context"
@ -7,8 +7,7 @@ import (
"github.com/stretchr/testify/require"
"gitea.dwysokinski.me/twhelp/core/internal/bundb"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/bundbtest"
"gitea.dwysokinski.me/twhelp/core/internal/adapter"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/jackc/pgerrcode"
"github.com/stretchr/testify/assert"
@ -22,9 +21,9 @@ func TestPlayer_CreateOrUpdate(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewPlayer(db)
repo := adapter.NewPlayerBun(db)
t.Run("OK", func(t *testing.T) {
t.Parallel()
@ -182,9 +181,9 @@ func TestPlayer_Delete(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewPlayer(db)
repo := adapter.NewPlayerBun(db)
t.Run("OK", func(t *testing.T) {
t.Parallel()
@ -221,9 +220,9 @@ func TestPlayer_List_ListCountWithRelations(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewPlayer(db)
repo := adapter.NewPlayerBun(db)
players := fixture.Players(t)
tribeCSA := fixture.Tribe(t, "pl169-csa")

View File

@ -1,4 +1,4 @@
package bundb
package adapter
import (
"context"
@ -7,7 +7,7 @@ import (
"fmt"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/uptrace/bun"
)
@ -16,22 +16,22 @@ var (
serverMetaColumns = []string{"key", "open", "url"}
)
type Server struct {
type ServerBun struct {
db *bun.DB
}
func NewServer(db *bun.DB) *Server {
return &Server{db: db}
func NewServerBun(db *bun.DB) *ServerBun {
return &ServerBun{db: db}
}
func (s *Server) CreateOrUpdate(ctx context.Context, params ...domain.CreateServerParams) ([]domain.Server, error) {
func (s *ServerBun) CreateOrUpdate(ctx context.Context, params ...domain.CreateServerParams) ([]domain.Server, error) {
if len(params) == 0 {
return nil, nil
}
servers := make([]model.Server, 0, len(params))
servers := make([]bunmodel.Server, 0, len(params))
for _, p := range params {
servers = append(servers, model.Server{
servers = append(servers, bunmodel.Server{
Key: p.Key,
URL: p.URL,
Open: p.Open,
@ -59,8 +59,8 @@ func (s *Server) CreateOrUpdate(ctx context.Context, params ...domain.CreateServ
return result, nil
}
func (s *Server) List(ctx context.Context, params domain.ListServersParams) ([]domain.Server, error) {
var servers []model.Server
func (s *ServerBun) List(ctx context.Context, params domain.ListServersParams) ([]domain.Server, error) {
var servers []bunmodel.Server
if err := s.buildListQuery(&servers, params).Scan(ctx); err != nil && !errors.Is(err, sql.ErrNoRows) {
return nil, fmt.Errorf("couldn't select servers from the db: %w", err)
@ -74,8 +74,8 @@ func (s *Server) List(ctx context.Context, params domain.ListServersParams) ([]d
return result, nil
}
func (s *Server) ListCount(ctx context.Context, params domain.ListServersParams) ([]domain.Server, int64, error) {
var servers []model.Server
func (s *ServerBun) ListCount(ctx context.Context, params domain.ListServersParams) ([]domain.Server, int64, error) {
var servers []bunmodel.Server
q := s.buildListQuery(&servers, params)
count, err := scanAndCount(ctx, q, q)
@ -91,19 +91,19 @@ func (s *Server) ListCount(ctx context.Context, params domain.ListServersParams)
return result, int64(count), nil
}
func (s *Server) buildListQuery(servers *[]model.Server, params domain.ListServersParams) *bun.SelectQuery {
func (s *ServerBun) buildListQuery(servers *[]bunmodel.Server, params domain.ListServersParams) *bun.SelectQuery {
return s.db.NewSelect().
Model(servers).
Order("server.version_code ASC", "server.open DESC", "server.key ASC").
Apply(listServersParamsApplier{params}.apply)
}
func (s *Server) Update(ctx context.Context, key string, params domain.UpdateServerParams) (domain.Server, error) {
func (s *ServerBun) Update(ctx context.Context, key string, params domain.UpdateServerParams) (domain.Server, error) {
if params.IsZero() {
return domain.Server{}, domain.ErrNothingToUpdate
}
var server model.Server
var server bunmodel.Server
res, err := s.db.NewUpdate().
Model(&server).
@ -200,21 +200,21 @@ func (u updateServerParamsApplier) applyConfig(q *bun.UpdateQuery) *bun.UpdateQu
if !u.params.Config.Valid {
return q
}
return q.Set("config = ?", model.NewServerConfig(u.params.Config.Config))
return q.Set("config = ?", bunmodel.NewServerConfig(u.params.Config.Config))
}
func (u updateServerParamsApplier) applyUnitInfo(q *bun.UpdateQuery) *bun.UpdateQuery {
if !u.params.UnitInfo.Valid {
return q
}
return q.Set("unit_info = ?", model.NewUnitInfo(u.params.UnitInfo.Info))
return q.Set("unit_info = ?", bunmodel.NewUnitInfo(u.params.UnitInfo.Info))
}
func (u updateServerParamsApplier) applyBuildingInfo(q *bun.UpdateQuery) *bun.UpdateQuery {
if !u.params.BuildingInfo.Valid {
return q
}
return q.Set("building_info = ?", model.NewBuildingInfo(u.params.BuildingInfo.Info))
return q.Set("building_info = ?", bunmodel.NewBuildingInfo(u.params.BuildingInfo.Info))
}
func (u updateServerParamsApplier) applyNumPlayers(q *bun.UpdateQuery) *bun.UpdateQuery {

View File

@ -1,4 +1,4 @@
package bundb_test
package adapter_test
import (
"context"
@ -11,8 +11,7 @@ import (
"github.com/stretchr/testify/assert"
"gitea.dwysokinski.me/twhelp/core/internal/bundb"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/bundbtest"
"gitea.dwysokinski.me/twhelp/core/internal/adapter"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
)
@ -23,7 +22,7 @@ func TestServer_CreateOrUpdate(t *testing.T) {
t.Skip("skipping long-running test")
}
repo := bundb.NewServer(bundbtest.NewDB(t))
repo := adapter.NewServerBun(newBunDB(t))
t.Run("OK", func(t *testing.T) {
t.Parallel()
@ -126,9 +125,9 @@ func TestServer_List_ListCount(t *testing.T) {
normalServers := concatStringSlices(normalOpenServers, normalClosedServers)
servers := concatStringSlices(specialServers, normalOpenServers, normalClosedServers)
db := bundbtest.NewDB(t)
db := newBunDB(t)
_ = loadFixtures(t, db)
repo := bundb.NewServer(db)
repo := adapter.NewServerBun(db)
tests := []struct {
name string
@ -337,8 +336,8 @@ func TestServer_Update(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
repo := bundb.NewServer(db)
db := newBunDB(t)
repo := adapter.NewServerBun(db)
fixture := loadFixtures(t, db)
server := fixture.Server(t, "de188")

View File

@ -1,4 +1,4 @@
package bundb
package adapter
import (
"context"
@ -7,7 +7,7 @@ import (
"fmt"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/uptrace/bun"
)
@ -16,23 +16,24 @@ var (
tribeMetaColumns = []string{"id", "name", "tag", "profile_url"}
)
type Tribe struct {
type TribeBun struct {
db *bun.DB
}
func NewTribe(db *bun.DB) *Tribe {
return &Tribe{db: db}
func NewTribeBun(db *bun.DB) *TribeBun {
return &TribeBun{db: db}
}
func (t *Tribe) CreateOrUpdate(ctx context.Context, params ...domain.CreateTribeParams) error {
func (t *TribeBun) CreateOrUpdate(ctx context.Context, params ...domain.CreateTribeParams) error {
if len(params) == 0 {
return nil
}
tribes := make([]model.Tribe, 0, len(params))
tribes := make([]bunmodel.Tribe, 0, len(params))
for _, p := range params {
tribes = append(tribes, model.NewTribe(p))
tribes = append(tribes, bunmodel.NewTribe(p))
}
if _, err := t.db.NewInsert().
Model(&tribes).
On("CONFLICT ON CONSTRAINT tribes_pkey DO UPDATE").
@ -60,13 +61,13 @@ func (t *Tribe) CreateOrUpdate(ctx context.Context, params ...domain.CreateTribe
return nil
}
func (t *Tribe) Delete(ctx context.Context, serverKey string, ids ...int64) error {
func (t *TribeBun) Delete(ctx context.Context, serverKey string, ids ...int64) error {
if len(ids) == 0 {
return nil
}
if _, err := t.db.NewUpdate().
Model(&model.Tribe{}).
Model(&bunmodel.Tribe{}).
Where("deleted_at IS NULL").
Where("id IN (?)", bun.In(ids)).
Where("server_key = ?", serverKey).
@ -79,9 +80,9 @@ func (t *Tribe) Delete(ctx context.Context, serverKey string, ids ...int64) erro
return nil
}
func (t *Tribe) UpdateDominance(ctx context.Context, serverKey string, numPlayerVillages int64) error {
func (t *TribeBun) UpdateDominance(ctx context.Context, serverKey string, numPlayerVillages int64) error {
q := t.db.NewUpdate().
Model(&model.Tribe{}).
Model(&bunmodel.Tribe{}).
Returning("NULL").
Where("server_key = ?", serverKey).
Where("deleted_at IS NULL")
@ -97,8 +98,8 @@ func (t *Tribe) UpdateDominance(ctx context.Context, serverKey string, numPlayer
return nil
}
func (t *Tribe) List(ctx context.Context, params domain.ListTribesParams) ([]domain.Tribe, error) {
var tribes []model.Tribe
func (t *TribeBun) List(ctx context.Context, params domain.ListTribesParams) ([]domain.Tribe, error) {
var tribes []bunmodel.Tribe
if err := t.buildListQuery(&tribes, params).Scan(ctx); err != nil && !errors.Is(err, sql.ErrNoRows) {
return nil, fmt.Errorf("couldn't select tribes from the db: %w", err)
@ -112,8 +113,8 @@ func (t *Tribe) List(ctx context.Context, params domain.ListTribesParams) ([]dom
return result, nil
}
func (t *Tribe) ListCount(ctx context.Context, params domain.ListTribesParams) ([]domain.Tribe, int64, error) {
var tribes []model.Tribe
func (t *TribeBun) ListCount(ctx context.Context, params domain.ListTribesParams) ([]domain.Tribe, int64, error) {
var tribes []bunmodel.Tribe
q := t.buildListQuery(&tribes, params)
count, err := scanAndCount(ctx, q, q)
@ -129,7 +130,7 @@ func (t *Tribe) ListCount(ctx context.Context, params domain.ListTribesParams) (
return result, int64(count), nil
}
func (t *Tribe) buildListQuery(tribes *[]model.Tribe, params domain.ListTribesParams) *bun.SelectQuery {
func (t *TribeBun) buildListQuery(tribes *[]bunmodel.Tribe, params domain.ListTribesParams) *bun.SelectQuery {
return t.db.NewSelect().
Model(tribes).
Order("tribe.server_key ASC").

View File

@ -1,4 +1,4 @@
package bundb
package adapter
import (
"context"
@ -6,7 +6,7 @@ import (
"errors"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/uptrace/bun"
)
@ -15,22 +15,22 @@ var (
tribeChangeOrders = []string{"tc.server_key ASC"}
)
type TribeChange struct {
type TribeChangeBun struct {
db *bun.DB
}
func NewTribeChange(db *bun.DB) *TribeChange {
return &TribeChange{db: db}
func NewTribeChangeBun(db *bun.DB) *TribeChangeBun {
return &TribeChangeBun{db: db}
}
func (t *TribeChange) Create(ctx context.Context, params ...domain.CreateTribeChangeParams) error {
func (t *TribeChangeBun) Create(ctx context.Context, params ...domain.CreateTribeChangeParams) error {
if len(params) == 0 {
return nil
}
tcs := make([]model.TribeChange, 0, len(params))
tcs := make([]bunmodel.TribeChange, 0, len(params))
for _, param := range params {
tcs = append(tcs, model.NewTribeChange(param))
tcs = append(tcs, bunmodel.NewTribeChange(param))
}
if _, err := t.db.NewInsert().
@ -43,8 +43,8 @@ func (t *TribeChange) Create(ctx context.Context, params ...domain.CreateTribeCh
return nil
}
func (t *TribeChange) List(ctx context.Context, params domain.ListTribeChangesParams) ([]domain.TribeChange, error) {
var tcs []model.TribeChange
func (t *TribeChangeBun) List(ctx context.Context, params domain.ListTribeChangesParams) ([]domain.TribeChange, error) {
var tcs []bunmodel.TribeChange
if err := t.db.NewSelect().
Model(&tcs).
@ -62,22 +62,22 @@ func (t *TribeChange) List(ctx context.Context, params domain.ListTribeChangesPa
return result, nil
}
func (t *TribeChange) ListCountWithRelations(
func (t *TribeChangeBun) ListCountWithRelations(
ctx context.Context,
params domain.ListTribeChangesParams,
) ([]domain.TribeChangeWithRelations, int64, error) {
var tcs []model.TribeChange
var tcs []bunmodel.TribeChange
paramsApplier := listTribeChangesParamsApplier{params}
subQ := t.db.NewSelect().
Column("id").
Model(&model.TribeChange{}).
Model(&bunmodel.TribeChange{}).
Order(tribeChangeOrders...).
Apply(paramsApplier.apply)
cntQ := t.db.NewSelect().
Model(&model.TribeChange{}).
Model(&bunmodel.TribeChange{}).
Apply(paramsApplier.applyFilters)
q := t.db.NewSelect().

View File

@ -1,11 +1,10 @@
package bundb_test
package adapter_test
import (
"context"
"testing"
"gitea.dwysokinski.me/twhelp/core/internal/bundb"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/bundbtest"
"gitea.dwysokinski.me/twhelp/core/internal/adapter"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/google/go-cmp/cmp"
"github.com/jackc/pgerrcode"
@ -20,9 +19,9 @@ func TestTribeChange_Create(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewTribeChange(db)
repo := adapter.NewTribeChangeBun(db)
t.Run("OK", func(t *testing.T) {
t.Parallel()
@ -165,9 +164,9 @@ func TestTribeChange_List_ListCountWithRelations(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewTribeChange(db)
repo := adapter.NewTribeChangeBun(db)
tcs := fixture.TribeChanges(t)
type expectedTribeChange struct {

View File

@ -1,4 +1,4 @@
package bundb
package adapter
import (
"context"
@ -7,27 +7,27 @@ import (
"fmt"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/uptrace/bun"
)
type TribeSnapshot struct {
type TribeSnapshotBun struct {
db *bun.DB
}
func NewTribeSnapshot(db *bun.DB) *TribeSnapshot {
return &TribeSnapshot{db: db}
func NewTribeSnapshotBun(db *bun.DB) *TribeSnapshotBun {
return &TribeSnapshotBun{db: db}
}
func (t *TribeSnapshot) Create(ctx context.Context, params ...domain.CreateTribeSnapshotParams) error {
func (t *TribeSnapshotBun) Create(ctx context.Context, params ...domain.CreateTribeSnapshotParams) error {
if len(params) == 0 {
return nil
}
snapshots := make([]model.TribeSnapshot, 0, len(params))
snapshots := make([]bunmodel.TribeSnapshot, 0, len(params))
for _, param := range params {
snapshots = append(snapshots, model.NewTribeSnapshot(param))
snapshots = append(snapshots, bunmodel.NewTribeSnapshot(param))
}
if _, err := t.db.NewInsert().
@ -40,8 +40,8 @@ func (t *TribeSnapshot) Create(ctx context.Context, params ...domain.CreateTribe
return nil
}
func (t *TribeSnapshot) List(ctx context.Context, params domain.ListTribeSnapshotsParams) ([]domain.TribeSnapshot, error) {
var snapshots []model.TribeSnapshot
func (t *TribeSnapshotBun) List(ctx context.Context, params domain.ListTribeSnapshotsParams) ([]domain.TribeSnapshot, error) {
var snapshots []bunmodel.TribeSnapshot
if err := t.buildListQuery(&snapshots, params).Scan(ctx); err != nil && !errors.Is(err, sql.ErrNoRows) {
return nil, fmt.Errorf("couldn't select tribe snapshots from the db: %w", err)
@ -55,8 +55,8 @@ func (t *TribeSnapshot) List(ctx context.Context, params domain.ListTribeSnapsho
return result, nil
}
func (t *TribeSnapshot) ListCount(ctx context.Context, params domain.ListTribeSnapshotsParams) ([]domain.TribeSnapshot, int64, error) {
var snapshots []model.TribeSnapshot
func (t *TribeSnapshotBun) ListCount(ctx context.Context, params domain.ListTribeSnapshotsParams) ([]domain.TribeSnapshot, int64, error) {
var snapshots []bunmodel.TribeSnapshot
q := t.buildListQuery(&snapshots, params)
count, err := scanAndCount(ctx, q, q)
@ -72,16 +72,16 @@ func (t *TribeSnapshot) ListCount(ctx context.Context, params domain.ListTribeSn
return result, int64(count), nil
}
func (t *TribeSnapshot) buildListQuery(snapshots *[]model.TribeSnapshot, params domain.ListTribeSnapshotsParams) *bun.SelectQuery {
func (t *TribeSnapshotBun) buildListQuery(snapshots *[]bunmodel.TribeSnapshot, params domain.ListTribeSnapshotsParams) *bun.SelectQuery {
return t.db.NewSelect().
Model(snapshots).
Order("ts.server_key ASC").
Apply(listTribeSnapshotsParamsApplier{params}.apply)
}
func (t *TribeSnapshot) Delete(ctx context.Context, serverKey string, createdAtLTE time.Time) error {
func (t *TribeSnapshotBun) Delete(ctx context.Context, serverKey string, createdAtLTE time.Time) error {
if _, err := t.db.NewDelete().
Model(&model.TribeSnapshot{}).
Model(&bunmodel.TribeSnapshot{}).
Where("server_key = ?", serverKey).
Where("created_at <= ?", createdAtLTE).
Returning("NULL").

View File

@ -1,12 +1,11 @@
package bundb_test
package adapter_test
import (
"context"
"testing"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/bundb"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/bundbtest"
"gitea.dwysokinski.me/twhelp/core/internal/adapter"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
@ -22,9 +21,9 @@ func TestTribeSnapshot_Create(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewTribeSnapshot(db)
repo := adapter.NewTribeSnapshotBun(db)
t.Run("OK", func(t *testing.T) {
t.Parallel()
@ -208,9 +207,9 @@ func TestTribeSnapshot_List_ListCount(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewTribeSnapshot(db)
repo := adapter.NewTribeSnapshotBun(db)
snapshots := fixture.TribeSnapshots(t)
type expectedSnapshots struct {
@ -459,9 +458,9 @@ func TestTribeSnapshot_Delete(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewTribeSnapshot(db)
repo := adapter.NewTribeSnapshotBun(db)
snapshotsBeforeDelete, err := repo.List(context.Background(), domain.ListTribeSnapshotsParams{})
assert.NoError(t, err)

View File

@ -1,4 +1,4 @@
package bundb_test
package adapter_test
import (
"context"
@ -12,10 +12,9 @@ import (
"github.com/stretchr/testify/assert"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/bundbtest"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"gitea.dwysokinski.me/twhelp/core/internal/bundb"
"gitea.dwysokinski.me/twhelp/core/internal/adapter"
)
func TestTribe_CreateOrUpdate(t *testing.T) {
@ -25,9 +24,9 @@ func TestTribe_CreateOrUpdate(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
_ = loadFixtures(t, db)
repo := bundb.NewTribe(db)
repo := adapter.NewTribeBun(db)
t.Run("OK", func(t *testing.T) {
t.Parallel()
@ -185,9 +184,9 @@ func TestTribe_Delete(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewTribe(db)
repo := adapter.NewTribeBun(db)
t.Run("OK", func(t *testing.T) {
t.Parallel()
@ -223,9 +222,9 @@ func TestTribe_List_ListCount(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewTribe(db)
repo := adapter.NewTribeBun(db)
tribes := fixture.Tribes(t)
type expectedTribe struct {
@ -618,9 +617,9 @@ func TestTribe_UpdateDominance(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewTribe(db)
repo := adapter.NewTribeBun(db)
serverDE188 := fixture.Server(t, "de188")
serverPL169 := fixture.Server(t, "pl169")

View File

@ -1,4 +1,4 @@
package bundb
package adapter
import (
"context"
@ -6,21 +6,21 @@ import (
"errors"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/uptrace/bun"
)
type Version struct {
type VersionBun struct {
db *bun.DB
}
func NewVersion(db *bun.DB) *Version {
return &Version{db: db}
func NewVersionBun(db *bun.DB) *VersionBun {
return &VersionBun{db: db}
}
func (v *Version) List(ctx context.Context) ([]domain.Version, error) {
var versions []model.Version
func (v *VersionBun) List(ctx context.Context) ([]domain.Version, error) {
var versions []bunmodel.Version
if err := v.buildListQuery(&versions).Scan(ctx); err != nil && !errors.Is(err, sql.ErrNoRows) {
return nil, fmt.Errorf("couldn't select versions from the db: %w", err)
@ -34,8 +34,8 @@ func (v *Version) List(ctx context.Context) ([]domain.Version, error) {
return result, nil
}
func (v *Version) ListCount(ctx context.Context) ([]domain.Version, int64, error) {
var versions []model.Version
func (v *VersionBun) ListCount(ctx context.Context) ([]domain.Version, int64, error) {
var versions []bunmodel.Version
count, err := v.buildListQuery(&versions).ScanAndCount(ctx)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
@ -50,14 +50,14 @@ func (v *Version) ListCount(ctx context.Context) ([]domain.Version, int64, error
return result, int64(count), nil
}
func (v *Version) buildListQuery(versions *[]model.Version) *bun.SelectQuery {
func (v *VersionBun) buildListQuery(versions *[]bunmodel.Version) *bun.SelectQuery {
return v.db.NewSelect().
Model(versions).
Order("code ASC")
}
func (v *Version) GetByCode(ctx context.Context, code string) (domain.Version, error) {
var version model.Version
func (v *VersionBun) GetByCode(ctx context.Context, code string) (domain.Version, error) {
var version bunmodel.Version
if err := v.db.NewSelect().
Model(&version).

View File

@ -1,11 +1,10 @@
package bundb_test
package adapter_test
import (
"context"
"testing"
"gitea.dwysokinski.me/twhelp/core/internal/bundb"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/bundbtest"
"gitea.dwysokinski.me/twhelp/core/internal/adapter"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
@ -19,7 +18,7 @@ func TestVersion_List_ListCount(t *testing.T) {
t.Skip("skipping long-running test")
}
repo := bundb.NewVersion(bundbtest.NewDB(t))
repo := adapter.NewVersionBun(newBunDB(t))
allVersions := []string{
"pl",
@ -70,7 +69,7 @@ func TestVersion_GetByCode(t *testing.T) {
t.Skip("skipping long-running test")
}
repo := bundb.NewVersion(bundbtest.NewDB(t))
repo := adapter.NewVersionBun(newBunDB(t))
t.Run("OK", func(t *testing.T) {
t.Parallel()

View File

@ -1,4 +1,4 @@
package bundb
package adapter
import (
"context"
@ -6,7 +6,7 @@ import (
"errors"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/uptrace/bun"
)
@ -16,22 +16,22 @@ var (
villageOrders = []string{"village.server_key ASC", "village.id ASC"}
)
type Village struct {
type VillageBun struct {
db *bun.DB
}
func NewVillage(db *bun.DB) *Village {
return &Village{db: db}
func NewVillageBun(db *bun.DB) *VillageBun {
return &VillageBun{db: db}
}
func (v *Village) CreateOrUpdate(ctx context.Context, params ...domain.CreateVillageParams) error {
func (v *VillageBun) CreateOrUpdate(ctx context.Context, params ...domain.CreateVillageParams) error {
if len(params) == 0 {
return nil
}
villages := make([]model.Village, 0, len(params))
villages := make([]bunmodel.Village, 0, len(params))
for _, p := range params {
villages = append(villages, model.NewVillage(p))
villages = append(villages, bunmodel.NewVillage(p))
}
if _, err := v.db.NewInsert().
Model(&villages).
@ -52,8 +52,8 @@ func (v *Village) CreateOrUpdate(ctx context.Context, params ...domain.CreateVil
return nil
}
func (v *Village) List(ctx context.Context, params domain.ListVillagesParams) ([]domain.Village, error) {
var villages []model.Village
func (v *VillageBun) List(ctx context.Context, params domain.ListVillagesParams) ([]domain.Village, error) {
var villages []bunmodel.Village
err := v.db.NewSelect().
Model(&villages).
@ -72,20 +72,20 @@ func (v *Village) List(ctx context.Context, params domain.ListVillagesParams) ([
return result, nil
}
func (v *Village) ListCountWithRelations(ctx context.Context, params domain.ListVillagesParams) ([]domain.VillageWithRelations, int64, error) {
var villages []model.Village
func (v *VillageBun) ListCountWithRelations(ctx context.Context, params domain.ListVillagesParams) ([]domain.VillageWithRelations, int64, error) {
var villages []bunmodel.Village
paramsApplier := listVillagesParamsApplier{params}
cntQ := v.db.NewSelect().
Model(&model.Village{}).
Model(&bunmodel.Village{}).
Apply(paramsApplier.applyFilters)
q := v.db.NewSelect().
Model(&villages).
Where("(village.id, village.server_key) IN (?)", v.db.NewSelect().
Column("id", "server_key").
Model(&model.Village{}).
Model(&bunmodel.Village{}).
Order(villageOrders...).
Apply(paramsApplier.apply)).
Order(villageOrders...).

View File

@ -1,12 +1,11 @@
package bundb_test
package adapter_test
import (
"context"
"testing"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/bundb"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/bundbtest"
"gitea.dwysokinski.me/twhelp/core/internal/adapter"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/jackc/pgerrcode"
"github.com/stretchr/testify/assert"
@ -20,9 +19,9 @@ func TestVillage_CreateOrUpdate(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewVillage(db)
repo := adapter.NewVillageBun(db)
t.Run("OK", func(t *testing.T) {
t.Parallel()
@ -129,9 +128,9 @@ func TestVillage_List_ListCountWithRelations(t *testing.T) {
t.Skip("skipping long-running test")
}
db := bundbtest.NewDB(t)
db := newBunDB(t)
fixture := loadFixtures(t, db)
repo := bundb.NewVillage(db)
repo := adapter.NewVillageBun(db)
villages := fixture.Villages(t)
type expectedVillage struct {

View File

@ -0,0 +1,69 @@
package bundbtest
import (
"context"
"database/sql"
"strings"
"time"
"unicode"
"github.com/cenkalti/backoff/v4"
"github.com/google/uuid"
"github.com/pressly/goose/v3"
"github.com/stretchr/testify/require"
"github.com/uptrace/bun"
"github.com/uptrace/bun/dialect/pgdialect"
"github.com/uptrace/bun/driver/pgdriver"
)
const (
migrationTimeout = 10 * time.Second
retryMaxInterval = 5 * time.Second
retryMaxElapsedTime = 30 * time.Second
)
// NewDB creates a new *bun.DB. Don't forget to set up goose before using this function.
func NewDB(t TestingT, dsn string) *bun.DB {
t.Helper()
schema := generateSchema()
sqldb := sql.OpenDB(
pgdriver.NewConnector(
pgdriver.WithDSN(dsn),
pgdriver.WithConnParams(map[string]any{
"search_path": schema,
}),
),
)
bunDB := bun.NewDB(sqldb, pgdialect.New())
t.Cleanup(func() {
_ = bunDB.Close()
})
bo := backoff.NewExponentialBackOff()
bo.MaxInterval = retryMaxInterval
bo.MaxElapsedTime = retryMaxElapsedTime
require.NoError(t, backoff.Retry(bunDB.Ping, bo), "couldn't ping DB")
_, err := bunDB.Exec("CREATE SCHEMA ?", bun.Safe(schema))
require.NoError(t, err, "couldn't create schema")
runMigrations(t, sqldb)
return bunDB
}
func runMigrations(t TestingT, db *sql.DB) {
t.Helper()
ctx, cancel := context.WithTimeout(context.Background(), migrationTimeout)
defer cancel()
require.NoError(t, goose.UpContext(ctx, db, "."), "couldn't migrate")
}
func generateSchema() string {
return strings.TrimFunc(strings.ReplaceAll(uuid.NewString(), "-", "_"), unicode.IsNumber)
}

View File

@ -1,7 +1,7 @@
package bundbtest
import (
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/stretchr/testify/require"
"github.com/uptrace/bun"
@ -9,15 +9,15 @@ import (
)
var modelsToRegister = []any{
&model.Version{},
&model.Server{},
&model.Tribe{},
&model.Player{},
&model.Village{},
&model.Ennoblement{},
&model.PlayerSnapshot{},
&model.TribeSnapshot{},
&model.TribeChange{},
&bunmodel.Version{},
&bunmodel.Server{},
&bunmodel.Tribe{},
&bunmodel.Player{},
&bunmodel.Village{},
&bunmodel.Ennoblement{},
&bunmodel.PlayerSnapshot{},
&bunmodel.TribeSnapshot{},
&bunmodel.TribeChange{},
}
type Fixture struct {
@ -37,7 +37,7 @@ func (f *Fixture) Server(t TestingT, id string) domain.Server {
row, err := f.Row("Server." + id)
require.NoError(t, err)
s, ok := row.(*model.Server)
s, ok := row.(*bunmodel.Server)
require.True(t, ok)
return s.ToDomain()
}
@ -58,7 +58,7 @@ func (f *Fixture) Tribe(t TestingT, id string) domain.Tribe {
row, err := f.Row("Tribe." + id)
require.NoError(t, err)
tribe, ok := row.(*model.Tribe)
tribe, ok := row.(*bunmodel.Tribe)
require.True(t, ok)
return tribe.ToDomain()
}
@ -79,7 +79,7 @@ func (f *Fixture) Player(t TestingT, id string) domain.Player {
row, err := f.Row("Player." + id)
require.NoError(t, err)
p, ok := row.(*model.Player)
p, ok := row.(*bunmodel.Player)
require.True(t, ok)
return p.ToDomain()
}
@ -100,7 +100,7 @@ func (f *Fixture) Village(t TestingT, id string) domain.Village {
row, err := f.Row("Village." + id)
require.NoError(t, err)
v, ok := row.(*model.Village)
v, ok := row.(*bunmodel.Village)
require.True(t, ok)
return v.ToDomain()
}
@ -121,7 +121,7 @@ func (f *Fixture) Ennoblement(t TestingT, id string) domain.Ennoblement {
row, err := f.Row("Ennoblement." + id)
require.NoError(t, err)
e, ok := row.(*model.Ennoblement)
e, ok := row.(*bunmodel.Ennoblement)
require.True(t, ok)
return e.ToDomain()
}
@ -142,7 +142,7 @@ func (f *Fixture) PlayerSnapshot(t TestingT, id string) domain.PlayerSnapshot {
row, err := f.Row("PlayerSnapshot." + id)
require.NoError(t, err)
ps, ok := row.(*model.PlayerSnapshot)
ps, ok := row.(*bunmodel.PlayerSnapshot)
require.True(t, ok)
return ps.ToDomain()
}
@ -163,7 +163,7 @@ func (f *Fixture) TribeSnapshot(t TestingT, id string) domain.TribeSnapshot {
row, err := f.Row("TribeSnapshot." + id)
require.NoError(t, err)
ts, ok := row.(*model.TribeSnapshot)
ts, ok := row.(*bunmodel.TribeSnapshot)
require.True(t, ok)
return ts.ToDomain()
}
@ -184,7 +184,7 @@ func (f *Fixture) TribeChange(t TestingT, id string) domain.TribeChange {
row, err := f.Row("TribeChange." + id)
require.NoError(t, err)
tc, ok := row.(*model.TribeChange)
tc, ok := row.(*bunmodel.TribeChange)
require.True(t, ok)
return tc.ToDomain()
}

View File

@ -0,0 +1,67 @@
package bundbtest
import (
"fmt"
"net"
"net/url"
"os"
"github.com/ory/dockertest/v3"
"github.com/ory/dockertest/v3/docker"
)
func NewPostgres(pool *dockertest.Pool, expSeconds uint) (*dockertest.Resource, *url.URL, error) {
q := url.Values{}
q.Add("sslmode", "disable")
dsn := &url.URL{
Scheme: "postgres",
User: url.UserPassword("postgres", "postgres"),
Path: "twhelpdb",
RawQuery: q.Encode(),
}
pw, _ := dsn.User.Password()
resource, err := pool.RunWithOptions(&dockertest.RunOptions{
Repository: "postgres",
Tag: "14.8",
Env: []string{
fmt.Sprintf("POSTGRES_USER=%s", dsn.User.Username()),
fmt.Sprintf("POSTGRES_PASSWORD=%s", pw),
fmt.Sprintf("POSTGRES_DB=%s", dsn.Path),
},
}, func(config *docker.HostConfig) {
config.AutoRemove = true
config.RestartPolicy = docker.RestartPolicy{
Name: "no",
}
})
if err != nil {
return nil, nil, fmt.Errorf("couldn't run postgres: %w", err)
}
if err = resource.Expire(expSeconds); err != nil {
return nil, nil, err
}
dsn.Host, err = getHostPort(resource, "5432/tcp")
if err != nil {
return nil, nil, err
}
return resource, dsn, nil
}
func getHostPort(resource *dockertest.Resource, id string) (string, error) {
dockerURL := os.Getenv("DOCKER_HOST")
if dockerURL == "" {
return resource.GetHostPort(id), nil
}
u, err := url.Parse(dockerURL)
if err != nil {
return "", err
}
return net.JoinHostPort(u.Hostname(), resource.GetPort(id)), nil
}

View File

@ -1,4 +1,4 @@
package model
package bunmodel
import "gitea.dwysokinski.me/twhelp/core/internal/domain"

View File

@ -1,9 +1,9 @@
package model_test
package bunmodel_test
import (
"testing"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/stretchr/testify/assert"
)
@ -82,5 +82,5 @@ func TestBuildingInfo(t *testing.T) {
BuildTimeFactor: 0.5,
},
}
assert.Equal(t, info, model.NewBuildingInfo(info).ToDomain())
assert.Equal(t, info, bunmodel.NewBuildingInfo(info).ToDomain())
}

View File

@ -1,4 +1,4 @@
package model
package bunmodel
import (
"time"

View File

@ -1,10 +1,10 @@
package model_test
package bunmodel_test
import (
"testing"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"github.com/stretchr/testify/assert"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
@ -25,7 +25,7 @@ func TestEnnoblement(t *testing.T) {
ServerKey: "pl151",
}
result := model.NewEnnoblement(params)
result := bunmodel.NewEnnoblement(params)
result.ID = id
ennoblement := result.ToDomain()
@ -39,19 +39,19 @@ func TestEnnoblement(t *testing.T) {
assert.Equal(t, params.ServerKey, ennoblement.ServerKey)
assert.Equal(t, id, ennoblement.ID)
result.Village = model.Village{
result.Village = bunmodel.Village{
ID: 12345,
}
result.NewOwner = model.Player{
result.NewOwner = bunmodel.Player{
ID: 11231,
}
result.NewTribe = model.Tribe{
result.NewTribe = bunmodel.Tribe{
ID: 11232,
}
result.OldOwner = model.Player{
result.OldOwner = bunmodel.Player{
ID: 11233,
}
result.OldTribe = model.Tribe{
result.OldTribe = bunmodel.Tribe{
ID: 11234,
}

View File

@ -1,4 +1,4 @@
package model
package bunmodel
type OpponentsDefeated struct {
RankAtt int64 `bun:"rank_att"`

View File

@ -1,4 +1,4 @@
package model
package bunmodel
import (
"time"

View File

@ -1,4 +1,4 @@
package model
package bunmodel
import (
"time"

View File

@ -1,10 +1,10 @@
package model_test
package bunmodel_test
import (
"testing"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/stretchr/testify/assert"
)
@ -33,7 +33,7 @@ func TestPlayerSnapshot(t *testing.T) {
Date: time.Date(2022, time.December, 24, 0, 0, 0, 0, time.UTC),
}
result := model.NewPlayerSnapshot(params)
result := bunmodel.NewPlayerSnapshot(params)
result.ID = id
snapshot := result.ToDomain()
@ -49,7 +49,7 @@ func TestPlayerSnapshot(t *testing.T) {
assert.Equal(t, params.Date, snapshot.Date)
assert.WithinDuration(t, time.Now(), snapshot.CreatedAt, time.Second)
result.Tribe = model.Tribe{
result.Tribe = bunmodel.Tribe{
ID: params.TribeID,
}

View File

@ -1,10 +1,10 @@
package model_test
package bunmodel_test
import (
"testing"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/stretchr/testify/assert"
)
@ -41,7 +41,7 @@ func TestPlayer(t *testing.T) {
ServerKey: "pl151",
}
result := model.NewPlayer(params)
result := bunmodel.NewPlayer(params)
result.DeletedAt = deletedAt
player := result.ToDomain()
@ -69,10 +69,10 @@ func TestPlayer(t *testing.T) {
assert.Equal(t, params.Name, meta.Name)
assert.Equal(t, params.ProfileURL, meta.ProfileURL)
result.Tribe = model.Tribe{
result.Tribe = bunmodel.Tribe{
ID: params.TribeID,
}
result.Server = model.Server{
result.Server = bunmodel.Server{
Key: params.ServerKey,
}

View File

@ -1,4 +1,4 @@
package model
package bunmodel
import (
"time"

View File

@ -1,4 +1,4 @@
package model
package bunmodel
import "gitea.dwysokinski.me/twhelp/core/internal/domain"

View File

@ -1,9 +1,9 @@
package model_test
package bunmodel_test
import (
"testing"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/stretchr/testify/assert"
)
@ -137,5 +137,5 @@ func TestServerConfig(t *testing.T) {
Check: 16,
},
}
assert.Equal(t, cfg, model.NewServerConfig(cfg).ToDomain())
assert.Equal(t, cfg, bunmodel.NewServerConfig(cfg).ToDomain())
}

View File

@ -1,10 +1,10 @@
package model_test
package bunmodel_test
import (
"testing"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/stretchr/testify/assert"
)
@ -41,7 +41,7 @@ func TestServer_ToDomain(t *testing.T) {
EnnoblementDataUpdatedAt: time.Now().Add(15 * time.Hour),
VersionCode: "pl",
}
dbModel := model.Server{
dbModel := bunmodel.Server{
Key: domainModel.Key,
URL: domainModel.URL,
Open: domainModel.Open,
@ -52,9 +52,9 @@ func TestServer_ToDomain(t *testing.T) {
NumPlayerVillages: domainModel.NumPlayerVillages,
NumBarbarianVillages: domainModel.NumBarbarianVillages,
NumBonusVillages: domainModel.NumBonusVillages,
Config: model.NewServerConfig(domainModel.Config),
BuildingInfo: model.NewBuildingInfo(domainModel.BuildingInfo),
UnitInfo: model.NewUnitInfo(domainModel.UnitInfo),
Config: bunmodel.NewServerConfig(domainModel.Config),
BuildingInfo: bunmodel.NewBuildingInfo(domainModel.BuildingInfo),
UnitInfo: bunmodel.NewUnitInfo(domainModel.UnitInfo),
CreatedAt: domainModel.CreatedAt,
PlayerDataUpdatedAt: domainModel.PlayerDataUpdatedAt,
PlayerSnapshotsCreatedAt: domainModel.PlayerSnapshotsCreatedAt,

View File

@ -1,4 +1,4 @@
package model
package bunmodel
import (
"time"

View File

@ -1,4 +1,4 @@
package model
package bunmodel
import (
"time"

View File

@ -1,10 +1,10 @@
package model_test
package bunmodel_test
import (
"testing"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/stretchr/testify/assert"
)
@ -20,7 +20,7 @@ func TestTribeChange(t *testing.T) {
ServerKey: "pl151",
}
result := model.NewTribeChange(params)
result := bunmodel.NewTribeChange(params)
result.ID = id
tc := result.ToDomain()
@ -31,13 +31,13 @@ func TestTribeChange(t *testing.T) {
assert.Equal(t, params.ServerKey, tc.ServerKey)
assert.WithinDuration(t, time.Now(), tc.CreatedAt, time.Second)
result.Player = model.Player{
result.Player = bunmodel.Player{
ID: 11231,
}
result.NewTribe = model.Tribe{
result.NewTribe = bunmodel.Tribe{
ID: 11232,
}
result.OldTribe = model.Tribe{
result.OldTribe = bunmodel.Tribe{
ID: 11234,
}

View File

@ -1,4 +1,4 @@
package model
package bunmodel
import (
"time"

View File

@ -1,10 +1,10 @@
package model_test
package bunmodel_test
import (
"testing"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/stretchr/testify/assert"
)
@ -35,7 +35,7 @@ func TestTribeSnapshot(t *testing.T) {
Date: time.Date(2022, time.December, 24, 0, 0, 0, 0, time.UTC),
}
result := model.NewTribeSnapshot(params)
result := bunmodel.NewTribeSnapshot(params)
result.ID = id
snapshot := result.ToDomain()

View File

@ -1,10 +1,10 @@
package model_test
package bunmodel_test
import (
"testing"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/stretchr/testify/assert"
)
@ -42,7 +42,7 @@ func TestTribe(t *testing.T) {
ServerKey: "pl151",
}
result := model.NewTribe(params)
result := bunmodel.NewTribe(params)
result.DeletedAt = deletedAt
tribe := result.ToDomain()

View File

@ -1,4 +1,4 @@
package model
package bunmodel
import "gitea.dwysokinski.me/twhelp/core/internal/domain"

View File

@ -1,9 +1,9 @@
package model_test
package bunmodel_test
import (
"testing"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/stretchr/testify/assert"
)
@ -65,5 +65,5 @@ func TestUnitInfo(t *testing.T) {
Carry: 8,
},
}
assert.Equal(t, info, model.NewUnitInfo(info).ToDomain())
assert.Equal(t, info, bunmodel.NewUnitInfo(info).ToDomain())
}

View File

@ -1,4 +1,4 @@
package model
package bunmodel
import (
"gitea.dwysokinski.me/twhelp/core/internal/domain"

View File

@ -1,11 +1,11 @@
package model_test
package bunmodel_test
import (
"testing"
"github.com/stretchr/testify/assert"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
)
@ -18,7 +18,7 @@ func TestVersion_ToDomain(t *testing.T) {
Host: "plemiona.pl",
Timezone: "Europe/Warsaw",
}
dbModel := model.Version{
dbModel := bunmodel.Version{
Code: domainModel.Code,
Name: domainModel.Name,
Host: domainModel.Host,

View File

@ -1,4 +1,4 @@
package model
package bunmodel
import (
"time"

View File

@ -1,10 +1,10 @@
package model_test
package bunmodel_test
import (
"testing"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/internal/bunmodel"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"github.com/stretchr/testify/assert"
)
@ -25,7 +25,7 @@ func TestVillage(t *testing.T) {
ServerKey: "pl151",
}
result := model.NewVillage(params)
result := bunmodel.NewVillage(params)
village := result.ToDomain()
assert.Equal(t, params.ID, village.ID)
@ -47,9 +47,9 @@ func TestVillage(t *testing.T) {
assert.Equal(t, params.Continent, meta.Continent)
assert.Equal(t, params.ProfileURL, meta.ProfileURL)
result.Player = model.Player{
result.Player = bunmodel.Player{
ID: 12321,
Tribe: model.Tribe{
Tribe: bunmodel.Tribe{
ID: 1234112,
},
}

View File

@ -1,156 +0,0 @@
package bundbtest
import (
"database/sql"
"errors"
"fmt"
"net"
"net/url"
"os"
"strings"
"sync"
"time"
"unicode"
"github.com/cenkalti/backoff/v4"
"github.com/google/uuid"
"github.com/ory/dockertest/v3"
"github.com/ory/dockertest/v3/docker"
"github.com/pressly/goose/v3"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/uptrace/bun"
"github.com/uptrace/bun/dialect/pgdialect"
"github.com/uptrace/bun/driver/pgdriver"
)
const (
poolMaxWait = 20 * time.Second
resourceExpSec = 180
migrationTimeout = 10 * time.Second
retryMaxInterval = 5 * time.Second
retryMaxElapsedTime = 30 * time.Second
)
func NewDB(t TestingT) *bun.DB {
t.Helper()
if dsn, ok := os.LookupEnv("TESTS_DB_DSN"); ok {
return NewDBWithDSN(t, dsn)
}
q := url.Values{}
q.Add("sslmode", "disable")
dsn := &url.URL{
Scheme: "postgres",
User: url.UserPassword("postgres", "postgres"),
Path: "twhelp",
RawQuery: q.Encode(),
}
pool, err := dockertest.NewPool("")
require.NoError(t, err, "couldn't connect to docker")
pool.MaxWait = poolMaxWait
pw, _ := dsn.User.Password()
resource, err := pool.RunWithOptions(&dockertest.RunOptions{
Repository: "postgres",
Tag: "14.8",
Env: []string{
fmt.Sprintf("POSTGRES_USER=%s", dsn.User.Username()),
fmt.Sprintf("POSTGRES_PASSWORD=%s", pw),
fmt.Sprintf("POSTGRES_DB=%s", dsn.Path),
},
}, func(config *docker.HostConfig) {
config.AutoRemove = true
config.RestartPolicy = docker.RestartPolicy{
Name: "no",
}
})
require.NoError(t, err, "couldn't start resource")
t.Cleanup(func() {
_ = pool.Purge(resource)
})
assert.NoError(t, resource.Expire(resourceExpSec))
dsn.Host = getHostPort(t, resource, "5432/tcp")
return NewDBWithDSN(t, dsn.String())
}
func NewDBWithDSN(t TestingT, dsn string) *bun.DB {
t.Helper()
schema := generateSchema()
sqldb := sql.OpenDB(
pgdriver.NewConnector(
pgdriver.WithDSN(dsn),
pgdriver.WithConnParams(map[string]any{
"search_path": schema,
}),
),
)
bunDB := bun.NewDB(sqldb, pgdialect.New())
t.Cleanup(func() {
_ = bunDB.Close()
})
require.NoError(t, retry(bunDB.Ping), "couldn't ping DB")
_, err := bunDB.Exec("CREATE SCHEMA ?", bun.Safe(schema))
require.NoError(t, err, "couldn't create schema")
runMigrations(t, sqldb)
return bunDB
}
func getHostPort(t TestingT, resource *dockertest.Resource, id string) string {
t.Helper()
dockerURL := os.Getenv("DOCKER_HOST")
if dockerURL == "" {
return resource.GetHostPort(id)
}
u, err := url.Parse(dockerURL)
require.NoError(t, err)
return net.JoinHostPort(u.Hostname(), resource.GetPort(id))
}
var gooseSetUpOnce = sync.Once{}
func runMigrations(t TestingT, db *sql.DB) {
t.Helper()
gooseSetUpOnce.Do(func() {
goose.SetBaseFS(os.DirFS("../../migrations"))
goose.SetLogger(goose.NopLogger())
require.NoError(t, goose.SetDialect("postgres"))
})
require.NoError(t, goose.Up(db, "."), "couldn't migrate")
}
func generateSchema() string {
return strings.TrimFunc(strings.ReplaceAll(uuid.NewString(), "-", "_"), unicode.IsNumber)
}
func retry(op func() error) error {
bo := backoff.NewExponentialBackOff()
bo.MaxInterval = retryMaxInterval
bo.MaxElapsedTime = retryMaxElapsedTime
if err := backoff.Retry(op, bo); err != nil {
if bo.NextBackOff() == backoff.Stop {
return errors.New("reached retry deadline")
}
return err
}
return nil
}

View File

@ -1,23 +0,0 @@
package bundb
import (
"context"
"github.com/uptrace/bun"
)
type Checker struct {
db *bun.DB
}
func NewChecker(db *bun.DB) *Checker {
return &Checker{db: db}
}
func (c *Checker) Name() string {
return "db:ping"
}
func (c *Checker) Check(ctx context.Context) error {
return c.db.PingContext(ctx)
}

View File

@ -1,26 +0,0 @@
package bundb_test
import (
"context"
"testing"
"gitea.dwysokinski.me/twhelp/core/internal/bundb"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/bundbtest"
"github.com/stretchr/testify/assert"
)
func TestChecker_Name(t *testing.T) {
t.Parallel()
assert.Equal(t, "db:ping", bundb.NewChecker(nil).Name())
}
func TestChecker_Check(t *testing.T) {
t.Parallel()
if testing.Short() {
t.Skip("skipping long-running test")
}
assert.NoError(t, bundb.NewChecker(bundbtest.NewDB(t)).Check(context.Background()))
}

View File

@ -16,8 +16,8 @@ import (
"testing"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/bundb"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/bundbtest"
"gitea.dwysokinski.me/twhelp/core/internal/adapter"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/bundbtest"
"gitea.dwysokinski.me/twhelp/core/internal/domain"
"gitea.dwysokinski.me/twhelp/core/internal/msg"
"gitea.dwysokinski.me/twhelp/core/internal/service"
@ -116,15 +116,15 @@ func TestUpdateData(t *testing.T) {
}))
// repos
db := bundbtest.NewDB(t)
versionRepo := bundb.NewVersion(db)
serverRepo := bundb.NewServer(db)
tribeRepo := bundb.NewTribe(db)
playerRepo := bundb.NewPlayer(db)
villageRepo := bundb.NewVillage(db)
tribeChangeRepo := bundb.NewTribeChange(db)
playerSnapshotRepo := bundb.NewPlayerSnapshot(db)
tribeSnapshotRepo := bundb.NewTribeSnapshot(db)
db := newBunDB(t)
versionRepo := adapter.NewVersionBun(db)
serverRepo := adapter.NewServerBun(db)
tribeRepo := adapter.NewTribeBun(db)
playerRepo := adapter.NewPlayerBun(db)
villageRepo := adapter.NewVillageBun(db)
tribeChangeRepo := adapter.NewTribeChangeBun(db)
playerSnapshotRepo := adapter.NewPlayerSnapshotBun(db)
tribeSnapshotRepo := adapter.NewTribeSnapshotBun(db)
// services
versionSvc := service.NewVersion(versionRepo)
@ -361,13 +361,13 @@ func TestUpdateEnnoblements(t *testing.T) {
)
// db
db := bundbtest.NewDB(t)
db := newBunDB(t)
require.NoError(t, bundbtest.NewFixture(db).Load(ctx, os.DirFS("./testdata/updateennoblements"), "fixture.yml"))
// repos
versionRepo := bundb.NewVersion(db)
serverRepo := bundb.NewServer(db)
ennoblementRepo := bundb.NewEnnoblement(db)
versionRepo := adapter.NewVersionBun(db)
serverRepo := adapter.NewServerBun(db)
ennoblementRepo := adapter.NewEnnoblementBun(db)
// services
versionSvc := service.NewVersion(versionRepo)
@ -476,16 +476,16 @@ func TestCreateSnapshots(t *testing.T) {
)
// db
db := bundbtest.NewDB(t)
db := newBunDB(t)
require.NoError(t, bundbtest.NewFixture(db).Load(ctx, os.DirFS("./testdata/createsnapshots"), "fixture.yml"))
// repos
versionRepo := bundb.NewVersion(db)
serverRepo := bundb.NewServer(db)
playerRepo := bundb.NewPlayer(db)
playerSnapshotRepo := bundb.NewPlayerSnapshot(db)
tribeRepo := bundb.NewTribe(db)
tribeSnapshotRepo := bundb.NewTribeSnapshot(db)
versionRepo := adapter.NewVersionBun(db)
serverRepo := adapter.NewServerBun(db)
playerRepo := adapter.NewPlayerBun(db)
playerSnapshotRepo := adapter.NewPlayerSnapshotBun(db)
tribeRepo := adapter.NewTribeBun(db)
tribeSnapshotRepo := adapter.NewTribeSnapshotBun(db)
// services
versionSvc := service.NewVersion(versionRepo)

View File

@ -2,14 +2,16 @@ package msg_test
import (
"context"
"errors"
"flag"
"fmt"
"log"
"net"
urlpkg "net/url"
"os"
"testing"
"time"
"gitea.dwysokinski.me/twhelp/core/internal/adapter/bundbtest"
"github.com/ThreeDotsLabs/watermill"
"github.com/ThreeDotsLabs/watermill-amqp/v2/pkg/amqp"
"github.com/ThreeDotsLabs/watermill/message"
@ -17,10 +19,185 @@ import (
"github.com/cenkalti/backoff/v4"
"github.com/ory/dockertest/v3"
"github.com/ory/dockertest/v3/docker"
"github.com/stretchr/testify/assert"
"github.com/pressly/goose/v3"
"github.com/stretchr/testify/require"
"github.com/uptrace/bun"
)
var (
dbDSN = os.Getenv("TESTS_DB_DSN")
rabbitMQURI = os.Getenv("TESTS_AMQP_URI")
)
func TestMain(m *testing.M) {
setUpGoose()
// https://github.com/golang/go/blob/7cfa7d69259590319524c3715df4a39b39924bc3/src/testing/testing.go#L224
flag.Parse()
if (dbDSN != "" && rabbitMQURI != "") || testing.Short() {
os.Exit(m.Run())
}
pool, err := dockertest.NewPool("")
if err != nil {
log.Fatalf("couldn't construct pool: %s", err)
}
pool.MaxWait = 30 * time.Second
if err = pool.Client.Ping(); err != nil {
log.Fatalf("couldn't connect to Docker: %s", err)
}
var resources []*dockertest.Resource
if dbDSN == "" {
resource, dsn := newPostgres(pool)
dbDSN = dsn.String()
resources = append(resources, resource)
}
if rabbitMQURI == "" {
resource, uri := newRabbitMQ(pool)
rabbitMQURI = uri.String()
resources = append(resources, resource)
}
code := m.Run()
for _, r := range resources {
_ = pool.Purge(r)
}
os.Exit(code)
}
func setUpGoose() {
goose.SetBaseFS(os.DirFS("../../migrations"))
goose.SetLogger(goose.NopLogger())
if err := goose.SetDialect("postgres"); err != nil {
log.Fatal(err)
}
}
func newPostgres(pool *dockertest.Pool) (*dockertest.Resource, *urlpkg.URL) {
resource, dsn, err := bundbtest.NewPostgres(pool, 240)
if err != nil {
log.Fatal(err)
}
return resource, dsn
}
func newRabbitMQ(pool *dockertest.Pool) (*dockertest.Resource, *urlpkg.URL) {
uri := &urlpkg.URL{
Scheme: "amqp",
User: urlpkg.UserPassword("rmq", "rmq"),
Path: "/",
}
pw, _ := uri.User.Password()
resource, err := pool.RunWithOptions(&dockertest.RunOptions{
Repository: "rabbitmq",
Tag: "3.12.1-alpine",
Env: []string{
fmt.Sprintf("RABBITMQ_DEFAULT_USER=%s", uri.User.Username()),
fmt.Sprintf("RABBITMQ_DEFAULT_PASS=%s", pw),
},
}, func(config *docker.HostConfig) {
config.AutoRemove = true
config.RestartPolicy = docker.RestartPolicy{
Name: "no",
}
})
if err != nil {
log.Fatalf("couldn't start rabbitmq: %s", err)
}
if err = resource.Expire(180); err != nil {
log.Fatal(err)
}
uri.Host, err = getHostPort(resource, "5672/tcp")
if err != nil {
log.Fatal(err)
}
return resource, uri
}
func getHostPort(resource *dockertest.Resource, id string) (string, error) {
dockerURL := os.Getenv("DOCKER_HOST")
if dockerURL == "" {
return resource.GetHostPort(id), nil
}
u, err := urlpkg.Parse(dockerURL)
if err != nil {
return "", err
}
return net.JoinHostPort(u.Hostname(), resource.GetPort(id)), nil
}
func newBunDB(tb testing.TB) *bun.DB {
tb.Helper()
return bundbtest.NewDB(tb, dbDSN)
}
func newRabbitMQConnection(tb testing.TB) *amqp.ConnectionWrapper {
tb.Helper()
bo := backoff.NewExponentialBackOff()
bo.MaxInterval = 5 * time.Second
bo.MaxElapsedTime = 30 * time.Second
require.NoError(tb, backoff.Retry(func() error {
conn, err := amqp.NewConnection(amqp.ConnectionConfig{AmqpURI: rabbitMQURI}, watermill.NopLogger{})
if err != nil {
return err
}
_ = conn.Close()
return nil
}, bo))
conn, err := amqp.NewConnection(amqp.ConnectionConfig{AmqpURI: rabbitMQURI}, watermill.NopLogger{})
require.NoError(tb, err)
tb.Cleanup(func() {
_ = conn.Close()
})
return conn
}
func newRabbitMQPubSub(
tb testing.TB,
conn *amqp.ConnectionWrapper,
queueNameGenerator amqp.QueueNameGenerator,
exchangeAndRoutingKeyNameGenerator func(topic string) string,
) (*amqp.Publisher, *amqp.Subscriber) {
tb.Helper()
cfg := amqp.NewNonDurablePubSubConfig("", queueNameGenerator)
cfg.Consume.NoRequeueOnNack = true
cfg.Consume.Qos.PrefetchCount = 1
cfg.Exchange.GenerateName = exchangeAndRoutingKeyNameGenerator
cfg.QueueBind.GenerateRoutingKey = exchangeAndRoutingKeyNameGenerator
publisher, err := amqp.NewPublisherWithConnection(cfg, watermill.NopLogger{}, conn)
require.NoError(tb, err)
tb.Cleanup(func() {
_ = publisher.Close()
})
subscriber, err := amqp.NewSubscriberWithConnection(cfg, watermill.NopLogger{}, conn)
require.NoError(tb, err)
tb.Cleanup(func() {
_ = subscriber.Close()
})
return publisher, subscriber
}
type registerer interface {
Register(router *message.Router)
}
@ -90,127 +267,3 @@ func newPubSub(tb testing.TB) *gochannel.GoChannel {
return pubSub
}
func newRabbitMQConnection(tb testing.TB) *amqp.ConnectionWrapper {
tb.Helper()
if uri, ok := os.LookupEnv("TESTS_AMQP_URI"); ok {
return newRabbitMQConnectionWithURI(tb, uri)
}
uri := &urlpkg.URL{
Scheme: "amqp",
User: urlpkg.UserPassword("rmq", "rmq"),
Path: "/",
}
pool, err := dockertest.NewPool("")
require.NoError(tb, err, "couldn't connect to docker")
pool.MaxWait = 20 * time.Second
pw, _ := uri.User.Password()
resource, err := pool.RunWithOptions(&dockertest.RunOptions{
Repository: "rabbitmq",
Tag: "3.11.15-alpine",
Env: []string{
fmt.Sprintf("RABBITMQ_DEFAULT_USER=%s", uri.User.Username()),
fmt.Sprintf("RABBITMQ_DEFAULT_PASS=%s", pw),
},
}, func(config *docker.HostConfig) {
config.AutoRemove = true
config.RestartPolicy = docker.RestartPolicy{
Name: "no",
}
})
require.NoError(tb, err, "couldn't start resource")
tb.Cleanup(func() {
_ = pool.Purge(resource)
})
assert.NoError(tb, resource.Expire(180))
uri.Host = getHostPort(tb, resource, "5672/tcp")
return newRabbitMQConnectionWithURI(tb, uri.String())
}
func newRabbitMQConnectionWithURI(tb testing.TB, uri string) *amqp.ConnectionWrapper {
tb.Helper()
require.NoError(tb, retry(func() error {
conn, err := amqp.NewConnection(amqp.ConnectionConfig{AmqpURI: uri}, watermill.NopLogger{})
if err != nil {
return err
}
_ = conn.Close()
return nil
}))
conn, err := amqp.NewConnection(amqp.ConnectionConfig{AmqpURI: uri}, watermill.NopLogger{})
require.NoError(tb, err)
tb.Cleanup(func() {
_ = conn.Close()
})
return conn
}
func newRabbitMQPubSub(
tb testing.TB,
conn *amqp.ConnectionWrapper,
queueNameGenerator amqp.QueueNameGenerator,
exchangeAndRoutingKeyNameGenerator func(topic string) string,
) (*amqp.Publisher, *amqp.Subscriber) {
tb.Helper()
cfg := amqp.NewNonDurablePubSubConfig("", queueNameGenerator)
cfg.Consume.NoRequeueOnNack = true
cfg.Consume.Qos.PrefetchCount = 1
cfg.Exchange.GenerateName = exchangeAndRoutingKeyNameGenerator
cfg.QueueBind.GenerateRoutingKey = exchangeAndRoutingKeyNameGenerator
publisher, err := amqp.NewPublisherWithConnection(cfg, watermill.NopLogger{}, conn)
require.NoError(tb, err)
tb.Cleanup(func() {
_ = publisher.Close()
})
subscriber, err := amqp.NewSubscriberWithConnection(cfg, watermill.NopLogger{}, conn)
require.NoError(tb, err)
tb.Cleanup(func() {
_ = subscriber.Close()
})
return publisher, subscriber
}
func getHostPort(tb testing.TB, resource *dockertest.Resource, id string) string {
tb.Helper()
dockerURL := os.Getenv("DOCKER_HOST")
if dockerURL == "" {
return resource.GetHostPort(id)
}
u, err := urlpkg.Parse(dockerURL)
require.NoError(tb, err)
return net.JoinHostPort(u.Hostname(), resource.GetPort(id))
}
func retry(op func() error) error {
bo := backoff.NewExponentialBackOff()
bo.MaxInterval = 5 * time.Second
bo.MaxElapsedTime = 30 * time.Second
if err := backoff.Retry(op, bo); err != nil {
if bo.NextBackOff() == backoff.Stop {
return errors.New("reached retry deadline")
}
return err
}
return nil
}