mirror of
https://github.com/muety/wakapi.git
synced 2023-08-10 21:12:56 +03:00
chore: add random time offset to scheduled reports jobs
This commit is contained in:
parent
f3b738b250
commit
9dbc2039fc
@ -341,22 +341,27 @@ func Load(version string) *Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Server.ListenIpV4 == "" && config.Server.ListenIpV6 == "" {
|
|
||||||
logbuch.Fatal("either of listen_ipv4 or listen_ipv6 must be set")
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.Db.MaxConn <= 0 {
|
|
||||||
logbuch.Fatal("you must allow at least one database connection")
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.Sentry.Dsn != "" {
|
if config.Sentry.Dsn != "" {
|
||||||
logbuch.Info("enabling sentry integration")
|
logbuch.Info("enabling sentry integration")
|
||||||
initSentry(config.Sentry, config.IsDev())
|
initSentry(config.Sentry, config.IsDev())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// some validation checks
|
||||||
|
if config.Server.ListenIpV4 == "" && config.Server.ListenIpV6 == "" {
|
||||||
|
logbuch.Fatal("either of listen_ipv4 or listen_ipv6 must be set")
|
||||||
|
}
|
||||||
|
if config.Db.MaxConn <= 0 {
|
||||||
|
logbuch.Fatal("you must allow at least one database connection")
|
||||||
|
}
|
||||||
if config.Mail.Provider != "" && findString(config.Mail.Provider, emailProviders, "") == "" {
|
if config.Mail.Provider != "" && findString(config.Mail.Provider, emailProviders, "") == "" {
|
||||||
logbuch.Fatal("unknown mail provider '%s'", config.Mail.Provider)
|
logbuch.Fatal("unknown mail provider '%s'", config.Mail.Provider)
|
||||||
}
|
}
|
||||||
|
if _, err := time.Parse("15:04", config.App.GetWeeklyReportTime()); err != nil {
|
||||||
|
logbuch.Fatal("invalid interval set for report_time_weekly")
|
||||||
|
}
|
||||||
|
if _, err := time.Parse("15:04", config.App.AggregationTime); err != nil {
|
||||||
|
logbuch.Fatal("invalid interval set for aggregation_time")
|
||||||
|
}
|
||||||
|
|
||||||
Set(config)
|
Set(config)
|
||||||
return Get()
|
return Get()
|
||||||
|
@ -6,31 +6,40 @@ import (
|
|||||||
"github.com/leandro-lugaresi/hub"
|
"github.com/leandro-lugaresi/hub"
|
||||||
"github.com/muety/wakapi/config"
|
"github.com/muety/wakapi/config"
|
||||||
"github.com/muety/wakapi/models"
|
"github.com/muety/wakapi/models"
|
||||||
|
"math/rand"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var reportLock = sync.Mutex{}
|
var reportLock = sync.Mutex{}
|
||||||
|
|
||||||
|
// range for random offset to add / subtract when scheduling a new job
|
||||||
|
// to avoid all mails being sent at once, but distributed over 2*offsetIntervalMin minutes
|
||||||
|
const offsetIntervalMin = 15
|
||||||
|
|
||||||
type ReportService struct {
|
type ReportService struct {
|
||||||
config *config.Config
|
config *config.Config
|
||||||
eventBus *hub.Hub
|
eventBus *hub.Hub
|
||||||
summaryService ISummaryService
|
summaryService ISummaryService
|
||||||
userService IUserService
|
userService IUserService
|
||||||
mailService IMailService
|
mailService IMailService
|
||||||
schedulersWeekly map[string]*gocron.Scheduler // user id -> scheduler
|
scheduler *gocron.Scheduler
|
||||||
|
rand *rand.Rand
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewReportService(summaryService ISummaryService, userService IUserService, mailService IMailService) *ReportService {
|
func NewReportService(summaryService ISummaryService, userService IUserService, mailService IMailService) *ReportService {
|
||||||
srv := &ReportService{
|
srv := &ReportService{
|
||||||
config: config.Get(),
|
config: config.Get(),
|
||||||
eventBus: config.EventBus(),
|
eventBus: config.EventBus(),
|
||||||
summaryService: summaryService,
|
summaryService: summaryService,
|
||||||
userService: userService,
|
userService: userService,
|
||||||
mailService: mailService,
|
mailService: mailService,
|
||||||
schedulersWeekly: map[string]*gocron.Scheduler{},
|
scheduler: gocron.NewScheduler(time.Local),
|
||||||
|
rand: rand.New(rand.NewSource(time.Now().Unix())),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
srv.scheduler.StartAsync()
|
||||||
|
|
||||||
sub := srv.eventBus.Subscribe(0, config.EventUserUpdate)
|
sub := srv.eventBus.Subscribe(0, config.EventUserUpdate)
|
||||||
go func(sub *hub.Subscription) {
|
go func(sub *hub.Subscription) {
|
||||||
for m := range sub.Receiver {
|
for m := range sub.Receiver {
|
||||||
@ -62,24 +71,24 @@ func (srv *ReportService) SyncSchedule(u *models.User) bool {
|
|||||||
defer reportLock.Unlock()
|
defer reportLock.Unlock()
|
||||||
|
|
||||||
// unschedule
|
// unschedule
|
||||||
if s, ok := srv.schedulersWeekly[u.ID]; ok && !u.ReportsWeekly {
|
if !u.ReportsWeekly {
|
||||||
s.Stop()
|
_ = srv.scheduler.RemoveByTag(u.ID)
|
||||||
s.Clear()
|
|
||||||
delete(srv.schedulersWeekly, u.ID)
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// schedule
|
// schedule
|
||||||
if _, ok := srv.schedulersWeekly[u.ID]; !ok && u.ReportsWeekly {
|
if j := srv.getJobByTag(u.ID); j == nil && u.ReportsWeekly {
|
||||||
s := gocron.NewScheduler(u.TZ())
|
t, _ := time.ParseInLocation("15:04", srv.config.App.GetWeeklyReportTime(), u.TZ())
|
||||||
s.
|
t = t.Add(time.Duration(srv.rand.Intn(offsetIntervalMin)*srv.rand.Intn(2)) * time.Minute)
|
||||||
|
if _, err := srv.scheduler.
|
||||||
Every(1).
|
Every(1).
|
||||||
Week().
|
Week().
|
||||||
Weekday(srv.config.App.GetWeeklyReportDay()).
|
Weekday(srv.config.App.GetWeeklyReportDay()).
|
||||||
At(srv.config.App.GetWeeklyReportTime()).
|
At(t).
|
||||||
Do(srv.Run, u, 7*24*time.Hour)
|
Tag(u.ID).
|
||||||
s.StartAsync()
|
Do(srv.Run, u, 7*24*time.Hour); err != nil {
|
||||||
srv.schedulersWeekly[u.ID] = s
|
config.Log().Error("failed to schedule report job for user '%s' – %v", u.ID, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return u.ReportsWeekly
|
return u.ReportsWeekly
|
||||||
@ -119,3 +128,14 @@ func (srv *ReportService) Run(user *models.User, duration time.Duration) error {
|
|||||||
logbuch.Info("sent report to user '%s'", user.ID)
|
logbuch.Info("sent report to user '%s'", user.ID)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (srv *ReportService) getJobByTag(tag string) *gocron.Job {
|
||||||
|
for _, j := range srv.scheduler.Jobs() {
|
||||||
|
for _, t := range j.Tags() {
|
||||||
|
if t == tag {
|
||||||
|
return j
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user