chore: generate leaderboard when enabled in user settings

This commit is contained in:
Ferdinand Mütsch 2022-10-02 10:13:39 +02:00
parent 13a3d9f03a
commit 4a22a19cb0
7 changed files with 49 additions and 10 deletions

View File

@ -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"`

View File

@ -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 {

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)
}

View File

@ -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)