199 lines
3.7 KiB
Go
199 lines
3.7 KiB
Go
/*
|
|
Copyright 2017-2022 CAcert Inc.
|
|
SPDX-License-Identifier: Apache-2.0
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package main
|
|
|
|
import (
|
|
"time"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
type Job interface {
|
|
Schedule()
|
|
Stop()
|
|
Run()
|
|
}
|
|
|
|
type jobIdentifier int
|
|
|
|
const (
|
|
JobIDCloseDecisions jobIdentifier = iota
|
|
JobIDRemindVotersJob
|
|
reminderDays = 3
|
|
)
|
|
|
|
var rescheduleChannel = make(chan jobIdentifier, 1)
|
|
|
|
func JobScheduler(quitChannel chan int) {
|
|
var jobs = map[jobIdentifier]Job{
|
|
JobIDCloseDecisions: NewCloseDecisionsJob(),
|
|
JobIDRemindVotersJob: NewRemindVotersJob(),
|
|
}
|
|
|
|
log.Info("started job scheduler")
|
|
|
|
for {
|
|
select {
|
|
case jobID := <-rescheduleChannel:
|
|
job := jobs[jobID]
|
|
|
|
log.Infof("reschedule job %s", job)
|
|
job.Schedule()
|
|
case <-quitChannel:
|
|
for _, job := range jobs {
|
|
job.Stop()
|
|
}
|
|
|
|
log.Info("stop job scheduler")
|
|
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
type CloseDecisionsJob struct {
|
|
timer *time.Timer
|
|
}
|
|
|
|
func NewCloseDecisionsJob() *CloseDecisionsJob {
|
|
job := &CloseDecisionsJob{}
|
|
job.Schedule()
|
|
|
|
return job
|
|
}
|
|
|
|
func (j *CloseDecisionsJob) Schedule() {
|
|
var (
|
|
nextDue *time.Time
|
|
err error
|
|
)
|
|
|
|
nextDue, err = GetNextPendingDecisionDue()
|
|
if err != nil {
|
|
log.Error("Could not get next pending due date")
|
|
|
|
if j.timer != nil {
|
|
j.timer.Stop()
|
|
j.timer = nil
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
if nextDue == nil {
|
|
log.Info("no next planned execution of CloseDecisionsJob")
|
|
j.Stop()
|
|
} else {
|
|
nextDue := nextDue.Add(time.Second)
|
|
log.Infof("scheduling CloseDecisionsJob for %s", nextDue)
|
|
when := time.Until(nextDue)
|
|
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()
|
|
j.timer = nil
|
|
}
|
|
}
|
|
|
|
func (j *CloseDecisionsJob) Run() {
|
|
log.Debug("running CloseDecisionsJob")
|
|
|
|
err := CloseDecisions()
|
|
if err != nil {
|
|
log.Errorf("closing decisions %v", err)
|
|
}
|
|
|
|
rescheduleChannel <- JobIDCloseDecisions
|
|
}
|
|
|
|
func (j *CloseDecisionsJob) String() string {
|
|
return "CloseDecisionsJob"
|
|
}
|
|
|
|
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, reminderDays)
|
|
|
|
log.Infof("scheduling RemindVotersJob for %s", nextExecution)
|
|
|
|
when := time.Until(nextExecution)
|
|
|
|
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")
|
|
|
|
defer func() { rescheduleChannel <- JobIDRemindVotersJob }()
|
|
|
|
var (
|
|
voters []Voter
|
|
err error
|
|
)
|
|
|
|
voters, err = GetReminderVoters()
|
|
if err != nil {
|
|
log.Errorf("problem getting voters %v", err)
|
|
|
|
return
|
|
}
|
|
|
|
var decisions []Decision
|
|
|
|
for i := range voters {
|
|
decisions, err = FindUnVotedDecisionsForVoter(&voters[i])
|
|
if err != nil {
|
|
log.Errorf("problem getting unvoted decisions: %v", err)
|
|
|
|
return
|
|
}
|
|
|
|
if len(decisions) > 0 {
|
|
NotifyMailChannel <- &RemindVoterNotification{voter: voters[i], decisions: decisions}
|
|
}
|
|
}
|
|
}
|