precompute more data in workerUpdateServerData.loadTribes

This commit is contained in:
Dawid Wysokiński 2021-05-01 15:41:54 +02:00
parent 674f1fe63c
commit e9248b1f71
2 changed files with 55 additions and 40 deletions

View File

@ -99,18 +99,6 @@ type searchableByID interface {
len() int
}
func makePlayersSearchable(players []*models.Player) searchableByID {
return playersSearchableByID{
players: players,
}
}
func makeTribesSearchable(tribes []*models.Tribe) searchableByID {
return tribesSearchableByID{
tribes: tribes,
}
}
func searchByID(haystack searchableByID, id int) int {
low := 0
high := haystack.len() - 1

View File

@ -107,13 +107,13 @@ func (w *workerUpdateServerData) loadPlayers(od map[int]*models.OpponentsDefeate
result.ids[index] = player.ID
}
searchableNewPlayers := &playersSearchableByID{result.players}
searchablePlayers := &playersSearchableByID{result.players}
if err := w.db.
Model(&models.Player{}).
Column("id").
Where("exists = true").
ForEach(func(player *models.Player) error {
if index := searchByID(searchableNewPlayers, player.ID); index < 0 {
if index := searchByID(searchablePlayers, player.ID); index < 0 {
result.deletedPlayers = append(result.deletedPlayers, player.ID)
}
return nil
@ -124,12 +124,24 @@ func (w *workerUpdateServerData) loadPlayers(od map[int]*models.OpponentsDefeate
return result, nil
}
func (w *workerUpdateServerData) loadTribes(od map[int]*models.OpponentsDefeated, numberOfVillages int) ([]*models.Tribe, error) {
tribes, err := w.dataloader.LoadTribes()
type loadTribesResult struct {
ids []int
tribes []*models.Tribe
deletedTribes []int
numberOfTribes int
}
func (w *workerUpdateServerData) loadTribes(od map[int]*models.OpponentsDefeated, numberOfVillages int) (loadTribesResult, error) {
var err error
result := loadTribesResult{}
result.tribes, err = w.dataloader.LoadTribes()
if err != nil {
return nil, err
return result, errors.Wrap(err, "workerUpdateServerData.loadTribes")
}
for _, tribe := range tribes {
result.numberOfTribes = len(result.tribes)
result.ids = make([]int, result.numberOfTribes)
for index, tribe := range result.tribes {
tribeOD, ok := od[tribe.ID]
if ok {
tribe.OpponentsDefeated = *tribeOD
@ -139,8 +151,24 @@ func (w *workerUpdateServerData) loadTribes(od map[int]*models.OpponentsDefeated
} else {
tribe.Dominance = 0
}
result.ids[index] = tribe.ID
}
return tribes, nil
searchableTribes := &tribesSearchableByID{result.tribes}
if err := w.db.
Model(&models.Tribe{}).
Column("id").
Where("exists = true").
ForEach(func(tribe *models.Tribe) error {
if index := searchByID(searchableTribes, tribe.ID); index < 0 {
result.deletedTribes = append(result.deletedTribes, tribe.ID)
}
return nil
}); err != nil {
return result, errors.Wrap(err, "workerUpdateServerData.loadTribes: Tribes that have been deleted couldn't be detected")
}
return result, nil
}
func (w *workerUpdateServerData) calculateODifference(od1 models.OpponentsDefeated, od2 models.OpponentsDefeated) models.OpponentsDefeated {
@ -161,7 +189,7 @@ func (w *workerUpdateServerData) calculateTodaysTribeStats(
history []*models.TribeHistory,
) []*models.DailyTribeStats {
var todaysStats []*models.DailyTribeStats
searchableTribes := makeTribesSearchable(tribes)
searchableTribes := &tribesSearchableByID{tribes}
for _, historyRecord := range history {
if index := searchByID(searchableTribes, historyRecord.TribeID); index != -1 {
@ -183,10 +211,12 @@ func (w *workerUpdateServerData) calculateTodaysTribeStats(
return todaysStats
}
func (w *workerUpdateServerData) calculateDailyPlayerStats(players []*models.Player,
history []*models.PlayerHistory) []*models.DailyPlayerStats {
func (w *workerUpdateServerData) calculateDailyPlayerStats(
players []*models.Player,
history []*models.PlayerHistory,
) []*models.DailyPlayerStats {
var todaysStats []*models.DailyPlayerStats
searchablePlayers := makePlayersSearchable(players)
searchablePlayers := &playersSearchableByID{players}
for _, historyRecord := range history {
if index := searchByID(searchablePlayers, historyRecord.PlayerID); index != -1 {
@ -222,11 +252,10 @@ func (w *workerUpdateServerData) update() error {
}
numberOfVillages := len(villages)
tribes, err := w.loadTribes(tod, countPlayerVillages(villages))
tribesResult, err := w.loadTribes(tod, countPlayerVillages(villages))
if err != nil {
return errors.Wrap(err, "workerUpdateServerData.update")
}
numberOfTribes := len(tribes)
playersResult, err := w.loadPlayers(pod)
if err != nil {
@ -249,13 +278,19 @@ func (w *workerUpdateServerData) update() error {
}
return w.db.RunInTransaction(context.Background(), func(tx *pg.Tx) error {
if len(tribes) > 0 {
ids := make([]int, len(tribes))
for index, tribe := range tribes {
ids[index] = tribe.ID
if len(tribesResult.deletedTribes) > 0 {
if _, err := tx.Model(&models.Tribe{}).
Where("tribe.id = ANY (?)", pg.Array(tribesResult.deletedTribes)).
Set("exists = false").
Set("deleted_at = now()").
Set("dominance = 0").
Update(); err != nil && err != pg.ErrNoRows {
return errors.Wrap(err, "couldn't update non-existent tribes")
}
}
if _, err := tx.Model(&tribes).
if tribesResult.numberOfTribes > 0 {
if _, err := tx.Model(&tribesResult.tribes).
OnConflict("(id) DO UPDATE").
Set("name = EXCLUDED.name").
Set("tag = EXCLUDED.tag").
@ -271,14 +306,6 @@ func (w *workerUpdateServerData) update() error {
Insert(); err != nil {
return errors.Wrap(err, "couldn't insert tribes")
}
if _, err := tx.Model(&tribes).
Where("NOT (tribe.id = ANY (?))", pg.Array(ids)).
Set("exists = false").
Set("deleted_at = now()").
Set("dominance = 0").
Update(); err != nil && err != pg.ErrNoRows {
return errors.Wrap(err, "couldn't update non-existent tribes")
}
var tribesHistory []*models.TribeHistory
if err := tx.
@ -291,7 +318,7 @@ func (w *workerUpdateServerData) update() error {
Select(); err != nil && err != pg.ErrNoRows {
return errors.Wrap(err, "couldn't select tribe history records")
}
todaysTribeStats := w.calculateTodaysTribeStats(tribes, tribesHistory)
todaysTribeStats := w.calculateTodaysTribeStats(tribesResult.tribes, tribesHistory)
if len(todaysTribeStats) > 0 {
if _, err := tx.
Model(&todaysTribeStats).
@ -385,7 +412,7 @@ func (w *workerUpdateServerData) update() error {
Set("building_config = ?", buildingCfg).
Set("config = ?", cfg).
Set("number_of_players = ?", playersResult.numberOfPlayers).
Set("number_of_tribes = ?", numberOfTribes).
Set("number_of_tribes = ?", tribesResult.numberOfTribes).
Set("number_of_villages = ?", numberOfVillages).
Returning("*").
WherePK().