add database vacuum cleaner, move all sql statements to separate file, cron saves daily player/tribe stats
This commit is contained in:
parent
7bca0d25e5
commit
ed8dd20dd8
217
cron/handler.go
217
cron/handler.go
|
@ -21,174 +21,6 @@ import (
|
|||
|
||||
const (
|
||||
endpointGetServers = "/backend/get_servers.php"
|
||||
serverPGFunctions = `
|
||||
CREATE OR REPLACE FUNCTION ?0.log_tribe_change()
|
||||
RETURNS trigger AS
|
||||
$BODY$
|
||||
BEGIN
|
||||
IF NEW.tribe_id <> OLD.tribe_id THEN
|
||||
INSERT INTO ?0.tribe_changes(player_id,old_tribe_id,new_tribe_id,created_at)
|
||||
VALUES(OLD.id,OLD.tribe_id,NEW.tribe_id,now());
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$BODY$
|
||||
LANGUAGE plpgsql VOLATILE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION ?0.log_player_name_change()
|
||||
RETURNS trigger AS
|
||||
$BODY$
|
||||
BEGIN
|
||||
IF NEW.name <> OLD.name THEN
|
||||
INSERT INTO player_name_changes(lang_version_tag,player_id,old_name,new_name,changed_on)
|
||||
VALUES(?1,NEW.id,OLD.name,NEW.name,CURRENT_DATE)
|
||||
ON CONFLICT DO NOTHING;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$BODY$
|
||||
LANGUAGE plpgsql VOLATILE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION ?0.get_old_and_new_owner_tribe_id()
|
||||
RETURNS trigger AS
|
||||
$BODY$
|
||||
BEGIN
|
||||
IF NEW.old_owner_id <> 0 THEN
|
||||
SELECT tribe_id INTO NEW.old_owner_tribe_id
|
||||
FROM ?0.players
|
||||
WHERE id = NEW.old_owner_id;
|
||||
END IF;
|
||||
IF NEW.old_owner_tribe_id IS NULL THEN
|
||||
NEW.old_owner_tribe_id = 0;
|
||||
END IF;
|
||||
IF NEW.new_owner_id <> 0 THEN
|
||||
SELECT tribe_id INTO NEW.new_owner_tribe_id
|
||||
FROM ?0.players
|
||||
WHERE id = NEW.new_owner_id;
|
||||
END IF;
|
||||
IF NEW.new_owner_tribe_id IS NULL THEN
|
||||
NEW.new_owner_tribe_id = 0;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$BODY$
|
||||
LANGUAGE plpgsql VOLATILE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION check_daily_growth()
|
||||
RETURNS trigger AS
|
||||
$BODY$
|
||||
BEGIN
|
||||
IF NEW.exist = false THEN
|
||||
NEW.daily_growth = 0;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$BODY$
|
||||
LANGUAGE plpgsql;
|
||||
|
||||
CREATE OR REPLACE FUNCTION check_existence()
|
||||
RETURNS trigger AS
|
||||
$BODY$
|
||||
BEGIN
|
||||
IF NEW.exist = false AND OLD.exist = true THEN
|
||||
NEW.deleted_at = now();
|
||||
END IF;
|
||||
IF NEW.exist = true THEN
|
||||
NEW.deleted_at = null;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$BODY$
|
||||
LANGUAGE plpgsql;
|
||||
|
||||
CREATE OR REPLACE FUNCTION check_dominance()
|
||||
RETURNS trigger AS
|
||||
$BODY$
|
||||
BEGIN
|
||||
IF NEW.exist = false THEN
|
||||
NEW.dominance = 0;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$BODY$
|
||||
LANGUAGE plpgsql;
|
||||
|
||||
CREATE OR REPLACE FUNCTION ?0.insert_to_player_to_servers()
|
||||
RETURNS trigger AS
|
||||
$BODY$
|
||||
BEGIN
|
||||
INSERT INTO player_to_servers(server_key,player_id)
|
||||
VALUES('?0', NEW.id)
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$BODY$
|
||||
LANGUAGE plpgsql;
|
||||
`
|
||||
serverPGTriggers = `
|
||||
DROP TRIGGER IF EXISTS ?0_tribe_changes ON ?0.players;
|
||||
CREATE TRIGGER ?0_tribe_changes
|
||||
AFTER UPDATE
|
||||
ON ?0.players
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE ?0.log_tribe_change();
|
||||
|
||||
DROP TRIGGER IF EXISTS ?0_name_change ON ?0.players;
|
||||
CREATE TRIGGER ?0_name_change
|
||||
AFTER UPDATE
|
||||
ON ?0.players
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE ?0.log_player_name_change();
|
||||
|
||||
DROP TRIGGER IF EXISTS ?0_check_daily_growth ON ?0.players;
|
||||
CREATE TRIGGER ?0_check_daily_growth
|
||||
BEFORE UPDATE
|
||||
ON ?0.players
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE check_daily_growth();
|
||||
|
||||
DROP TRIGGER IF EXISTS ?0_check_player_existence ON ?0.players;
|
||||
CREATE TRIGGER ?0_check_player_existence
|
||||
BEFORE UPDATE
|
||||
ON ?0.players
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE check_existence();
|
||||
|
||||
DROP TRIGGER IF EXISTS ?0_check_tribe_existence ON ?0.tribes;
|
||||
CREATE TRIGGER ?0_check_tribe_existence
|
||||
BEFORE UPDATE
|
||||
ON ?0.tribes
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE check_existence();
|
||||
|
||||
DROP TRIGGER IF EXISTS ?0_check_dominance ON ?0.tribes;
|
||||
CREATE TRIGGER ?0_check_dominance
|
||||
BEFORE UPDATE
|
||||
ON ?0.tribes
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE check_dominance();
|
||||
|
||||
DROP TRIGGER IF EXISTS ?0_update_ennoblement_old_and_new_owner_tribe_id ON ?0.ennoblements;
|
||||
CREATE TRIGGER ?0_update_ennoblement_old_and_new_owner_tribe_id
|
||||
BEFORE INSERT
|
||||
ON ?0.ennoblements
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE ?0.get_old_and_new_owner_tribe_id();
|
||||
|
||||
DROP TRIGGER IF EXISTS ?0_insert_to_player_to_servers ON ?0.players;
|
||||
CREATE TRIGGER ?0_insert_to_player_to_servers
|
||||
AFTER INSERT
|
||||
ON ?0.players
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE ?0.insert_to_player_to_servers();
|
||||
`
|
||||
)
|
||||
|
||||
type handler struct {
|
||||
|
@ -210,8 +42,12 @@ func Attach(c *cron.Cron, db *pg.DB) error {
|
|||
if _, err := c.AddFunc("30 1 * * *", h.updateStats); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := c.AddFunc("30 2 * * *", h.vacuumDatabase); err != nil {
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
h.updateServersData()
|
||||
// h.updateServersData()
|
||||
h.vacuumDatabase()
|
||||
h.updateServersHistory()
|
||||
h.updateStats()
|
||||
}()
|
||||
|
@ -266,6 +102,8 @@ func (h *handler) createSchema(server *models.Server) error {
|
|||
(*models.TribeHistory)(nil),
|
||||
(*models.PlayerHistory)(nil),
|
||||
(*models.TribeChange)(nil),
|
||||
(*models.DailyPlayerStats)(nil),
|
||||
(*models.DailyTribeStats)(nil),
|
||||
}
|
||||
|
||||
for _, model := range models {
|
||||
|
@ -365,7 +203,7 @@ func (h *handler) updateServersData() {
|
|||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
max := runtime.NumCPU() * 5
|
||||
max := runtime.NumCPU() * 2
|
||||
count := 0
|
||||
|
||||
for _, server := range servers {
|
||||
|
@ -492,3 +330,42 @@ func (h *handler) updateStats() {
|
|||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) vacuumDatabase() {
|
||||
servers := []*models.Server{}
|
||||
err := h.db.
|
||||
Model(&servers).
|
||||
Select()
|
||||
if err != nil {
|
||||
log.Fatal(errors.Wrap(err, "vacuumDatabase"))
|
||||
return
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
max := runtime.NumCPU() * 5
|
||||
count := 0
|
||||
|
||||
for _, server := range servers {
|
||||
if count >= max {
|
||||
wg.Wait()
|
||||
count = 0
|
||||
}
|
||||
sh := &vacuumServerDBHandler{
|
||||
db: h.db.WithParam("SERVER", pg.Safe(server.Key)),
|
||||
}
|
||||
count++
|
||||
wg.Add(1)
|
||||
go func(server *models.Server, sh *vacuumServerDBHandler) {
|
||||
defer wg.Done()
|
||||
log.Printf("%s: vacuuming database", server.Key)
|
||||
if err := sh.vacuum(); err != nil {
|
||||
log.Println(errors.Wrap(err, server.Key))
|
||||
return
|
||||
} else {
|
||||
log.Printf("%s: database vacuumed", server.Key)
|
||||
}
|
||||
}(server, sh)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package cron
|
||||
|
||||
import "github.com/tribalwarshelp/shared/models"
|
||||
|
||||
type tribeSearchableByID struct {
|
||||
*models.Tribe
|
||||
}
|
||||
|
||||
func (t tribeSearchableByID) id() int {
|
||||
return t.ID
|
||||
}
|
||||
|
||||
type playerSearchableByID struct {
|
||||
*models.Player
|
||||
}
|
||||
|
||||
func (t playerSearchableByID) id() int {
|
||||
return t.ID
|
||||
}
|
||||
|
||||
type searchableByID interface {
|
||||
id() int
|
||||
}
|
||||
|
||||
func makePlayersSearchable(players []*models.Player) []searchableByID {
|
||||
searchable := []searchableByID{}
|
||||
for _, player := range players {
|
||||
searchable = append(searchable, playerSearchableByID{player})
|
||||
}
|
||||
return searchable
|
||||
}
|
||||
|
||||
func makeTribesSearchable(tribes []*models.Tribe) []searchableByID {
|
||||
searchable := []searchableByID{}
|
||||
for _, tribe := range tribes {
|
||||
searchable = append(searchable, tribeSearchableByID{tribe})
|
||||
}
|
||||
return searchable
|
||||
}
|
||||
|
||||
func searchByID(haystack []searchableByID, id int) int {
|
||||
low := 0
|
||||
high := len(haystack) - 1
|
||||
|
||||
for low <= high {
|
||||
median := (low + high) / 2
|
||||
|
||||
if haystack[median].id() < id {
|
||||
low = median + 1
|
||||
} else {
|
||||
high = median - 1
|
||||
}
|
||||
}
|
||||
|
||||
if low == len(haystack) || haystack[low].id() != id {
|
||||
return 0
|
||||
}
|
||||
|
||||
return low
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
package cron
|
||||
|
||||
const (
|
||||
serverPGFunctions = `
|
||||
CREATE OR REPLACE FUNCTION ?0.log_tribe_change()
|
||||
RETURNS trigger AS
|
||||
$BODY$
|
||||
BEGIN
|
||||
IF NEW.tribe_id <> OLD.tribe_id THEN
|
||||
INSERT INTO ?0.tribe_changes(player_id,old_tribe_id,new_tribe_id,created_at)
|
||||
VALUES(OLD.id,OLD.tribe_id,NEW.tribe_id,now());
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$BODY$
|
||||
LANGUAGE plpgsql VOLATILE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION ?0.log_player_name_change()
|
||||
RETURNS trigger AS
|
||||
$BODY$
|
||||
BEGIN
|
||||
IF NEW.name <> OLD.name THEN
|
||||
INSERT INTO player_name_changes(lang_version_tag,player_id,old_name,new_name,changed_on)
|
||||
VALUES(?1,NEW.id,OLD.name,NEW.name,CURRENT_DATE)
|
||||
ON CONFLICT DO NOTHING;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$BODY$
|
||||
LANGUAGE plpgsql VOLATILE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION ?0.get_old_and_new_owner_tribe_id()
|
||||
RETURNS trigger AS
|
||||
$BODY$
|
||||
BEGIN
|
||||
IF NEW.old_owner_id <> 0 THEN
|
||||
SELECT tribe_id INTO NEW.old_owner_tribe_id
|
||||
FROM ?0.players
|
||||
WHERE id = NEW.old_owner_id;
|
||||
END IF;
|
||||
IF NEW.old_owner_tribe_id IS NULL THEN
|
||||
NEW.old_owner_tribe_id = 0;
|
||||
END IF;
|
||||
IF NEW.new_owner_id <> 0 THEN
|
||||
SELECT tribe_id INTO NEW.new_owner_tribe_id
|
||||
FROM ?0.players
|
||||
WHERE id = NEW.new_owner_id;
|
||||
END IF;
|
||||
IF NEW.new_owner_tribe_id IS NULL THEN
|
||||
NEW.new_owner_tribe_id = 0;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$BODY$
|
||||
LANGUAGE plpgsql VOLATILE;
|
||||
|
||||
CREATE OR REPLACE FUNCTION check_daily_growth()
|
||||
RETURNS trigger AS
|
||||
$BODY$
|
||||
BEGIN
|
||||
IF NEW.exist = false THEN
|
||||
NEW.daily_growth = 0;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$BODY$
|
||||
LANGUAGE plpgsql;
|
||||
|
||||
CREATE OR REPLACE FUNCTION check_existence()
|
||||
RETURNS trigger AS
|
||||
$BODY$
|
||||
BEGIN
|
||||
IF NEW.exist = false AND OLD.exist = true THEN
|
||||
NEW.deleted_at = now();
|
||||
END IF;
|
||||
IF NEW.exist = true THEN
|
||||
NEW.deleted_at = null;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$BODY$
|
||||
LANGUAGE plpgsql;
|
||||
|
||||
CREATE OR REPLACE FUNCTION check_dominance()
|
||||
RETURNS trigger AS
|
||||
$BODY$
|
||||
BEGIN
|
||||
IF NEW.exist = false THEN
|
||||
NEW.dominance = 0;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$BODY$
|
||||
LANGUAGE plpgsql;
|
||||
|
||||
CREATE OR REPLACE FUNCTION ?0.insert_to_player_to_servers()
|
||||
RETURNS trigger AS
|
||||
$BODY$
|
||||
BEGIN
|
||||
INSERT INTO player_to_servers(server_key,player_id)
|
||||
VALUES('?0', NEW.id)
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$BODY$
|
||||
LANGUAGE plpgsql;
|
||||
`
|
||||
serverPGTriggers = `
|
||||
DROP TRIGGER IF EXISTS ?0_tribe_changes ON ?0.players;
|
||||
CREATE TRIGGER ?0_tribe_changes
|
||||
AFTER UPDATE
|
||||
ON ?0.players
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE ?0.log_tribe_change();
|
||||
|
||||
DROP TRIGGER IF EXISTS ?0_name_change ON ?0.players;
|
||||
CREATE TRIGGER ?0_name_change
|
||||
AFTER UPDATE
|
||||
ON ?0.players
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE ?0.log_player_name_change();
|
||||
|
||||
DROP TRIGGER IF EXISTS ?0_check_daily_growth ON ?0.players;
|
||||
CREATE TRIGGER ?0_check_daily_growth
|
||||
BEFORE UPDATE
|
||||
ON ?0.players
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE check_daily_growth();
|
||||
|
||||
DROP TRIGGER IF EXISTS ?0_check_player_existence ON ?0.players;
|
||||
CREATE TRIGGER ?0_check_player_existence
|
||||
BEFORE UPDATE
|
||||
ON ?0.players
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE check_existence();
|
||||
|
||||
DROP TRIGGER IF EXISTS ?0_check_tribe_existence ON ?0.tribes;
|
||||
CREATE TRIGGER ?0_check_tribe_existence
|
||||
BEFORE UPDATE
|
||||
ON ?0.tribes
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE check_existence();
|
||||
|
||||
DROP TRIGGER IF EXISTS ?0_check_dominance ON ?0.tribes;
|
||||
CREATE TRIGGER ?0_check_dominance
|
||||
BEFORE UPDATE
|
||||
ON ?0.tribes
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE check_dominance();
|
||||
|
||||
DROP TRIGGER IF EXISTS ?0_update_ennoblement_old_and_new_owner_tribe_id ON ?0.ennoblements;
|
||||
CREATE TRIGGER ?0_update_ennoblement_old_and_new_owner_tribe_id
|
||||
BEFORE INSERT
|
||||
ON ?0.ennoblements
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE ?0.get_old_and_new_owner_tribe_id();
|
||||
|
||||
DROP TRIGGER IF EXISTS ?0_insert_to_player_to_servers ON ?0.players;
|
||||
CREATE TRIGGER ?0_insert_to_player_to_servers
|
||||
AFTER INSERT
|
||||
ON ?0.players
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE ?0.insert_to_player_to_servers();
|
||||
`
|
||||
)
|
|
@ -399,6 +399,76 @@ func (h *updateServerDataHandler) getUnitConfig() (*models.UnitConfig, error) {
|
|||
return cfg, nil
|
||||
}
|
||||
|
||||
func (h *updateServerDataHandler) isDateTheSameAsServerHistoryUpdatedAt(t time.Time) bool {
|
||||
return t.Year() == h.server.HistoryUpdatedAt.Year() &&
|
||||
t.Month() == h.server.HistoryUpdatedAt.Month() &&
|
||||
t.Day() == h.server.HistoryUpdatedAt.Day()
|
||||
}
|
||||
|
||||
func (h *updateServerDataHandler) calculateODDifference(od1 models.OpponentsDefeated, od2 models.OpponentsDefeated) models.OpponentsDefeated {
|
||||
return models.OpponentsDefeated{
|
||||
RankAtt: (od1.RankAtt - od2.RankAtt) * -1,
|
||||
ScoreAtt: od1.ScoreAtt - od2.ScoreAtt,
|
||||
RankDef: (od1.RankDef - od2.RankDef) * -1,
|
||||
ScoreDef: od1.ScoreDef - od2.ScoreDef,
|
||||
RankSup: (od1.RankSup - od2.RankSup) * -1,
|
||||
ScoreSup: od1.ScoreSup - od2.ScoreSup,
|
||||
RankTotal: (od1.RankTotal - od2.RankTotal) * -1,
|
||||
ScoreTotal: od1.ScoreTotal - od2.ScoreTotal,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *updateServerDataHandler) calculateDailyTribeStats(tribes []*models.Tribe,
|
||||
history []*models.TribeHistory) []*models.DailyTribeStats {
|
||||
dailyStats := []*models.DailyTribeStats{}
|
||||
|
||||
for _, historyRecord := range history {
|
||||
if !h.isDateTheSameAsServerHistoryUpdatedAt(historyRecord.CreatedAt) {
|
||||
continue
|
||||
}
|
||||
if index := searchByID(makeTribesSearchable(tribes), historyRecord.TribeID); index != 0 {
|
||||
tribe := tribes[index]
|
||||
dailyStats = append(dailyStats, &models.DailyTribeStats{
|
||||
TribeID: tribe.ID,
|
||||
Members: tribe.TotalMembers - historyRecord.TotalMembers,
|
||||
Villages: tribe.TotalVillages - historyRecord.TotalVillages,
|
||||
Points: tribe.Points - historyRecord.Points,
|
||||
AllPoints: tribe.AllPoints - historyRecord.AllPoints,
|
||||
Rank: (tribe.Rank - historyRecord.Rank) * -1,
|
||||
Dominance: tribe.Dominance - historyRecord.Dominance,
|
||||
CreatedAt: historyRecord.CreatedAt,
|
||||
OpponentsDefeated: h.calculateODDifference(tribe.OpponentsDefeated, historyRecord.OpponentsDefeated),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return dailyStats
|
||||
}
|
||||
|
||||
func (h *updateServerDataHandler) calculateDailyPlayerStats(players []*models.Player,
|
||||
history []*models.PlayerHistory) []*models.DailyPlayerStats {
|
||||
dailyStats := []*models.DailyPlayerStats{}
|
||||
|
||||
for _, historyRecord := range history {
|
||||
if !h.isDateTheSameAsServerHistoryUpdatedAt(historyRecord.CreatedAt) {
|
||||
continue
|
||||
}
|
||||
if index := searchByID(makePlayersSearchable(players), historyRecord.PlayerID); index != 0 {
|
||||
player := players[index]
|
||||
dailyStats = append(dailyStats, &models.DailyPlayerStats{
|
||||
PlayerID: player.ID,
|
||||
Villages: player.TotalVillages - historyRecord.TotalVillages,
|
||||
Points: player.Points - historyRecord.Points,
|
||||
Rank: (player.Rank - historyRecord.Rank) * -1,
|
||||
CreatedAt: historyRecord.CreatedAt,
|
||||
OpponentsDefeated: h.calculateODDifference(player.OpponentsDefeated, historyRecord.OpponentsDefeated),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return dailyStats
|
||||
}
|
||||
|
||||
func (h *updateServerDataHandler) update() error {
|
||||
pod, err := h.getOD(false)
|
||||
if err != nil {
|
||||
|
@ -476,7 +546,34 @@ func (h *updateServerDataHandler) update() error {
|
|||
Where("id NOT IN (?)", pg.In(ids)).
|
||||
Set("exist = false").
|
||||
Update(); err != nil && err != pg.ErrNoRows {
|
||||
return errors.Wrap(err, "cannot update not existed tribes")
|
||||
return errors.Wrap(err, "cannot update not exist tribes")
|
||||
}
|
||||
|
||||
tribesHistory := []*models.TribeHistory{}
|
||||
if err := tx.Model(&tribesHistory).
|
||||
DistinctOn("tribe_id").
|
||||
Column("*").
|
||||
Where("tribe_id IN (?)", pg.In(ids)).
|
||||
Order("tribe_id DESC", "created_at DESC").
|
||||
Select(); err != nil && err != pg.ErrNoRows {
|
||||
return errors.Wrap(err, "cannot select tribes history")
|
||||
}
|
||||
|
||||
todaysTribesStats := h.calculateDailyTribeStats(tribes, tribesHistory)
|
||||
if len(todaysTribesStats) > 0 {
|
||||
if _, err := tx.
|
||||
Model(&todaysTribesStats).
|
||||
OnConflict("ON CONSTRAINT daily_tribe_stats_tribe_id_created_at_key DO UPDATE").
|
||||
Set("members = EXCLUDED.members").
|
||||
Set("villages = EXCLUDED.villages").
|
||||
Set("points = EXCLUDED.points").
|
||||
Set("all_points = EXCLUDED.all_points").
|
||||
Set("rank = EXCLUDED.rank").
|
||||
Set("dominance = EXCLUDED.dominance").
|
||||
Apply(attachODSetClauses).
|
||||
Insert(); err != nil {
|
||||
return errors.Wrap(err, "cannot insert today's tribes stats")
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(players) > 0 {
|
||||
|
@ -502,7 +599,30 @@ func (h *updateServerDataHandler) update() error {
|
|||
Where("id NOT IN (?)", pg.In(ids)).
|
||||
Set("exist = false").
|
||||
Update(); err != nil && err != pg.ErrNoRows {
|
||||
return errors.Wrap(err, "cannot update not existed players")
|
||||
return errors.Wrap(err, "cannot update not exist players")
|
||||
}
|
||||
|
||||
playerHistory := []*models.PlayerHistory{}
|
||||
if err := tx.Model(&playerHistory).
|
||||
DistinctOn("player_id").
|
||||
Column("*").
|
||||
Where("player_id IN (?)", pg.In(ids)).
|
||||
Order("player_id DESC", "created_at DESC").Select(); err != nil && err != pg.ErrNoRows {
|
||||
return errors.Wrap(err, "cannot select players history")
|
||||
}
|
||||
|
||||
todaysPlayersStats := h.calculateDailyPlayerStats(players, playerHistory)
|
||||
if len(todaysPlayersStats) > 0 {
|
||||
if _, err := tx.
|
||||
Model(&todaysPlayersStats).
|
||||
OnConflict("ON CONSTRAINT daily_player_stats_player_id_created_at_key DO UPDATE").
|
||||
Set("villages = EXCLUDED.villages").
|
||||
Set("points = EXCLUDED.points").
|
||||
Set("rank = EXCLUDED.rank").
|
||||
Apply(attachODSetClauses).
|
||||
Insert(); err != nil {
|
||||
return errors.Wrap(err, "cannot insert today's players stats")
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(villages) > 0 {
|
||||
|
@ -525,7 +645,7 @@ func (h *updateServerDataHandler) update() error {
|
|||
if _, err := tx.Model(&models.Village{}).
|
||||
Where("id NOT IN (?)", pg.In(ids)).
|
||||
Delete(); err != nil && err != pg.ErrNoRows {
|
||||
return errors.Wrap(err, "cannot delete not existed villages")
|
||||
return errors.Wrap(err, "cannot delete not exist villages")
|
||||
}
|
||||
}
|
||||
if len(ennoblements) > 0 {
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package cron
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/go-pg/pg/v10"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tribalwarshelp/shared/models"
|
||||
)
|
||||
|
||||
type vacuumServerDBHandler struct {
|
||||
db *pg.DB
|
||||
}
|
||||
|
||||
func (h *vacuumServerDBHandler) vacuum() error {
|
||||
tx, err := h.db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Close()
|
||||
|
||||
withNotExitedPlayers := h.db.Model(&models.Player{}).Where("exist = false")
|
||||
withNotExitedTribes := h.db.Model(&models.Tribe{}).Where("exist = false")
|
||||
|
||||
_, err = tx.Model(&models.PlayerHistory{}).
|
||||
With("players", withNotExitedPlayers).
|
||||
Where("player_id IN (Select id FROM players) OR player_history.created_at < ?", time.Now().Add(-1*24*time.Hour*90)).
|
||||
Delete()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cannot delete old player history")
|
||||
}
|
||||
|
||||
_, err = tx.Model(&models.TribeHistory{}).
|
||||
With("tribes", withNotExitedTribes).
|
||||
Where("tribe_id IN (Select id FROM tribes) OR tribe_history.created_at < ?", time.Now().Add(-1*24*time.Hour*90)).
|
||||
Delete()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cannot delete old tribe history")
|
||||
}
|
||||
|
||||
_, err = tx.Model(&models.DailyPlayerStats{}).
|
||||
With("players", withNotExitedPlayers).
|
||||
Where("player_id IN (Select id FROM players) OR daily_player_stats.created_at < ?", time.Now().Add(-1*24*time.Hour*90)).
|
||||
Delete()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cannot delete old player stats")
|
||||
}
|
||||
|
||||
_, err = tx.Model(&models.DailyTribeStats{}).
|
||||
With("tribes", withNotExitedTribes).
|
||||
Where("tribe_id IN (Select id FROM tribes) OR daily_tribe_stats.created_at < ?", time.Now().Add(-1*24*time.Hour*90)).
|
||||
Delete()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cannot delete old tribe stats")
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
10
go.mod
10
go.mod
|
@ -4,10 +4,14 @@ go 1.14
|
|||
|
||||
require (
|
||||
github.com/Kichiyaki/go-php-serialize v0.0.0-20200601110855-47b6982acf83
|
||||
github.com/go-pg/pg/v10 v10.0.0-beta.1
|
||||
github.com/go-pg/pg/v10 v10.0.0-beta.2
|
||||
github.com/joho/godotenv v1.3.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/tribalwarshelp/shared v0.0.0-20200624134544-636239c5fd17
|
||||
golang.org/x/net v0.0.0-20200528225125-3c3fba18258b // indirect
|
||||
github.com/segmentio/encoding v0.1.14 // indirect
|
||||
github.com/tribalwarshelp/shared v0.0.0-20200625103607-9768e416aea9
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect
|
||||
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 // indirect
|
||||
google.golang.org/grpc v1.30.0 // indirect
|
||||
google.golang.org/protobuf v1.25.0 // indirect
|
||||
)
|
||||
|
|
48
go.sum
48
go.sum
|
@ -20,8 +20,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
|
|||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/go-pg/pg/v10 v10.0.0-beta.1 h1:GD65aZVx9yR6fxxXdglBlook89oxxg2FYE11TDd9Now=
|
||||
github.com/go-pg/pg/v10 v10.0.0-beta.1/go.mod h1:JYxBTzIz9dpSAa+bphD1U7A/PBCwiuw1o8pYNDSsQ+4=
|
||||
github.com/go-pg/pg/v10 v10.0.0-beta.2 h1:8tNEJLtOEw5/Df0BLLBOHCiLaYAiu4uhdngjK955MK8=
|
||||
github.com/go-pg/pg/v10 v10.0.0-beta.2/go.mod h1:UAuqGPC94ySi4rJ3DC5e4SY1rlwugZbJA/XoJ/kf5Rw=
|
||||
github.com/go-pg/pg/v9 v9.0.0-beta.14/go.mod h1:T2Sr6bpTCOr2lUqOUMiXLMJqZHSUBKk1LdgSqjwhZfA=
|
||||
github.com/go-pg/pg/v9 v9.0.3/go.mod h1:Tm/Q3Vt6gdQOH6TTN1H/xLlIXc+Qrka7TZ6uREtu/eA=
|
||||
github.com/go-pg/pg/v9 v9.1.6 h1:IqBayenvp9EWjHncRE7//SRmQuktq60oeO1/MkEx3dY=
|
||||
|
@ -53,6 +53,8 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
|||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
|
@ -80,20 +82,18 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
|
|||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/segmentio/encoding v0.1.10/go.mod h1:RWhr02uzMB9gQC1x+MfYxedtmBibb9cZ6Vv9VxRSSbw=
|
||||
github.com/segmentio/encoding v0.1.12 h1:SwIDXReTDnlYqOcLachzJEczAEihST7Mx7nGlAWCJ3Q=
|
||||
github.com/segmentio/encoding v0.1.12/go.mod h1:RWhr02uzMB9gQC1x+MfYxedtmBibb9cZ6Vv9VxRSSbw=
|
||||
github.com/segmentio/encoding v0.1.13 h1:izH8HknGvMZvlqplu+kmCmbsW5VEvz4yBsZpdUUKUDM=
|
||||
github.com/segmentio/encoding v0.1.13/go.mod h1:RWhr02uzMB9gQC1x+MfYxedtmBibb9cZ6Vv9VxRSSbw=
|
||||
github.com/segmentio/encoding v0.1.14 h1:BfnglNbNRohLaBLf93uP5/IwKqeWrezXK/g6IRnj75c=
|
||||
github.com/segmentio/encoding v0.1.14/go.mod h1:RWhr02uzMB9gQC1x+MfYxedtmBibb9cZ6Vv9VxRSSbw=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
|
||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs=
|
||||
github.com/tribalwarshelp/shared v0.0.0-20200623082627-128bf01a6570 h1:W2cBKRRvr1QLG2GzuJFuvtVe0dblHkkb+E2SlbdJBHo=
|
||||
github.com/tribalwarshelp/shared v0.0.0-20200623082627-128bf01a6570/go.mod h1:tf+2yTHasV6jAF3V2deZ9slNoCyBzC0fMdTjI7clf6Y=
|
||||
github.com/tribalwarshelp/shared v0.0.0-20200623144748-aa834a01dce6 h1:WZ1oxHysFtiPjHa2ADUqiGrzwcN3j0YpiVg/V2e/74o=
|
||||
github.com/tribalwarshelp/shared v0.0.0-20200623144748-aa834a01dce6/go.mod h1:tf+2yTHasV6jAF3V2deZ9slNoCyBzC0fMdTjI7clf6Y=
|
||||
github.com/tribalwarshelp/shared v0.0.0-20200624134544-636239c5fd17 h1:DUMz3ROe2nYRszZuu97LVIgdPrt8QBWAVouFlrucL8c=
|
||||
github.com/tribalwarshelp/shared v0.0.0-20200624134544-636239c5fd17/go.mod h1:tf+2yTHasV6jAF3V2deZ9slNoCyBzC0fMdTjI7clf6Y=
|
||||
github.com/tribalwarshelp/shared v0.0.0-20200625103607-9768e416aea9 h1:CHeznuISvmlW1pYpnA7Bz3nVdQ6kc9ORtGtIKEKH8M8=
|
||||
github.com/tribalwarshelp/shared v0.0.0-20200625103607-9768e416aea9/go.mod h1:tf+2yTHasV6jAF3V2deZ9slNoCyBzC0fMdTjI7clf6Y=
|
||||
github.com/vmihailenco/bufpool v0.1.5/go.mod h1:fL9i/PRTuS7AELqAHwSU1Zf1c70xhkhGe/cD5ud9pJk=
|
||||
github.com/vmihailenco/bufpool v0.1.11 h1:gOq2WmBrq0i2yW5QJ16ykccQ4wH9UyEsgLm6czKAd94=
|
||||
github.com/vmihailenco/bufpool v0.1.11/go.mod h1:AFf/MOy3l2CFTKbxwt0mp2MwnqjNEs5H/UxrkA5jxTQ=
|
||||
|
@ -101,8 +101,8 @@ github.com/vmihailenco/msgpack/v4 v4.3.5/go.mod h1:DuaveEe48abshDmz5UBKyZ+yDugva
|
|||
github.com/vmihailenco/msgpack/v4 v4.3.7/go.mod h1:Ii+PksJlvFT5ZRcB/4YLAInMIp6a0WOCm0L3BU0aNG4=
|
||||
github.com/vmihailenco/msgpack/v4 v4.3.11 h1:Q47CePddpNGNhk4GCnAx9DDtASi2rasatE0cd26cZoE=
|
||||
github.com/vmihailenco/msgpack/v4 v4.3.11/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
|
||||
github.com/vmihailenco/msgpack/v5 v5.0.0-alpha.2 h1:0jVpYJSRJzGY7m21n9V5uIkl7Zre64W8DR1dxEKX2g4=
|
||||
github.com/vmihailenco/msgpack/v5 v5.0.0-alpha.2/go.mod h1:LDfrk4wJpSFwkzNOJxrCWiSm8c7Iqw/hXNPT2fzQfE8=
|
||||
github.com/vmihailenco/msgpack/v5 v5.0.0-beta.1 h1:d71/KA0LhvkrJ/Ok+Wx9qK7bU8meKA1Hk0jpVI5kJjk=
|
||||
github.com/vmihailenco/msgpack/v5 v5.0.0-beta.1/go.mod h1:xlngVLeyQ/Qi05oQxhQ+oTuqa03RjMwMfk/7/TCs+QI=
|
||||
github.com/vmihailenco/tagparser v0.1.0/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
||||
github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY=
|
||||
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
|
||||
|
@ -114,8 +114,10 @@ golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3
|
|||
golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20191128160524-b544559bb6d1/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 h1:cg5LA/zNPRzIXIWSCxQW10Rvpy94aQh3LT/ShoCpkHw=
|
||||
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM=
|
||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
|
@ -133,10 +135,10 @@ golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200222033325-078779b8f2d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2 h1:eDrdRpKgkcCqKZQwyZRyeFZgfqt37SL7Kv3tok06cKE=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200528225125-3c3fba18258b h1:IYiJPiJfzktmDAO1HQiwjMjwjlYKHAL7KzeD544RJPs=
|
||||
golang.org/x/net v0.0.0-20200528225125-3c3fba18258b/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM=
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -148,8 +150,10 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121 h1:rITEj+UZHYC927n8GT97eC3zrpzXdb/voyeOuVKS46o=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 h1:OjiUf46hAmXblsZdnoSXsEUSKU8r1UEzcL5RVZ4gO9Y=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 h1:5/PjkGUjvEU5Gl6BxmvKRPpqo2uNMv4rcHBMwzk/st8=
|
||||
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
|
@ -177,6 +181,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
|
|||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
@ -187,6 +193,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
|||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
|
|
Reference in New Issue