feat: add a new domain model - TribeSnapshotWithRelations
ci/woodpecker/push/govulncheck Pipeline was successful Details
ci/woodpecker/push/test Pipeline was successful Details

This commit is contained in:
Dawid Wysokiński 2024-03-19 07:01:38 +01:00
parent bc1e6617b9
commit 0bec35d0d2
Signed by: Kichiyaki
GPG Key ID: B5445E357FB8B892
7 changed files with 222 additions and 2 deletions

View File

@ -76,6 +76,31 @@ func (repo *TribeSnapshotBunRepository) List(
return domain.NewListTribeSnapshotsResult(separateListResultAndNext(converted, params.Limit()))
}
func (repo *TribeSnapshotBunRepository) ListWithRelations(
ctx context.Context,
params domain.ListTribeSnapshotsParams,
) (domain.ListTribeSnapshotsWithRelationsResult, error) {
var tribeSnapshots bunmodel.TribeSnapshots
if err := repo.db.NewSelect().
Model(&tribeSnapshots).
Apply(listTribeSnapshotsParamsApplier{params: params}.apply).
Relation("Tribe").
Scan(ctx); err != nil && !errors.Is(err, sql.ErrNoRows) {
return domain.ListTribeSnapshotsWithRelationsResult{}, fmt.Errorf(
"couldn't select tribe snapshots from the db: %w",
err,
)
}
converted, err := tribeSnapshots.ToDomainWithRelations()
if err != nil {
return domain.ListTribeSnapshotsWithRelationsResult{}, err
}
return domain.NewListTribeSnapshotsWithRelationsResult(separateListResultAndNext(converted, params.Limit()))
}
type listTribeSnapshotsParamsApplier struct {
params domain.ListTribeSnapshotsParams
}

View File

@ -66,6 +66,10 @@ type tribeChangeRepository interface {
type tribeSnapshotRepository interface {
Create(ctx context.Context, params ...domain.CreateTribeSnapshotParams) error
List(ctx context.Context, params domain.ListTribeSnapshotsParams) (domain.ListTribeSnapshotsResult, error)
ListWithRelations(
ctx context.Context,
params domain.ListTribeSnapshotsParams,
) (domain.ListTribeSnapshotsWithRelationsResult, error)
}
type playerSnapshotRepository interface {

View File

@ -117,7 +117,7 @@ func testTribeSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repos
})
})
t.Run("List", func(t *testing.T) {
t.Run("List & ListWithRelations", func(t *testing.T) {
t.Parallel()
repos := newRepos(t)
@ -154,13 +154,14 @@ func testTribeSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repos
},
},
{
name: "OK: sort=[serverKey DESC, date DESC]",
name: "OK: sort=[serverKey DESC, date DESC, id DESC]",
params: func(t *testing.T) domain.ListTribeSnapshotsParams {
t.Helper()
params := domain.NewListTribeSnapshotsParams()
require.NoError(t, params.SetSort([]domain.TribeSnapshotSort{
domain.TribeSnapshotSortServerKeyDESC,
domain.TribeSnapshotSortDateDESC,
domain.TribeSnapshotSortIDDESC,
}))
return params
},
@ -176,6 +177,7 @@ func testTribeSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repos
return cmp.Or(
cmp.Compare(a.ServerKey(), b.ServerKey()),
a.Date().Compare(b.Date()),
cmp.Compare(a.ID(), b.ID()),
) * -1
}))
},
@ -440,6 +442,14 @@ func testTribeSnapshotRepository(t *testing.T, newRepos func(t *testing.T) repos
res, err := repos.tribeSnapshot.List(ctx, params)
assertError(t, err)
tt.assertResult(t, params, res)
resWithRelations, err := repos.tribeSnapshot.ListWithRelations(ctx, params)
assertError(t, err)
require.Len(t, resWithRelations.TribeSnapshots(), len(res.TribeSnapshots()))
for i, ts := range resWithRelations.TribeSnapshots() {
assert.Equal(t, res.TribeSnapshots()[i], ts.TribeSnapshot())
assert.Equal(t, ts.TribeSnapshot().TribeID(), ts.Tribe().ID())
}
})
}
})

View File

@ -14,6 +14,7 @@ type TribeSnapshot struct {
ID int `bun:"id,pk,autoincrement,identity"`
TribeID int `bun:"tribe_id,nullzero"`
ServerKey string `bun:"server_key,nullzero"`
Tribe Tribe `bun:"tribe,rel:belongs-to,join:tribe_id=id,join:server_key=server_key"`
NumMembers int `bun:"num_members"`
NumVillages int `bun:"num_villages"`
Points int `bun:"points"`
@ -61,8 +62,26 @@ func (ts TribeSnapshot) ToDomain() (domain.TribeSnapshot, error) {
return converted, nil
}
func (ts TribeSnapshot) ToDomainWithRelations() (domain.TribeSnapshotWithRelations, error) {
converted, err := ts.ToDomain()
if err != nil {
return domain.TribeSnapshotWithRelations{}, err
}
tribe, err := ts.Tribe.ToMeta()
if err != nil {
return domain.TribeSnapshotWithRelations{}, err
}
return converted.WithRelations(tribe), nil
}
type TribeSnapshots []TribeSnapshot
func (tss TribeSnapshots) ToDomain() (domain.TribeSnapshots, error) {
return sliceToDomain(tss)
}
func (tss TribeSnapshots) ToDomainWithRelations() (domain.TribeSnapshotsWithRelations, error) {
return sliceToDomainWithRelations(tss)
}

View File

@ -94,3 +94,38 @@ func NewTribeSnapshot(tb TestingTB, opts ...func(cfg *TribeSnapshotConfig)) doma
return ts
}
type TribeSnapshotWithRelationsConfig struct {
TribeSnapshotOptions []func(cfg *TribeSnapshotConfig)
TribeOptions []func(cfg *TribeConfig)
}
func NewTribeSnapshotWithRelations(
tb TestingTB,
opts ...func(cfg *TribeSnapshotWithRelationsConfig),
) domain.TribeSnapshotWithRelations {
tb.Helper()
cfg := &TribeSnapshotWithRelationsConfig{}
for _, opt := range opts {
opt(cfg)
}
ts := NewTribeSnapshot(tb, cfg.TribeSnapshotOptions...)
if ts.TribeID() > 0 {
cfg.TribeOptions = append([]func(cfg *TribeConfig){
func(cfg *TribeConfig) {
cfg.ID = ts.ID()
},
}, cfg.TribeOptions...)
}
var tribe domain.TribeMeta
if len(cfg.TribeOptions) > 0 {
tribe = NewTribe(tb, cfg.TribeOptions...).Meta()
}
return ts.WithRelations(tribe)
}

View File

@ -129,6 +129,13 @@ func (ts TribeSnapshot) CreatedAt() time.Time {
return ts.createdAt
}
func (ts TribeSnapshot) WithRelations(tribe TribeMeta) TribeSnapshotWithRelations {
return TribeSnapshotWithRelations{
snapshot: ts,
tribe: tribe,
}
}
func (ts TribeSnapshot) ToCursor() (TribeSnapshotCursor, error) {
return NewTribeSnapshotCursor(ts.id, ts.serverKey, ts.date)
}
@ -139,6 +146,25 @@ func (ts TribeSnapshot) IsZero() bool {
type TribeSnapshots []TribeSnapshot
type TribeSnapshotWithRelations struct {
snapshot TribeSnapshot
tribe TribeMeta
}
func (ts TribeSnapshotWithRelations) TribeSnapshot() TribeSnapshot {
return ts.snapshot
}
func (ts TribeSnapshotWithRelations) Tribe() TribeMeta {
return ts.tribe
}
func (ts TribeSnapshotWithRelations) IsZero() bool {
return ts.snapshot.IsZero()
}
type TribeSnapshotsWithRelations []TribeSnapshotWithRelations
type CreateTribeSnapshotParams struct {
tribeID int
serverKey string
@ -536,3 +562,57 @@ func (res ListTribeSnapshotsResult) Self() TribeSnapshotCursor {
func (res ListTribeSnapshotsResult) Next() TribeSnapshotCursor {
return res.next
}
type ListTribeSnapshotsWithRelationsResult struct {
snapshots TribeSnapshotsWithRelations
self TribeSnapshotCursor
next TribeSnapshotCursor
}
const listTribeSnapshotsWithRelationsResultModelName = "ListTribeSnapshotsWithRelationsResult"
func NewListTribeSnapshotsWithRelationsResult(
snapshots TribeSnapshotsWithRelations,
next TribeSnapshotWithRelations,
) (ListTribeSnapshotsWithRelationsResult, error) {
var err error
res := ListTribeSnapshotsWithRelationsResult{
snapshots: snapshots,
}
if len(snapshots) > 0 {
res.self, err = snapshots[0].TribeSnapshot().ToCursor()
if err != nil {
return ListTribeSnapshotsWithRelationsResult{}, ValidationError{
Model: listTribeSnapshotsWithRelationsResultModelName,
Field: "self",
Err: err,
}
}
}
if !next.IsZero() {
res.next, err = next.TribeSnapshot().ToCursor()
if err != nil {
return ListTribeSnapshotsWithRelationsResult{}, ValidationError{
Model: listTribeSnapshotsWithRelationsResultModelName,
Field: "next",
Err: err,
}
}
}
return res, nil
}
func (res ListTribeSnapshotsWithRelationsResult) TribeSnapshots() TribeSnapshotsWithRelations {
return res.snapshots
}
func (res ListTribeSnapshotsWithRelationsResult) Self() TribeSnapshotCursor {
return res.self
}
func (res ListTribeSnapshotsWithRelationsResult) Next() TribeSnapshotCursor {
return res.next
}

View File

@ -585,3 +585,50 @@ func TestNewListTribeSnapshotsResult(t *testing.T) {
assert.True(t, res.Next().IsZero())
})
}
func TestNewListTribeSnapshotsWithRelationsResult(t *testing.T) {
t.Parallel()
snapshots := domain.TribeSnapshotsWithRelations{
domaintest.NewTribeSnapshotWithRelations(t),
domaintest.NewTribeSnapshotWithRelations(t),
domaintest.NewTribeSnapshotWithRelations(t),
}
next := domaintest.NewTribeSnapshotWithRelations(t)
t.Run("OK: with next", func(t *testing.T) {
t.Parallel()
res, err := domain.NewListTribeSnapshotsWithRelationsResult(snapshots, next)
require.NoError(t, err)
assert.Equal(t, snapshots, res.TribeSnapshots())
assert.Equal(t, snapshots[0].TribeSnapshot().ID(), res.Self().ID())
assert.Equal(t, snapshots[0].TribeSnapshot().ServerKey(), res.Self().ServerKey())
assert.Equal(t, snapshots[0].TribeSnapshot().Date(), res.Self().Date())
assert.Equal(t, next.TribeSnapshot().ID(), res.Next().ID())
assert.Equal(t, next.TribeSnapshot().ServerKey(), res.Next().ServerKey())
assert.Equal(t, next.TribeSnapshot().Date(), res.Next().Date())
})
t.Run("OK: without next", func(t *testing.T) {
t.Parallel()
res, err := domain.NewListTribeSnapshotsWithRelationsResult(snapshots, domain.TribeSnapshotWithRelations{})
require.NoError(t, err)
assert.Equal(t, snapshots, res.TribeSnapshots())
assert.Equal(t, snapshots[0].TribeSnapshot().ID(), res.Self().ID())
assert.Equal(t, snapshots[0].TribeSnapshot().ServerKey(), res.Self().ServerKey())
assert.Equal(t, snapshots[0].TribeSnapshot().Date(), res.Self().Date())
assert.True(t, res.Next().IsZero())
})
t.Run("OK: 0 snapshots", func(t *testing.T) {
t.Parallel()
res, err := domain.NewListTribeSnapshotsWithRelationsResult(nil, domain.TribeSnapshotWithRelations{})
require.NoError(t, err)
assert.Zero(t, res.TribeSnapshots())
assert.True(t, res.Self().IsZero())
assert.True(t, res.Next().IsZero())
})
}