diff --git a/README.md b/README.md index edebc9e..1f4c7b7 100644 --- a/README.md +++ b/README.md @@ -1,78 +1,83 @@ # TWHelp API -A GraphQL API for Tribal Wars data. All versions are available. +A GraphQL API for Tribal Wars data. ## API Limits -You can fetch in one HTTP request: +You can fetch in one GraphQL query: -1. 1000 daily player/tribe stats -2. 100 ennoblements -3. 100 versions -4. 100 players/tribes +1. 1000 daily player/tribe stats records +2. 200 ennoblements +3. 30 versions +4. 200 players/tribes 5. 1000 villages 6. 100 player/tribe history records 7. 100 servers -8. 60 server stats +8. 60 server stats records 9. 100 tribe changes ## Sample queries You can check how to make requests from JavaScript [here](https://github.com/tribalwarshelp/scripts). -1. All barbarian villages with 10% more population +1. All bonus villages with 10% more population ```graphql query { - villages(server: "en115", filter: { playerID: [0], bonus: 4 }) { - total - items { - id - name - x - y - points + villages(server: "en115", filter: { playerID: [0], bonus: 4 }) { + total + items { + id + name + x + y + points + } } - } } + ``` 2. Top 30 players without a tribe, ordered by points. ```graphql query { - players( - server: "pl148" - filter: { tribeID: [0], sort: "points DESC", limit: 30 } - ) { - total - items { - id - name - rank - points - totalVillages - rankAtt - rankDef - rankTotal - rankSup + players( + server: "pl148" + filter: { tribeID: [0] } + sort: ["points DESC"] + limit: 30 + ) { + total + items { + id + name + rank + points + totalVillages + rankAtt + rankDef + rankTotal + rankSup + } } - } } + ``` 3. Search a player by a nickname fragment. ```graphql query { - players(server: "pl148", filter: { nameIEQ: "%pablo%" }) { - total - items { - id - name + players(server: "pl148", filter: { nameIEQ: "%pablo%" }) { + total + items { + id + name + } } - } } + ``` ## Map service @@ -112,8 +117,6 @@ DB_NAME=your_pgdb_name DB_PORT=your_pgdb_port DB_HOST=your_pgdb_host DB_PASSWORD=your_pgdb_password -REDIS_HOST=your_redis_host -REDIS_PORT=your_redis_port LIMIT_WHITELIST=127.0.0.1,::1 LOG_DB_QUERIES=[true|false] ``` diff --git a/dailyplayerstats/repository.go b/dailyplayerstats/repository.go index 2158b6a..ec5276d 100644 --- a/dailyplayerstats/repository.go +++ b/dailyplayerstats/repository.go @@ -9,6 +9,7 @@ import ( type FetchConfig struct { Server string Filter *models.DailyPlayerStatsFilter + Select bool Count bool Sort []string Limit int diff --git a/dailyplayerstats/repository/pg_repository.go b/dailyplayerstats/repository/pg_repository.go index a8cc8e3..e251d9e 100644 --- a/dailyplayerstats/repository/pg_repository.go +++ b/dailyplayerstats/repository/pg_repository.go @@ -38,10 +38,12 @@ func (repo *pgRepository) Fetch(ctx context.Context, cfg dailyplayerstats.FetchC } query = query.Apply(relationshipAndSortAppender.Append) - if cfg.Count { + if cfg.Count && cfg.Select { total, err = query.SelectAndCount() - } else { + } else if cfg.Select { err = query.Select() + } else if cfg.Count { + total, err = query.Count() } if err != nil && err != pg.ErrNoRows { if strings.Contains(err.Error(), `relation "`+cfg.Server) { diff --git a/dailyplayerstats/usecase/dailyplayerstats_usecase.go b/dailyplayerstats/usecase/dailyplayerstats_usecase.go index 4033672..1a9229b 100644 --- a/dailyplayerstats/usecase/dailyplayerstats_usecase.go +++ b/dailyplayerstats/usecase/dailyplayerstats_usecase.go @@ -21,7 +21,6 @@ func (ucase *usecase) Fetch(ctx context.Context, cfg dailyplayerstats.FetchConfi if cfg.Filter == nil { cfg.Filter = &models.DailyPlayerStatsFilter{} } - if !middleware.CanExceedLimit(ctx) && (cfg.Limit > dailyplayerstats.FetchLimit || cfg.Limit <= 0) { cfg.Limit = dailyplayerstats.FetchLimit } diff --git a/dailytribestats/repository.go b/dailytribestats/repository.go index 605986d..d816e86 100644 --- a/dailytribestats/repository.go +++ b/dailytribestats/repository.go @@ -9,6 +9,7 @@ import ( type FetchConfig struct { Server string Filter *models.DailyTribeStatsFilter + Select bool Count bool Sort []string Limit int diff --git a/dailytribestats/repository/pg_repository.go b/dailytribestats/repository/pg_repository.go index ad44e64..d67eec6 100644 --- a/dailytribestats/repository/pg_repository.go +++ b/dailytribestats/repository/pg_repository.go @@ -38,10 +38,12 @@ func (repo *pgRepository) Fetch(ctx context.Context, cfg dailytribestats.FetchCo } query = query.Apply(relationshipAndSortAppender.Append) - if cfg.Count { + if cfg.Count && cfg.Select { total, err = query.SelectAndCount() - } else { + } else if cfg.Select { err = query.Select() + } else if cfg.Count { + total, err = query.Count() } if err != nil && err != pg.ErrNoRows { if strings.Contains(err.Error(), `relation "`+cfg.Server) { diff --git a/ennoblement/repository.go b/ennoblement/repository.go index 13302a3..3e4f1e7 100644 --- a/ennoblement/repository.go +++ b/ennoblement/repository.go @@ -9,6 +9,7 @@ import ( type FetchConfig struct { Server string Filter *models.EnnoblementFilter + Select bool Count bool Sort []string Limit int diff --git a/ennoblement/repository/pg_repository.go b/ennoblement/repository/pg_repository.go index cf2f1f9..4ba4dd7 100644 --- a/ennoblement/repository/pg_repository.go +++ b/ennoblement/repository/pg_repository.go @@ -38,10 +38,12 @@ func (repo *pgRepository) Fetch(ctx context.Context, cfg ennoblement.FetchConfig } query = query.Apply(relationshipAndSortAppender.Append) - if cfg.Count { + if cfg.Count && cfg.Select { total, err = query.SelectAndCount() - } else { + } else if cfg.Select { err = query.Select() + } else if cfg.Count { + total, err = query.Count() } if err != nil && err != pg.ErrNoRows { if strings.Contains(err.Error(), `relation "`+cfg.Server) { diff --git a/go.sum b/go.sum index d2094fe..80150ec 100644 --- a/go.sum +++ b/go.sum @@ -160,8 +160,6 @@ github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GH github.com/tribalwarshelp/map-generator v0.0.0-20210106163923-fa048a59f5f2 h1:yYSQuWN6YvY0cL77Ha7Y350Xm2/J+6suHubv5F/ZluY= github.com/tribalwarshelp/map-generator v0.0.0-20210106163923-fa048a59f5f2/go.mod h1:ywyp0CZ3JsJ+0GAbUJVWo3dipHcAohD7KkV2TNbiTHU= github.com/tribalwarshelp/shared v0.0.0-20210106162314-d3488036ca2f/go.mod h1:vtDs7EjEysk4dpFPfu3c4lkICXZYIRV0BrT7rsqG0dw= -github.com/tribalwarshelp/shared v0.0.0-20210115163415-972e2df3f7db h1:RzMEF4BP3YJ7jJOyYO00TdeB6DY7g0Dp/8cQ8t6WKzw= -github.com/tribalwarshelp/shared v0.0.0-20210115163415-972e2df3f7db/go.mod h1:vtDs7EjEysk4dpFPfu3c4lkICXZYIRV0BrT7rsqG0dw= github.com/tribalwarshelp/shared v0.0.0-20210321105345-7a8582fd0b91 h1:YxUIaDrLe3nE+8MHWxcGn1f/Ic0AfC/iS8/tnHAm2iE= github.com/tribalwarshelp/shared v0.0.0-20210321105345-7a8582fd0b91/go.mod h1:EnTN6KBL5jZZnan7cVOWIsAO3q+a1XNPpa9m6Pv3MeM= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= diff --git a/graphql/dataloaders/data_loaders.go b/graphql/dataloaders/data_loaders.go index 0de6335..64f40e3 100644 --- a/graphql/dataloaders/data_loaders.go +++ b/graphql/dataloaders/data_loaders.go @@ -11,6 +11,10 @@ import ( "github.com/tribalwarshelp/shared/models" ) +const ( + wait = 4 * time.Millisecond +) + type DataLoaders struct { VersionByCode *VersionLoader } @@ -25,7 +29,7 @@ type Config struct { func NewDataLoaders(cfg Config) *DataLoaders { return &DataLoaders{ VersionByCode: &VersionLoader{ - wait: 4 * time.Millisecond, + wait: wait, maxBatch: 0, fetch: func(keys []string) ([]*models.Version, []error) { codes := []models.VersionCode{} @@ -36,6 +40,7 @@ func NewDataLoaders(cfg Config) *DataLoaders { Filter: &models.VersionFilter{ Code: codes, }, + Select: true, }) if err != nil { return nil, []error{err} diff --git a/graphql/dataloaders/server_data_loaders.go b/graphql/dataloaders/server_data_loaders.go index cabb7dd..d1ac6a7 100644 --- a/graphql/dataloaders/server_data_loaders.go +++ b/graphql/dataloaders/server_data_loaders.go @@ -2,8 +2,6 @@ package dataloaders import ( "context" - "time" - "github.com/tribalwarshelp/api/player" "github.com/tribalwarshelp/api/tribe" "github.com/tribalwarshelp/api/village" @@ -19,13 +17,14 @@ type ServerDataLoaders struct { func NewServerDataLoaders(server string, cfg Config) *ServerDataLoaders { return &ServerDataLoaders{ PlayerByID: &PlayerLoader{ - wait: 2 * time.Millisecond, + wait: wait, maxBatch: 0, fetch: func(ids []int) ([]*models.Player, []error) { players, _, err := cfg.PlayerRepo.Fetch(context.Background(), player.FetchConfig{ Filter: &models.PlayerFilter{ ID: ids, }, + Select: true, Server: server, }) if err != nil { @@ -46,7 +45,7 @@ func NewServerDataLoaders(server string, cfg Config) *ServerDataLoaders { }, }, TribeByID: &TribeLoader{ - wait: 2 * time.Millisecond, + wait: wait, maxBatch: 0, fetch: func(ids []int) ([]*models.Tribe, []error) { tribes, _, err := cfg.TribeRepo.Fetch(context.Background(), tribe.FetchConfig{ @@ -54,6 +53,7 @@ func NewServerDataLoaders(server string, cfg Config) *ServerDataLoaders { Filter: &models.TribeFilter{ ID: ids, }, + Select: true, }) if err != nil { return nil, []error{err} @@ -73,7 +73,7 @@ func NewServerDataLoaders(server string, cfg Config) *ServerDataLoaders { }, }, VillageByID: &VillageLoader{ - wait: 2 * time.Millisecond, + wait: wait, maxBatch: 0, fetch: func(ids []int) ([]*models.Village, []error) { villages, _, err := cfg.VillageRepo.Fetch(context.Background(), village.FetchConfig{ @@ -82,6 +82,7 @@ func NewServerDataLoaders(server string, cfg Config) *ServerDataLoaders { Filter: &models.VillageFilter{ ID: ids, }, + Select: true, }) if err != nil { return nil, []error{err} diff --git a/graphql/dataloaders/version_data_loaders.go b/graphql/dataloaders/version_data_loaders.go index d7ec337..6e5101f 100644 --- a/graphql/dataloaders/version_data_loaders.go +++ b/graphql/dataloaders/version_data_loaders.go @@ -2,8 +2,6 @@ package dataloaders import ( "context" - "time" - "github.com/tribalwarshelp/shared/models" ) @@ -15,7 +13,7 @@ type VersionDataLoaders struct { func NewVersionDataLoaders(versionCode models.VersionCode, cfg Config) *VersionDataLoaders { return &VersionDataLoaders{ PlayerServersByID: &PlayerServersLoader{ - wait: 2 * time.Millisecond, + wait: wait, maxBatch: 0, fetch: func(keys []int) ([][]string, []error) { playerServersByID, err := cfg.PlayerRepo.FetchPlayerServers(context.Background(), versionCode, keys...) @@ -30,7 +28,7 @@ func NewVersionDataLoaders(versionCode models.VersionCode, cfg Config) *VersionD }, }, PlayerNameChangesByID: &PlayerNameChangesLoader{ - wait: 2 * time.Millisecond, + wait: wait, maxBatch: 0, fetch: func(keys []int) ([][]*models.PlayerNameChange, []error) { playerNameChangesByID, err := cfg.PlayerRepo.FetchNameChanges(context.Background(), versionCode, keys...) diff --git a/graphql/resolvers/daily_player_stats.go b/graphql/resolvers/daily_player_stats.go index 4aaa8f7..ecc9939 100644 --- a/graphql/resolvers/daily_player_stats.go +++ b/graphql/resolvers/daily_player_stats.go @@ -31,6 +31,7 @@ func (r *queryResolver) DailyPlayerStats(ctx context.Context, Sort: sort, Limit: utils.SafeIntPointer(limit, 0), Offset: utils.SafeIntPointer(offset, 0), + Select: shouldSelectItems(ctx), Count: shouldCount(ctx), }) return list, err diff --git a/graphql/resolvers/daily_tribe_stats.go b/graphql/resolvers/daily_tribe_stats.go index 87c19e1..d7f61fa 100644 --- a/graphql/resolvers/daily_tribe_stats.go +++ b/graphql/resolvers/daily_tribe_stats.go @@ -31,6 +31,7 @@ func (r *queryResolver) DailyTribeStats(ctx context.Context, Sort: sort, Limit: utils.SafeIntPointer(limit, 0), Offset: utils.SafeIntPointer(offset, 0), + Select: shouldSelectItems(ctx), Count: shouldCount(ctx), }) return list, err diff --git a/graphql/resolvers/ennoblement.go b/graphql/resolvers/ennoblement.go index 53eb22a..0ee62a6 100644 --- a/graphql/resolvers/ennoblement.go +++ b/graphql/resolvers/ennoblement.go @@ -63,6 +63,7 @@ func (r *queryResolver) Ennoblements(ctx context.Context, server string, Limit: utils.SafeIntPointer(limit, 0), Offset: utils.SafeIntPointer(offset, 0), Count: shouldCount(ctx), + Select: shouldSelectItems(ctx), }) return list, err } diff --git a/graphql/resolvers/helpers.go b/graphql/resolvers/helpers.go index 5fd7434..a3653dd 100644 --- a/graphql/resolvers/helpers.go +++ b/graphql/resolvers/helpers.go @@ -67,11 +67,19 @@ func getTribe(ctx context.Context, id int) *models.Tribe { return nil } -func shouldCount(ctx context.Context) bool { +func findField(ctx context.Context, name string) bool { for _, field := range graphql.CollectFieldsCtx(ctx, nil) { - if field.Name == countField { + if field.Name == name { return true } } return false } + +func shouldCount(ctx context.Context) bool { + return findField(ctx, countField) +} + +func shouldSelectItems(ctx context.Context) bool { + return findField(ctx, itemsField) +} diff --git a/graphql/resolvers/player.go b/graphql/resolvers/player.go index 818b38e..d3c8e60 100644 --- a/graphql/resolvers/player.go +++ b/graphql/resolvers/player.go @@ -62,6 +62,7 @@ func (r *queryResolver) Players(ctx context.Context, Limit: utils.SafeIntPointer(limit, 0), Offset: utils.SafeIntPointer(offset, 0), Count: shouldCount(ctx), + Select: shouldSelectItems(ctx), }) return list, err } diff --git a/graphql/resolvers/player_history.go b/graphql/resolvers/player_history.go index 95e547a..6035261 100644 --- a/graphql/resolvers/player_history.go +++ b/graphql/resolvers/player_history.go @@ -40,6 +40,7 @@ func (r *Resolver) PlayerHistory(ctx context.Context, Limit: utils.SafeIntPointer(limit, 0), Offset: utils.SafeIntPointer(offset, 0), Count: shouldCount(ctx), + Select: shouldSelectItems(ctx), }) return list, err } diff --git a/graphql/resolvers/resolver.go b/graphql/resolvers/resolver.go index 74027f0..3bc4a7f 100644 --- a/graphql/resolvers/resolver.go +++ b/graphql/resolvers/resolver.go @@ -18,6 +18,7 @@ import ( const ( countField = "total" + itemsField = "items" ) type Resolver struct { diff --git a/graphql/resolvers/server.go b/graphql/resolvers/server.go index 6fe2e04..87ecc40 100644 --- a/graphql/resolvers/server.go +++ b/graphql/resolvers/server.go @@ -33,6 +33,7 @@ func (r *queryResolver) Servers(ctx context.Context, Limit: utils.SafeIntPointer(limit, 0), Offset: utils.SafeIntPointer(offset, 0), Count: shouldCount(ctx), + Select: shouldSelectItems(ctx), }) return list, err } diff --git a/graphql/resolvers/server_stats.go b/graphql/resolvers/server_stats.go index c306cfa..fde66de 100644 --- a/graphql/resolvers/server_stats.go +++ b/graphql/resolvers/server_stats.go @@ -24,6 +24,7 @@ func (r *Resolver) ServerStats(ctx context.Context, Limit: utils.SafeIntPointer(limit, 0), Offset: utils.SafeIntPointer(offset, 0), Count: shouldCount(ctx), + Select: shouldSelectItems(ctx), }) return list, err } diff --git a/graphql/resolvers/tribe.go b/graphql/resolvers/tribe.go index 528f5f0..79bee9e 100644 --- a/graphql/resolvers/tribe.go +++ b/graphql/resolvers/tribe.go @@ -24,6 +24,7 @@ func (r *queryResolver) Tribes(ctx context.Context, Limit: utils.SafeIntPointer(limit, 0), Offset: utils.SafeIntPointer(offset, 0), Count: shouldCount(ctx), + Select: shouldSelectItems(ctx), }) return list, err } diff --git a/graphql/resolvers/tribe_change.go b/graphql/resolvers/tribe_change.go index b510421..5afde8a 100644 --- a/graphql/resolvers/tribe_change.go +++ b/graphql/resolvers/tribe_change.go @@ -47,6 +47,7 @@ func (r *Resolver) TribeChanges(ctx context.Context, Limit: utils.SafeIntPointer(limit, 0), Offset: utils.SafeIntPointer(offset, 0), Count: shouldCount(ctx), + Select: shouldSelectItems(ctx), Server: server, }) return list, err diff --git a/graphql/resolvers/tribe_history.go b/graphql/resolvers/tribe_history.go index f450bc6..a89d381 100644 --- a/graphql/resolvers/tribe_history.go +++ b/graphql/resolvers/tribe_history.go @@ -31,6 +31,7 @@ func (r *Resolver) TribeHistory(ctx context.Context, Limit: utils.SafeIntPointer(limit, 0), Offset: utils.SafeIntPointer(offset, 0), Count: shouldCount(ctx), + Select: shouldSelectItems(ctx), Server: server, }) return list, err diff --git a/graphql/resolvers/version.go b/graphql/resolvers/version.go index eef57aa..11fc905 100644 --- a/graphql/resolvers/version.go +++ b/graphql/resolvers/version.go @@ -21,6 +21,7 @@ func (r *queryResolver) Versions(ctx context.Context, Sort: sort, Limit: utils.SafeIntPointer(limit, 0), Offset: utils.SafeIntPointer(offset, 0), + Select: shouldSelectItems(ctx), Count: shouldCount(ctx), }) return list, err diff --git a/graphql/resolvers/village.go b/graphql/resolvers/village.go index 7dcf51f..02c9fbe 100644 --- a/graphql/resolvers/village.go +++ b/graphql/resolvers/village.go @@ -30,6 +30,7 @@ func (r *queryResolver) Villages(ctx context.Context, Sort: sort, Limit: utils.SafeIntPointer(limit, 0), Offset: utils.SafeIntPointer(offset, 0), + Select: shouldSelectItems(ctx), Count: shouldCount(ctx), Server: server, }) diff --git a/middleware/dataloaders_to_context.go b/middleware/dataloaders_to_context.go index f311ac3..c977040 100644 --- a/middleware/dataloaders_to_context.go +++ b/middleware/dataloaders_to_context.go @@ -29,6 +29,7 @@ func DataLoadersToContext(dltcc DataLoadersToContextConfig, cfg dataloaders.Conf versionDataLoaders := make(map[models.VersionCode]*dataloaders.VersionDataLoaders) servers, _, err := dltcc.ServerRepo.Fetch(c.Request.Context(), server.FetchConfig{ Columns: []string{utils.Underscore("versionCode"), "key"}, + Select: true, }) if err != nil { c.JSON(http.StatusInternalServerError, &gqlerror.Error{ diff --git a/middleware/limit_whitelist.go b/middleware/limit_whitelist.go index 8a5be0f..b3c6d29 100644 --- a/middleware/limit_whitelist.go +++ b/middleware/limit_whitelist.go @@ -16,13 +16,13 @@ type NetworksAndIps struct { } func (networksAndIps NetworksAndIps) Contains(ip net.IP) bool { - for _, expectedIP := range networksAndIps.Ips { - if expectedIP.Equal(ip) { + for _, whitelistedIP := range networksAndIps.Ips { + if whitelistedIP.Equal(ip) { return true } } - for _, subnetwork := range networksAndIps.Networks { - if subnetwork.Contains(ip) { + for _, network := range networksAndIps.Networks { + if network.Contains(ip) { return true } } @@ -43,7 +43,10 @@ func (cfg LimitWhitelistConfig) GetNetworksAndIps() NetworksAndIps { continue } - ips = append(ips, net.ParseIP(ip)) + parsed := net.ParseIP(ip) + if parsed != nil { + ips = append(ips, parsed) + } } return NetworksAndIps{ Networks: networks, diff --git a/player/repository.go b/player/repository.go index af04281..6a844d4 100644 --- a/player/repository.go +++ b/player/repository.go @@ -9,6 +9,7 @@ import ( type FetchConfig struct { Server string Filter *models.PlayerFilter + Select bool Count bool Sort []string Limit int diff --git a/player/repository/pg_repository.go b/player/repository/pg_repository.go index 74dd546..96531cf 100644 --- a/player/repository/pg_repository.go +++ b/player/repository/pg_repository.go @@ -39,10 +39,12 @@ func (repo *pgRepository) Fetch(ctx context.Context, cfg player.FetchConfig) ([] } query = query.Apply(relationshipAndSortAppender.Append) - if cfg.Count { + if cfg.Count && cfg.Select { total, err = query.SelectAndCount() - } else { + } else if cfg.Select { err = query.Select() + } else if cfg.Count { + total, err = query.Count() } if err != nil && err != pg.ErrNoRows { if strings.Contains(err.Error(), `relation "`+cfg.Server) { diff --git a/player/usecase/player_usecase.go b/player/usecase/player_usecase.go index 6c1f47e..1886a5f 100644 --- a/player/usecase/player_usecase.go +++ b/player/usecase/player_usecase.go @@ -37,8 +37,9 @@ func (ucase *usecase) GetByID(ctx context.Context, server string, id int) (*mode Filter: &models.PlayerFilter{ ID: []int{id}, }, - Limit: 1, - Count: false, + Limit: 1, + Count: false, + Select: true, }) if err != nil { return nil, err diff --git a/playerhistory/repository.go b/playerhistory/repository.go index e9d07c5..a65cd53 100644 --- a/playerhistory/repository.go +++ b/playerhistory/repository.go @@ -10,6 +10,7 @@ type FetchConfig struct { Server string Filter *models.PlayerHistoryFilter Count bool + Select bool Sort []string Limit int Offset int diff --git a/playerhistory/repository/pg_repository.go b/playerhistory/repository/pg_repository.go index 82f4a6d..53f6d99 100644 --- a/playerhistory/repository/pg_repository.go +++ b/playerhistory/repository/pg_repository.go @@ -38,10 +38,12 @@ func (repo *pgRepository) Fetch(ctx context.Context, cfg playerhistory.FetchConf } query = query.Apply(relationshipAndSortAppender.Append) - if cfg.Count { + if cfg.Count && cfg.Select { total, err = query.SelectAndCount() - } else { + } else if cfg.Select { err = query.Select() + } else if cfg.Count { + total, err = query.Count() } if err != nil && err != pg.ErrNoRows { if strings.Contains(err.Error(), `relation "`+cfg.Server) { diff --git a/server/repository.go b/server/repository.go index 6c1876d..9949607 100644 --- a/server/repository.go +++ b/server/repository.go @@ -9,6 +9,7 @@ import ( type FetchConfig struct { Filter *models.ServerFilter Columns []string + Select bool Count bool Sort []string Limit int diff --git a/server/repository/pg_repository.go b/server/repository/pg_repository.go index 6061d61..ac7f03e 100644 --- a/server/repository/pg_repository.go +++ b/server/repository/pg_repository.go @@ -41,10 +41,12 @@ func (repo *pgRepository) Fetch(ctx context.Context, cfg server.FetchConfig) ([] query = query.Column(cfg.Columns...) } - if cfg.Count { + if cfg.Count && cfg.Select { total, err = query.SelectAndCount() - } else { + } else if cfg.Select { err = query.Select() + } else if cfg.Count { + total, err = query.Count() } if err != nil && err != pg.ErrNoRows { return nil, 0, fmt.Errorf("Internal server error") diff --git a/server/usecase/server_usecase.go b/server/usecase/server_usecase.go index 15b4b6d..fdcfb13 100644 --- a/server/usecase/server_usecase.go +++ b/server/usecase/server_usecase.go @@ -34,8 +34,9 @@ func (ucase *usecase) GetByKey(ctx context.Context, key string) (*models.Server, Filter: &models.ServerFilter{ Key: []string{key}, }, - Limit: 1, - Count: false, + Limit: 1, + Count: false, + Select: true, }) if err != nil { return nil, err diff --git a/servermap/usecase/map_usecase.go b/servermap/usecase/map_usecase.go index 996f391..d63ccc2 100644 --- a/servermap/usecase/map_usecase.go +++ b/servermap/usecase/map_usecase.go @@ -32,38 +32,14 @@ func New(villageRepo village.Repository) servermap.Usecase { func (ucase *usecase) GetMarkers(ctx context.Context, cfg servermap.GetMarkersConfig) ([]*generator.Marker, error) { g := new(errgroup.Group) - tribes := make(map[string][]int) - tribeIDs := []int{} - cache := make(map[int]bool) - for _, data := range cfg.Tribes { - //id,#color - id, color, err := parseMarker(data) - if err != nil { - return nil, errors.Wrapf(err, "tribe=%s", data) - } - if ok := cache[id]; ok || color == "" { - continue - } - tribeIDs = append(tribeIDs, id) - cache[id] = true - tribes[color] = append(tribes[color], id) + tribes, tribeIDs, err := toMarkers(cfg.Tribes) + if err != nil { + return nil, err } - players := make(map[string][]int) - playerIDs := []int{} - cache = make(map[int]bool) - for _, data := range cfg.Players { - //id,#color - id, color, err := parseMarker(data) - if err != nil { - return nil, errors.Wrapf(err, "player=%s", data) - } - if ok := cache[id]; ok || color == "" { - continue - } - playerIDs = append(playerIDs, id) - cache[id] = true - players[color] = append(players[color], id) + players, playerIDs, err := toMarkers(cfg.Players) + if err != nil { + return nil, err } otherMarkers := []*generator.Marker{} @@ -82,6 +58,7 @@ func (ucase *usecase) GetMarkers(ctx context.Context, cfg servermap.GetMarkersCo TribeIDNEQ: tribeIDs, }, }, + Select: true, Columns: []string{"x", "y"}, Count: false, }) @@ -108,6 +85,7 @@ func (ucase *usecase) GetMarkers(ctx context.Context, cfg servermap.GetMarkersCo Filter: &models.VillageFilter{ PlayerID: []int{0}, }, + Select: true, Columns: []string{"x", "y"}, Count: false, }) @@ -138,6 +116,7 @@ func (ucase *usecase) GetMarkers(ctx context.Context, cfg servermap.GetMarkersCo TribeID: ids, }, }, + Select: true, Columns: []string{"x", "y"}, Count: false, }) @@ -166,6 +145,7 @@ func (ucase *usecase) GetMarkers(ctx context.Context, cfg servermap.GetMarkersCo Filter: &models.VillageFilter{ PlayerID: ids, }, + Select: true, Columns: []string{"x", "y"}, Count: false, }) @@ -183,14 +163,17 @@ func (ucase *usecase) GetMarkers(ctx context.Context, cfg servermap.GetMarkersCo }) } - err := g.Wait() + err = g.Wait() + if err != nil { + return nil, err + } sort.SliceStable(playerMarkers, func(i, j int) bool { return len(playerMarkers[i].Villages) < len(playerMarkers[j].Villages) }) sort.SliceStable(tribeMarkers, func(i, j int) bool { return len(tribeMarkers[i].Villages) < len(tribeMarkers[j].Villages) }) - return concatMarkers(otherMarkers, tribeMarkers, playerMarkers), err + return concatMarkers(otherMarkers, tribeMarkers, playerMarkers), nil } func concatMarkers(slices ...[]*generator.Marker) []*generator.Marker { @@ -206,14 +189,14 @@ func concatMarkers(slices ...[]*generator.Marker) []*generator.Marker { return tmp } -func parseMarker(str string) (int, string, error) { - splitted := strings.Split(str, ",") +func toMarker(param string) (int, string, error) { + splitted := strings.Split(param, ",") if len(splitted) != 2 { - return 0, "", fmt.Errorf("%s: Invalid marker format (should be id,#hexcolor)", str) + return 0, "", fmt.Errorf("%s: Invalid marker format (should be id,#hexcolor)", param) } id, err := strconv.Atoi(splitted[0]) if err != nil { - return 0, "", errors.Wrapf(err, "%s: Invalid marker format (should be id,#hexcolor)", str) + return 0, "", errors.Wrapf(err, "%s: Invalid marker format (should be id,#hexcolor)", param) } if id <= 0 { return 0, "", fmt.Errorf("ID should be greater than 0") @@ -221,3 +204,23 @@ func parseMarker(str string) (int, string, error) { return id, splitted[1], nil } + +func toMarkers(params []string) (map[string][]int, []int, error) { + idsByColor := make(map[string][]int) + ids := []int{} + cache := make(map[int]bool) + for _, param := range params { + //id,#color + id, color, err := toMarker(param) + if err != nil { + return nil, nil, errors.Wrapf(err, "invalid param %s", param) + } + if ok := cache[id]; ok || color == "" { + continue + } + ids = append(ids, id) + cache[id] = true + idsByColor[color] = append(idsByColor[color], id) + } + return idsByColor, ids, nil +} diff --git a/serverstats/repository.go b/serverstats/repository.go index 044a13e..3fbd7e7 100644 --- a/serverstats/repository.go +++ b/serverstats/repository.go @@ -9,6 +9,7 @@ import ( type FetchConfig struct { Server string Filter *models.ServerStatsFilter + Select bool Count bool Sort []string Limit int diff --git a/serverstats/repository/pg_repository.go b/serverstats/repository/pg_repository.go index ee4a51f..41306b9 100644 --- a/serverstats/repository/pg_repository.go +++ b/serverstats/repository/pg_repository.go @@ -33,10 +33,12 @@ func (repo *pgRepository) Fetch(ctx context.Context, cfg serverstats.FetchConfig query = query.Apply(cfg.Filter.Where) } - if cfg.Count { + if cfg.Count && cfg.Select { total, err = query.SelectAndCount() - } else { + } else if cfg.Select { err = query.Select() + } else if cfg.Count { + total, err = query.Count() } if err != nil && err != pg.ErrNoRows { if strings.Contains(err.Error(), `relation "`+cfg.Server) { diff --git a/tribe/repository.go b/tribe/repository.go index 1878987..0a8e067 100644 --- a/tribe/repository.go +++ b/tribe/repository.go @@ -10,6 +10,7 @@ type FetchConfig struct { Server string Filter *models.TribeFilter Count bool + Select bool Sort []string Limit int Offset int diff --git a/tribe/repository/pg_repository.go b/tribe/repository/pg_repository.go index 23f4562..da33f9e 100644 --- a/tribe/repository/pg_repository.go +++ b/tribe/repository/pg_repository.go @@ -34,10 +34,12 @@ func (repo *pgRepository) Fetch(ctx context.Context, cfg tribe.FetchConfig) ([]* query = query.Apply(cfg.Filter.Where) } - if cfg.Count { + if cfg.Count && cfg.Select { total, err = query.SelectAndCount() - } else { + } else if cfg.Select { err = query.Select() + } else if cfg.Count { + total, err = query.Count() } if err != nil && err != pg.ErrNoRows { if strings.Contains(err.Error(), `relation "`+cfg.Server) { diff --git a/tribe/usecase/tribe_usecase.go b/tribe/usecase/tribe_usecase.go index 4651429..9334348 100644 --- a/tribe/usecase/tribe_usecase.go +++ b/tribe/usecase/tribe_usecase.go @@ -39,6 +39,7 @@ func (ucase *usecase) GetByID(ctx context.Context, server string, id int) (*mode Limit: 1, Server: server, Count: false, + Select: true, }) if err != nil { return nil, err diff --git a/tribechange/repository.go b/tribechange/repository.go index 8078be5..20d22d2 100644 --- a/tribechange/repository.go +++ b/tribechange/repository.go @@ -10,6 +10,7 @@ type FetchConfig struct { Server string Filter *models.TribeChangeFilter Count bool + Select bool Sort []string Limit int Offset int diff --git a/tribechange/repository/pg_repository.go b/tribechange/repository/pg_repository.go index 4f1fc3c..9989520 100644 --- a/tribechange/repository/pg_repository.go +++ b/tribechange/repository/pg_repository.go @@ -38,10 +38,12 @@ func (repo *pgRepository) Fetch(ctx context.Context, cfg tribechange.FetchConfig } query = query.Apply(relationshipAndSortAppender.Append) - if cfg.Count { + if cfg.Count && cfg.Select { total, err = query.SelectAndCount() - } else { + } else if cfg.Select { err = query.Select() + } else if cfg.Count { + total, err = query.Count() } if err != nil && err != pg.ErrNoRows { if strings.Contains(err.Error(), `relation "`+cfg.Server) { diff --git a/tribehistory/repository.go b/tribehistory/repository.go index 9576a7d..4c10b98 100644 --- a/tribehistory/repository.go +++ b/tribehistory/repository.go @@ -9,6 +9,7 @@ import ( type FetchConfig struct { Server string Filter *models.TribeHistoryFilter + Select bool Count bool Sort []string Limit int diff --git a/tribehistory/repository/pg_repository.go b/tribehistory/repository/pg_repository.go index 1e04846..1a24f96 100644 --- a/tribehistory/repository/pg_repository.go +++ b/tribehistory/repository/pg_repository.go @@ -38,10 +38,12 @@ func (repo *pgRepository) Fetch(ctx context.Context, cfg tribehistory.FetchConfi } query = query.Apply(relationshipAndSortAppender.Append) - if cfg.Count { + if cfg.Count && cfg.Select { total, err = query.SelectAndCount() - } else { + } else if cfg.Select { err = query.Select() + } else if cfg.Count { + total, err = query.Count() } if err != nil && err != pg.ErrNoRows { if strings.Contains(err.Error(), `relation "`+cfg.Server) { diff --git a/version/repository.go b/version/repository.go index 5c7df8d..ee47866 100644 --- a/version/repository.go +++ b/version/repository.go @@ -8,6 +8,7 @@ import ( type FetchConfig struct { Filter *models.VersionFilter + Select bool Count bool Sort []string Limit int diff --git a/version/repository/pg_repository.go b/version/repository/pg_repository.go index efc0bae..fee8740 100644 --- a/version/repository/pg_repository.go +++ b/version/repository/pg_repository.go @@ -38,10 +38,12 @@ func (repo *pgRepository) Fetch(ctx context.Context, cfg version.FetchConfig) ([ query = query.Apply(cfg.Filter.Where) } - if cfg.Count { + if cfg.Count && cfg.Select { total, err = query.SelectAndCount() - } else { + } else if cfg.Select { err = query.Select() + } else if cfg.Count { + total, err = query.Count() } if err != nil && err != pg.ErrNoRows { return nil, 0, fmt.Errorf("Internal server error") diff --git a/version/usecase/version_usecase.go b/version/usecase/version_usecase.go index 5e58380..b3ea5b3 100644 --- a/version/usecase/version_usecase.go +++ b/version/usecase/version_usecase.go @@ -38,7 +38,9 @@ func (ucase *usecase) GetByCode(ctx context.Context, code models.VersionCode) (* Filter: &models.VersionFilter{ Code: []models.VersionCode{code}, }, - Limit: 1, + Limit: 1, + Select: true, + Count: false, }) if err != nil { return nil, err diff --git a/village/repository.go b/village/repository.go index 1113dca..d3c993f 100644 --- a/village/repository.go +++ b/village/repository.go @@ -10,6 +10,7 @@ type FetchConfig struct { Server string Filter *models.VillageFilter Columns []string + Select bool Count bool Sort []string Limit int diff --git a/village/repository/pg_repository.go b/village/repository/pg_repository.go index 20f8c9b..38c930e 100644 --- a/village/repository/pg_repository.go +++ b/village/repository/pg_repository.go @@ -41,10 +41,12 @@ func (repo *pgRepository) Fetch(ctx context.Context, cfg village.FetchConfig) ([ query = query.Apply(relationshipAndSortAppender.Append) total := 0 - if cfg.Count { + if cfg.Count && cfg.Select { total, err = query.SelectAndCount() - } else { + } else if cfg.Select { err = query.Select() + } else if cfg.Count { + total, err = query.Count() } if err != nil && err != pg.ErrNoRows { if strings.Contains(err.Error(), `relation "`+cfg.Server) { diff --git a/village/usecase/village_usecase.go b/village/usecase/village_usecase.go index 3c33ce9..da62e1b 100644 --- a/village/usecase/village_usecase.go +++ b/village/usecase/village_usecase.go @@ -37,6 +37,8 @@ func (ucase *usecase) GetByID(ctx context.Context, server string, id int) (*mode }, Limit: 1, Server: server, + Select: true, + Count: false, }) if err != nil { return nil, err