add serverstats usecase, repository and resolvers
This commit is contained in:
parent
ca2cb4debe
commit
c40369a911
2
go.mod
2
go.mod
|
@ -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
2
go.sum
|
@ -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
|
@ -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"`
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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!
|
||||
}
|
4
main.go
4
main.go
|
@ -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),
|
||||
},
|
||||
})
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package serverstats
|
||||
|
||||
const (
|
||||
PaginationLimit = 60
|
||||
)
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
Reference in New Issue