-
Notifications
You must be signed in to change notification settings - Fork 6
/
cronjobs.go
102 lines (89 loc) · 2.77 KB
/
cronjobs.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package cron
import (
"time"
"github.com/TUM-Dev/Campus-Backend/server/model"
"github.com/mmcdole/gofeed"
log "github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
"gorm.io/gorm"
)
type CronService struct {
db *gorm.DB
gf *gofeed.Parser
}
// StorageDir is the directory where files are stored
// this is a variable, so it can be changed during tests
var StorageDir = "/Storage/" // target location of files
// names for cron jobs as specified in database
const (
NewsType = "news"
FileDownloadType = "fileDownload"
DishNameDownload = "dishNameDownload"
CanteenHeadcount = "canteenHeadCount"
MovieType = "movie"
FeedbackEmail = "feedbackEmail"
/* MensaType = "mensa"
AlarmType = "alarm" */
)
func New(db *gorm.DB) *CronService {
return &CronService{
db: db,
gf: gofeed.NewParser(),
}
}
func (c *CronService) Run() error {
for {
g := new(errgroup.Group)
log.Trace("Cron: checking for pending")
var res []model.Crontab
c.db.Model(&model.Crontab{}).
Find(&res, "`interval` > 0 AND (lastRun+`interval`) < ? AND type IN (?, ?, ?, ?, ?, ?)",
time.Now().Unix(),
NewsType,
FileDownloadType,
DishNameDownload,
CanteenHeadcount,
MovieType,
FeedbackEmail,
)
for _, cronjob := range res {
// Persist run to DB right away
cronFields := log.Fields{"Cron (id)": cronjob.Cron, "type": cronjob.Type.String, "LastRun": cronjob.LastRun, "interval": cronjob.Interval, "id (not real id)": cronjob.ID.Int64}
log.WithFields(cronFields).Trace("Running cronjob")
cronjob.LastRun = int32(time.Now().Unix())
c.db.Save(&cronjob)
// Run each job in a separate goroutine, so we can parallelize them
switch cronjob.Type.String {
case NewsType:
// if this is not copied here, this may not be threads save due to go's guarantees
// loop variable cronjob captured by func literal (govet)
copyCronjob := cronjob
g.Go(func() error { return c.newsCron(©Cronjob) })
case FileDownloadType:
g.Go(func() error { return c.fileDownloadCron() })
case DishNameDownload:
g.Go(func() error { return c.dishNameDownloadCron() })
case MovieType:
g.Go(func() error { return c.movieCron() })
/*
TODO: Implement handlers for other cronjobs
case MensaType:
g.Go(func() error { return c.mensaCron() })
case KinoType:
g.Go(func() error { return c.kinoCron() })
case AlarmType:
g.Go(func() error { return c.alarmCron() })
*/
case CanteenHeadcount:
g.Go(func() error { return c.canteenHeadCountCron() })
case FeedbackEmail:
g.Go(func() error { return c.feedbackEmailCron() })
}
}
if err := g.Wait(); err != nil {
log.WithError(err).Error("Couldn't run all cron jobs")
}
log.Trace("Cron: sleeping for 30 seconds")
time.Sleep(30 * time.Second)
}
}