add serverstats usecase, repository and resolvers

This commit is contained in:
Dawid Wysokiński 2020-06-21 13:51:26 +02:00
parent ca2cb4debe
commit c40369a911
14 changed files with 1115 additions and 1 deletions

2
go.mod
View File

@ -13,7 +13,7 @@ require (
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/pkg/errors v0.9.1
github.com/segmentio/encoding v0.1.14 // indirect
github.com/tribalwarshelp/shared v0.0.0-20200621083628-e0fdaa9bdff6
github.com/tribalwarshelp/shared v0.0.0-20200621113135-f37b4069eaaf
github.com/vektah/gqlparser/v2 v2.0.1
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect

2
go.sum
View File

@ -170,6 +170,8 @@ github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYm
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs=
github.com/tribalwarshelp/shared v0.0.0-20200621083628-e0fdaa9bdff6 h1:HjOXWkYjCl9cs6Jd0VUByJEPKE8TXVz6CHB88f8wPXk=
github.com/tribalwarshelp/shared v0.0.0-20200621083628-e0fdaa9bdff6/go.mod h1:tf+2yTHasV6jAF3V2deZ9slNoCyBzC0fMdTjI7clf6Y=
github.com/tribalwarshelp/shared v0.0.0-20200621113135-f37b4069eaaf h1:FoZBGciPITYC26jh6CzEvRhKdm0c3TaCNs1WUCPS9pM=
github.com/tribalwarshelp/shared v0.0.0-20200621113135-f37b4069eaaf/go.mod h1:tf+2yTHasV6jAF3V2deZ9slNoCyBzC0fMdTjI7clf6Y=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,11 @@ type PlayersList struct {
Total int `json:"total"`
}
type ServerStatsList struct {
Items []*models.ServerStats `json:"items"`
Total int `json:"total"`
}
type ServersList struct {
Items []*models.Server `json:"items"`
Total int `json:"total"`

View File

@ -86,3 +86,7 @@ models:
model: github.com/tribalwarshelp/shared/models.TribeHistory
TribeHistoryFilter:
model: github.com/tribalwarshelp/shared/models.TribeHistoryFilter
ServerStatsRecord:
model: github.com/tribalwarshelp/shared/models.ServerStats
ServerStatsFilter:
model: github.com/tribalwarshelp/shared/models.ServerStatsFilter

View File

@ -8,6 +8,7 @@ import (
"github.com/tribalwarshelp/api/player"
"github.com/tribalwarshelp/api/playerhistory"
"github.com/tribalwarshelp/api/server"
"github.com/tribalwarshelp/api/serverstats"
"github.com/tribalwarshelp/api/tribe"
"github.com/tribalwarshelp/api/tribehistory"
"github.com/tribalwarshelp/api/village"
@ -23,6 +24,7 @@ type Resolver struct {
EnnoblementUcase ennoblement.Usecase
PlayerHistoryUcase playerhistory.Usecase
TribeHistoryUcase tribehistory.Usecase
ServerStatsUcase serverstats.Usecase
}
// Query returns generated.QueryResolver implementation.
@ -34,6 +36,9 @@ func (r *Resolver) LiveEnnoblement() generated.LiveEnnoblementResolver {
}
func (r *Resolver) Ennoblement() generated.EnnoblementResolver { return &ennoblementResolver{r} }
func (r *Resolver) Server() generated.ServerResolver { return &serverResolver{r} }
func (r *Resolver) ServerStatsRecord() generated.ServerStatsRecordResolver {
return &serverStatsRecordResolver{r}
}
func (r *Resolver) PlayerHistoryRecord() generated.PlayerHistoryRecordResolver {
return &playerHistoryRecordResolver{r}
}
@ -49,3 +54,4 @@ type ennoblementResolver struct{ *Resolver }
type serverResolver struct{ *Resolver }
type playerHistoryRecordResolver struct{ *Resolver }
type tribeHistoryRecordResolver struct{ *Resolver }
type serverStatsRecordResolver struct{ *Resolver }

View File

@ -0,0 +1,23 @@
package resolvers
import (
"context"
"time"
"github.com/tribalwarshelp/api/graphql/generated"
"github.com/tribalwarshelp/api/utils"
"github.com/tribalwarshelp/shared/models"
)
func (r *serverStatsRecordResolver) CreatedAt(ctx context.Context, obj *models.ServerStats) (*time.Time, error) {
server, _ := getServer(ctx)
t := formatDate(ctx, utils.LanguageTagFromServerKey(server), obj.CreatedAt)
return &t, nil
}
func (r *Resolver) ServerStats(ctx context.Context, server string, filter *models.ServerStatsFilter) (*generated.ServerStatsList, error) {
var err error
list := &generated.ServerStatsList{}
list.Items, list.Total, err = r.ServerStatsUcase.Fetch(ctx, server, filter)
return list, err
}

View File

@ -0,0 +1,34 @@
type ServerStatsRecord {
activePlayers: Int!
inactivePlayers: Int!
players: Int!
activeTribes: Int!
inactiveTribes: Int!
tribes: Int!
bonusVillages: Int!
barbarianVillages: Int!
playerVillages: Int!
villages: Int!
createdAt: Time! @goField(forceResolver: true)
}
type ServerStatsList {
items: [ServerStatsRecord!]
total: Int!
}
input ServerStatsFilter {
createdAt: Time
createdAtGT: Time
createdAtGTE: Time
createdAtLT: Time
createdAtLTE: Time
offset: Int
limit: Int
sort: String
}
extend type Query {
serverStats(server: String!, filter: ServerStatsFilter): ServerStatsList!
}

View File

@ -30,6 +30,8 @@ import (
playerhistoryucase "github.com/tribalwarshelp/api/playerhistory/usecase"
serverrepo "github.com/tribalwarshelp/api/server/repository"
serverucase "github.com/tribalwarshelp/api/server/usecase"
serverstatsrepo "github.com/tribalwarshelp/api/serverstats/repository"
serverstatsucase "github.com/tribalwarshelp/api/serverstats/usecase"
triberepo "github.com/tribalwarshelp/api/tribe/repository"
tribeucase "github.com/tribalwarshelp/api/tribe/usecase"
tribehistoryrepo "github.com/tribalwarshelp/api/tribehistory/repository"
@ -92,6 +94,7 @@ func main() {
ennoblementRepo := ennoblementrepo.NewPGRepository(db)
tribehistoryRepo := tribehistoryrepo.NewPGRepository(db)
playerhistoryRepo := playerhistoryrepo.NewPGRepository(db)
serverstatsRepo := serverstatsrepo.NewPGRepository(db)
liveennoblementRepo := liveennoblementrepo.NewPGRepository(db, redisClient)
router := gin.Default()
@ -114,6 +117,7 @@ func main() {
LiveEnnoblementUcase: liveennoblementucase.New(liveennoblementRepo),
TribeHistoryUcase: tribehistoryucase.New(tribehistoryRepo),
PlayerHistoryUcase: playerhistoryucase.New(playerhistoryRepo),
ServerStatsUcase: serverstatsucase.New(serverstatsRepo),
},
})

5
serverstats/constants.go Normal file
View File

@ -0,0 +1,5 @@
package serverstats
const (
PaginationLimit = 60
)

11
serverstats/repository.go Normal file
View File

@ -0,0 +1,11 @@
package serverstats
import (
"context"
"github.com/tribalwarshelp/shared/models"
)
type Repository interface {
Fetch(ctx context.Context, server string, filter *models.ServerStatsFilter) ([]*models.ServerStats, int, error)
}

View File

@ -0,0 +1,47 @@
package repository
import (
"context"
"fmt"
"strings"
"github.com/go-pg/pg/v10"
"github.com/pkg/errors"
"github.com/tribalwarshelp/api/serverstats"
"github.com/tribalwarshelp/shared/models"
)
type pgRepository struct {
*pg.DB
}
func NewPGRepository(db *pg.DB) serverstats.Repository {
return &pgRepository{db}
}
func (repo *pgRepository) Fetch(ctx context.Context, server string, f *models.ServerStatsFilter) ([]*models.ServerStats, int, error) {
var err error
data := []*models.ServerStats{}
query := repo.WithParam("SERVER", pg.Safe(server)).Model(&data).Context(ctx)
if f != nil {
query = query.
WhereStruct(f).
Limit(f.Limit).
Offset(f.Offset)
if f.Sort != "" {
query = query.Order(f.Sort)
}
}
total, err := query.SelectAndCount()
if err != nil && err != pg.ErrNoRows {
if strings.Contains(err.Error(), `relation "`+server) {
return nil, 0, fmt.Errorf("Server not found")
}
return nil, 0, errors.Wrap(err, "Internal server error")
}
return data, total, nil
}

11
serverstats/usecase.go Normal file
View File

@ -0,0 +1,11 @@
package serverstats
import (
"context"
"github.com/tribalwarshelp/shared/models"
)
type Usecase interface {
Fetch(ctx context.Context, server string, filter *models.ServerStatsFilter) ([]*models.ServerStats, int, error)
}

View File

@ -0,0 +1,28 @@
package usecase
import (
"context"
"github.com/tribalwarshelp/api/serverstats"
"github.com/tribalwarshelp/api/utils"
"github.com/tribalwarshelp/shared/models"
)
type usecase struct {
repo serverstats.Repository
}
func New(repo serverstats.Repository) serverstats.Usecase {
return &usecase{repo}
}
func (ucase *usecase) Fetch(ctx context.Context, server string, filter *models.ServerStatsFilter) ([]*models.ServerStats, int, error) {
if filter == nil {
filter = &models.ServerStatsFilter{}
}
if filter.Limit > serverstats.PaginationLimit || filter.Limit <= 0 {
filter.Limit = serverstats.PaginationLimit
}
filter.Sort = utils.SanitizeSort(filter.Sort)
return ucase.repo.Fetch(ctx, server, filter)
}