-
Notifications
You must be signed in to change notification settings - Fork 3
/
timer.go
104 lines (91 loc) · 2.85 KB
/
timer.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
103
104
package sched
import (
"fmt"
"time"
"github.com/gorhill/cronexpr"
)
//Timer is an Interface for a Timer object that is used by a Schedule to determine when to run the next run of a job.
// Timer need to implement the Next() method returning the time of the next Job run. Timer indicates that no jobs shall
// be scheduled anymore by returning done == true. The `next time.Time` returned with `done bool` == true IS IGNORED.
// Next() shall not return time in the past. Time in the past is reset to time.Now() at evaluation time in the scheduler.
type Timer interface {
Next() (next time.Time, done bool)
}
//Once A timer that run ONCE after an optional specific delay.
type Once struct {
delay time.Duration
done bool
}
//NewOnce Return a timer that trigger ONCE after `d` delay as soon as Timer is inquired for the next Run.
//Delay = 0 means the Timer return now(), aka as soon as time is inquired.
func NewOnce(d time.Duration) (*Once, error) {
if d < 0 {
return nil, fmt.Errorf("invalid d, must be >= 0")
}
return &Once{
delay: d,
}, nil
}
// NewOnceTime Return a timer that trigger ONCE at `t` time.Time.
//If `t` is in the past at inquery time, timer will NOT run.
func NewOnceTime(t time.Time) (*Once, error) {
remaining := time.Until(t)
if remaining < 0 {
return &Once{
delay: remaining,
done: true,
}, nil
}
return &Once{
delay: remaining,
}, nil
}
//Next Return Next Time OR a boolean indicating no more Next()(s)
func (o *Once) Next() (time.Time, bool) {
if !o.done {
o.done = true
return time.Now().Add(o.delay), false
}
return time.Time{}, o.done
}
//Fixed A Timer that fires at a fixed duration intervals
type Fixed struct {
duration time.Duration
next time.Time
}
//NewFixed Returns Fixed Timer; A Timer that fires at a fixed duration intervals.
func NewFixed(duration time.Duration) (*Fixed, error) {
if duration < 0 {
return nil, fmt.Errorf("invalid duration, must be >= 0")
}
return &Fixed{
duration: duration,
next: time.Now().Add(duration),
}, nil
}
//Next Return Next fire time.
func (f *Fixed) Next() (time.Time, bool) {
now := time.Now()
if now.After(f.next) {
f.next = f.next.Add(f.duration)
}
return f.next, false
}
//Cron A Timer that fires at according to a cron expression.
//All expresion supported by `https://github.com/gorhill/cronexpr` are supported.
type Cron struct {
expression cronexpr.Expression
}
//NewCron returns a Timer that fires at according to a cron expression.
//All expresion supported by `https://github.com/gorhill/cronexpr` are supported.
func NewCron(cronExpression string) (*Cron, error) {
expression, err := cronexpr.Parse(cronExpression)
if err != nil {
return nil, fmt.Errorf("cron expression invalid: %w", err)
}
return &Cron{expression: *expression}, nil
}
//Next Return Next fire time.
func (c *Cron) Next() (time.Time, bool) {
return c.expression.Next(time.Now()), false
}