From 4a22a19cb00fa742d87781fdecb9ae75342fc1ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Sun, 2 Oct 2022 10:13:39 +0200 Subject: [PATCH] chore: generate leaderboard when enabled in user settings --- config/config.go | 2 +- models/user.go | 7 ++++--- repositories/leaderboard.go | 9 +++++++++ repositories/repositories.go | 1 + routes/settings.go | 1 + services/leaderboard.go | 38 ++++++++++++++++++++++++++++++------ services/services.go | 1 + 7 files changed, 49 insertions(+), 10 deletions(-) diff --git a/config/config.go b/config/config.go index a15e6de..dc3be48 100644 --- a/config/config.go +++ b/config/config.go @@ -66,7 +66,7 @@ var env string type appConfig struct { AggregationTime string `yaml:"aggregation_time" default:"02:15" env:"WAKAPI_AGGREGATION_TIME"` - LeaderboardGenerationTime string `yaml:"leaderboard_generation_time" default:"06:00,18:00" env:"WAKAPI_LEADERBOARD_GENERATION_TIME"` + LeaderboardGenerationTime string `yaml:"leaderboard_generation_time" default:"06:00;18:00" env:"WAKAPI_LEADERBOARD_GENERATION_TIME"` ReportTimeWeekly string `yaml:"report_time_weekly" default:"fri,18:00" env:"WAKAPI_REPORT_TIME_WEEKLY"` ImportBackoffMin int `yaml:"import_backoff_min" default:"5" env:"WAKAPI_IMPORT_BACKOFF_MIN"` ImportBatchSize int `yaml:"import_batch_size" default:"50" env:"WAKAPI_IMPORT_BATCH_SIZE"` diff --git a/models/user.go b/models/user.go index 8207c3d..3dd2d0f 100644 --- a/models/user.go +++ b/models/user.go @@ -66,9 +66,10 @@ type CredentialsReset struct { } type UserDataUpdate struct { - Email string `schema:"email"` - Location string `schema:"location"` - ReportsWeekly bool `schema:"reports_weekly"` + Email string `schema:"email"` + Location string `schema:"location"` + ReportsWeekly bool `schema:"reports_weekly"` + PublicLeaderboard bool `schema:"public_leaderboard"` } type TimeByUser struct { diff --git a/repositories/leaderboard.go b/repositories/leaderboard.go index 366873a..d39c700 100644 --- a/repositories/leaderboard.go +++ b/repositories/leaderboard.go @@ -24,6 +24,15 @@ func (r *LeaderboardRepository) InsertBatch(items []*models.LeaderboardItem) err return nil } +func (r *LeaderboardRepository) CountAllByUser(userId string) (int64, error) { + var count int64 + err := r.db. + Table("leaderboard_items"). + Where("user_id = ?", userId). + Count(&count).Error + return count, err +} + func (r *LeaderboardRepository) GetAllAggregatedByInterval(key *models.IntervalKey, by *uint8) ([]*models.LeaderboardItem, error) { // TODO: distinct by (user, key) to filter out potential duplicates ? var items []*models.LeaderboardItem diff --git a/repositories/repositories.go b/repositories/repositories.go index e8361b2..b18b639 100644 --- a/repositories/repositories.go +++ b/repositories/repositories.go @@ -88,6 +88,7 @@ type IUserRepository interface { type ILeaderboardRepository interface { InsertBatch([]*models.LeaderboardItem) error + CountAllByUser(string) (int64, error) DeleteByUserAndInterval(string, *models.IntervalKey) error GetAllAggregatedByInterval(*models.IntervalKey, *uint8) ([]*models.LeaderboardItem, error) GetAggregatedByUserAndInterval(string, *models.IntervalKey, *uint8) ([]*models.LeaderboardItem, error) diff --git a/routes/settings.go b/routes/settings.go index 960ec9e..7ea56b8 100644 --- a/routes/settings.go +++ b/routes/settings.go @@ -182,6 +182,7 @@ func (h *SettingsHandler) actionUpdateUser(w http.ResponseWriter, r *http.Reques user.Email = payload.Email user.Location = payload.Location user.ReportsWeekly = payload.ReportsWeekly + user.PublicLeaderboard = payload.PublicLeaderboard if _, err := h.userSrvc.Update(user); err != nil { return http.StatusInternalServerError, "", conf.ErrInternalServerError diff --git a/services/leaderboard.go b/services/leaderboard.go index db015cd..29f0508 100644 --- a/services/leaderboard.go +++ b/services/leaderboard.go @@ -2,6 +2,7 @@ package services import ( "github.com/emvi/logbuch" + "github.com/go-co-op/gocron" "github.com/leandro-lugaresi/hub" "github.com/muety/wakapi/config" "github.com/muety/wakapi/models" @@ -21,7 +22,7 @@ type LeaderboardService struct { } func NewLeaderboardService(leaderboardRepo repositories.ILeaderboardRepository, summaryService ISummaryService, userService IUserService) *LeaderboardService { - return &LeaderboardService{ + srv := &LeaderboardService{ config: config.Get(), cache: cache.New(24*time.Hour, 24*time.Hour), eventBus: config.EventBus(), @@ -29,6 +30,28 @@ func NewLeaderboardService(leaderboardRepo repositories.ILeaderboardRepository, summaryService: summaryService, userService: userService, } + + onUserUpdate := srv.eventBus.Subscribe(0, config.EventUserUpdate) + go func(sub *hub.Subscription) { + for m := range sub.Receiver { + + // generate leaderboard for updated user, if leaderboard enabled and none present, yet + user := m.Fields[config.FieldPayload].(*models.User) + if user.PublicLeaderboard { + exists, err := srv.ExistsAnyByUser(user.ID) + if err != nil { + config.Log().Error("failed to check existing leaderboards upon user update - %v", err) + } + if !exists { + logbuch.Info("generating leaderboard for '%s' after settings update", user.ID) + srv.Run([]*models.User{user}, models.IntervalPast7Days, []uint8{models.SummaryLanguage}) + } + } + + } + }(&onUserUpdate) + + return srv } func (srv *LeaderboardService) ScheduleDefault() { @@ -42,11 +65,9 @@ func (srv *LeaderboardService) ScheduleDefault() { srv.Run(users, interval, by) } - runAllUsers(models.IntervalPast7Days, []uint8{models.SummaryLanguage}) - - //s := gocron.NewScheduler(time.Local) - //s.Every(1).Day().At(srv.config.App.LeaderboardGenerationTime).Do(runAllUsers, models.IntervalPast7Days, []uint8{models.SummaryLanguage}) - //s.StartBlocking() + s := gocron.NewScheduler(time.Local) + s.Every(1).Day().At(srv.config.App.LeaderboardGenerationTime).Do(runAllUsers, models.IntervalPast7Days, []uint8{models.SummaryLanguage}) + s.StartBlocking() } func (srv *LeaderboardService) Run(users []*models.User, interval *models.IntervalKey, by []uint8) error { @@ -92,6 +113,11 @@ func (srv *LeaderboardService) Run(users []*models.User, interval *models.Interv return nil } +func (srv *LeaderboardService) ExistsAnyByUser(userId string) (bool, error) { + count, err := srv.repository.CountAllByUser(userId) + return count > 0, err +} + func (srv *LeaderboardService) GetByInterval(interval *models.IntervalKey) ([]*models.LeaderboardItem, error) { return srv.GetAggregatedByInterval(interval, nil) } diff --git a/services/services.go b/services/services.go index 75320a8..4dc0283 100644 --- a/services/services.go +++ b/services/services.go @@ -100,6 +100,7 @@ type IReportService interface { type ILeaderboardService interface { ScheduleDefault() Run([]*models.User, *models.IntervalKey, []uint8) error + ExistsAnyByUser(string) (bool, error) GetByInterval(*models.IntervalKey) ([]*models.LeaderboardItem, error) GetAggregatedByInterval(*models.IntervalKey, *uint8) ([]*models.LeaderboardItem, error) GenerateByUser(*models.User, *models.IntervalKey) (*models.LeaderboardItem, error)