Use dep in Jenkinsfile
[cacert-boardvoting.git] / jobs.go
1 package main
2
3 import "time"
4
5 type Job interface {
6 Schedule()
7 Stop()
8 Run()
9 }
10
11 type jobIdentifier int
12
13 const (
14 JobIdCloseDecisions jobIdentifier = iota
15 JobIdRemindVotersJob
16 )
17
18 var rescheduleChannel = make(chan jobIdentifier, 1)
19
20 func JobScheduler(quitChannel chan int) {
21 var jobs = map[jobIdentifier]Job{
22 JobIdCloseDecisions: NewCloseDecisionsJob(),
23 JobIdRemindVotersJob: NewRemindVotersJob(),
24 }
25 log.Info("started job scheduler")
26
27 for {
28 select {
29 case jobId := <-rescheduleChannel:
30 job := jobs[jobId]
31 log.Infof("reschedule job %s", job)
32 job.Schedule()
33 case <-quitChannel:
34 for _, job := range jobs {
35 job.Stop()
36 }
37 log.Info("stop job scheduler")
38 return
39 }
40 }
41 }
42
43 type CloseDecisionsJob struct {
44 timer *time.Timer
45 }
46
47 func NewCloseDecisionsJob() *CloseDecisionsJob {
48 job := &CloseDecisionsJob{}
49 job.Schedule()
50 return job
51 }
52
53 func (j *CloseDecisionsJob) Schedule() {
54 var nextDue *time.Time
55 nextDue, err := GetNextPendingDecisionDue()
56 if err != nil {
57 log.Error("Could not get next pending due date")
58 if j.timer != nil {
59 j.timer.Stop()
60 j.timer = nil
61 }
62 return
63 }
64 if nextDue == nil {
65 log.Info("no next planned execution of CloseDecisionsJob")
66 j.Stop()
67 } else {
68 nextDue := nextDue.Add(time.Second)
69 log.Infof("scheduling CloseDecisionsJob for %s", nextDue)
70 when := nextDue.Sub(time.Now())
71 if j.timer != nil {
72 j.timer.Reset(when)
73 } else {
74 j.timer = time.AfterFunc(when, j.Run)
75 }
76 }
77 }
78
79 func (j *CloseDecisionsJob) Stop() {
80 if j.timer != nil {
81 j.timer.Stop()
82 j.timer = nil
83 }
84 }
85
86 func (j *CloseDecisionsJob) Run() {
87 log.Debug("running CloseDecisionsJob")
88 err := CloseDecisions()
89 if err != nil {
90 log.Errorf("closing decisions %v", err)
91 }
92 rescheduleChannel <- JobIdCloseDecisions
93 }
94
95 func (j *CloseDecisionsJob) String() string {
96 return "CloseDecisionsJob"
97 }
98
99 type RemindVotersJob struct {
100 timer *time.Timer
101 }
102
103 func NewRemindVotersJob() *RemindVotersJob {
104 job := &RemindVotersJob{}
105 job.Schedule()
106 return job
107 }
108
109 func (j *RemindVotersJob) Schedule() {
110 year, month, day := time.Now().UTC().Date()
111 nextExecution := time.Date(year, month, day, 0, 0, 0, 0, time.UTC).AddDate(0, 0, 3)
112 log.Infof("scheduling RemindVotersJob for %s", nextExecution)
113 when := nextExecution.Sub(time.Now())
114 if j.timer != nil {
115 j.timer.Reset(when)
116 } else {
117 j.timer = time.AfterFunc(when, j.Run)
118 }
119 }
120
121 func (j *RemindVotersJob) Stop() {
122 if j.timer != nil {
123 j.timer.Stop()
124 j.timer = nil
125 }
126 }
127
128 func (j *RemindVotersJob) Run() {
129 log.Info("running RemindVotersJob")
130 defer func() { rescheduleChannel <- JobIdRemindVotersJob }()
131
132 voters, err := GetReminderVoters()
133 if err != nil {
134 log.Errorf("problem getting voters %v", err)
135 return
136 }
137
138 for _, voter := range *voters {
139 decisions, err := FindUnvotedDecisionsForVoter(&voter)
140 if err != nil {
141 log.Errorf("problem getting unvoted decisions: %v", err)
142 return
143 }
144 if len(*decisions) > 0 {
145 NotifyMailChannel <- &RemindVoterNotification{voter: voter, decisions: *decisions}
146 }
147 }
148 }