cacert-boardvoting/jobs.go

149 lines
2.9 KiB
Go
Raw Normal View History

2017-04-20 09:35:33 +00:00
package main
import "time"
type Job interface {
Schedule()
Stop()
Run()
}
type jobIdentifier int
const (
JobIdCloseDecisions jobIdentifier = iota
2017-04-20 18:58:22 +00:00
JobIdRemindVotersJob
2017-04-20 09:35:33 +00:00
)
var rescheduleChannel = make(chan jobIdentifier, 1)
func JobScheduler(quitChannel chan int) {
var jobs = map[jobIdentifier]Job{
2017-04-20 18:58:22 +00:00
JobIdCloseDecisions: NewCloseDecisionsJob(),
JobIdRemindVotersJob: NewRemindVotersJob(),
2017-04-20 09:35:33 +00:00
}
log.Info("started job scheduler")
2017-04-20 09:35:33 +00:00
for {
select {
case jobId := <-rescheduleChannel:
job := jobs[jobId]
log.Infof("reschedule job %s", job)
2017-04-20 09:35:33 +00:00
job.Schedule()
case <-quitChannel:
for _, job := range jobs {
job.Stop()
}
log.Info("stop job scheduler")
2017-04-20 09:35:33 +00:00
return
}
}
}
type CloseDecisionsJob struct {
timer *time.Timer
}
func NewCloseDecisionsJob() *CloseDecisionsJob {
job := &CloseDecisionsJob{}
job.Schedule()
return job
}
func (j *CloseDecisionsJob) Schedule() {
var nextDue *time.Time
nextDue, err := GetNextPendingDecisionDue()
if err != nil {
log.Error("Could not get next pending due date")
2017-04-20 09:35:33 +00:00
if j.timer != nil {
j.timer.Stop()
j.timer = nil
}
return
}
if nextDue == nil {
log.Info("no next planned execution of CloseDecisionsJob")
2017-04-20 18:58:22 +00:00
j.Stop()
2017-04-20 09:35:33 +00:00
} else {
nextDue := nextDue.Add(time.Second)
log.Infof("scheduling CloseDecisionsJob for %s", nextDue)
2017-04-20 09:35:33 +00:00
when := nextDue.Sub(time.Now())
if j.timer != nil {
j.timer.Reset(when)
} else {
j.timer = time.AfterFunc(when, j.Run)
}
}
}
func (j *CloseDecisionsJob) Stop() {
if j.timer != nil {
j.timer.Stop()
2017-04-20 18:58:22 +00:00
j.timer = nil
2017-04-20 09:35:33 +00:00
}
}
func (j *CloseDecisionsJob) Run() {
log.Debug("running CloseDecisionsJob")
2017-04-20 09:35:33 +00:00
err := CloseDecisions()
if err != nil {
log.Errorf("closing decisions %v", err)
2017-04-20 09:35:33 +00:00
}
rescheduleChannel <- JobIdCloseDecisions
}
func (j *CloseDecisionsJob) String() string {
return "CloseDecisionsJob"
}
2017-04-20 18:58:22 +00:00
type RemindVotersJob struct {
timer *time.Timer
}
func NewRemindVotersJob() *RemindVotersJob {
job := &RemindVotersJob{}
job.Schedule()
return job
}
func (j *RemindVotersJob) Schedule() {
year, month, day := time.Now().UTC().Date()
nextExecution := time.Date(year, month, day, 0, 0, 0, 0, time.UTC).AddDate(0, 0, 3)
log.Infof("scheduling RemindVotersJob for %s", nextExecution)
2017-04-20 18:58:22 +00:00
when := nextExecution.Sub(time.Now())
if j.timer != nil {
j.timer.Reset(when)
} else {
j.timer = time.AfterFunc(when, j.Run)
}
}
func (j *RemindVotersJob) Stop() {
if j.timer != nil {
j.timer.Stop()
j.timer = nil
}
}
func (j *RemindVotersJob) Run() {
log.Info("running RemindVotersJob")
2017-04-20 18:58:22 +00:00
defer func() { rescheduleChannel <- JobIdRemindVotersJob }()
voters, err := GetReminderVoters()
if err != nil {
log.Errorf("problem getting voters %v", err)
2017-04-20 18:58:22 +00:00
return
}
for _, voter := range *voters {
decisions, err := FindUnvotedDecisionsForVoter(&voter)
if err != nil {
log.Errorf("problem getting unvoted decisions: %v", err)
2017-04-20 18:58:22 +00:00
return
}
if len(*decisions) > 0 {
2017-04-21 00:25:49 +00:00
NotifyMailChannel <- &RemindVoterNotification{voter: voter, decisions: *decisions}
2017-04-20 18:58:22 +00:00
}
}
}