-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtaskdata.go
137 lines (117 loc) · 3.26 KB
/
taskdata.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package bgscheduler
import (
"time"
)
// ExactLaunchTime describes the exact time for execution.
// If Hour defined, a task will be executed daily in that Hour:Minute:Second.
// For skipping Hour (hourly execution) it should be set as -1.
// Minute and Second have the same semantics.
type ExactLaunchTime struct {
Hour int
Minute int
Second int
}
// Equals shows are instances equal or not
func (r *ExactLaunchTime) Equals(other ExactLaunchTime) bool {
return other.Hour == r.Hour && other.Minute == r.Minute && other.Second == r.Second
}
// Zero shows that all time params are -1 (all parts are skipped)
func (r *ExactLaunchTime) Zero() bool {
return r.Hour == -1 && r.Minute == -1 && r.Second == -1
}
type intervalTaskData struct {
Task Task
Interval time.Duration
LastLaunchTime *time.Time
}
func newIntervalTaskData(interval time.Duration, task Task, lastLaunchTime *time.Time) *intervalTaskData {
return &intervalTaskData{
Interval: interval,
Task: task,
LastLaunchTime: lastLaunchTime,
}
}
type exactTimeInterval time.Duration
const (
exactTimeDay = exactTimeInterval(24 * time.Hour)
exactTimeHour = exactTimeInterval(time.Hour)
exactTimeMinute = exactTimeInterval(time.Minute)
)
type exactTimeTaskData struct {
ExactLaunchTime
Task Task
LastLaunchTime *time.Time
TimeToLaunch time.Duration
intervalType exactTimeInterval
lastScanTime time.Time
}
func newExactTimeTaskData(exactLaunchTime ExactLaunchTime, task Task, lastLaunchTime *time.Time) *exactTimeTaskData {
r := &exactTimeTaskData{
ExactLaunchTime: exactLaunchTime,
Task: task,
LastLaunchTime: lastLaunchTime,
lastScanTime: time.Now(),
}
r.ResetTimeToLaunch()
return r
}
func (r *exactTimeTaskData) ResetAfterLaunch() (timeToLaunch time.Duration) {
n := time.Now()
r.LastLaunchTime = &n
return r.ResetTimeToLaunch()
}
func (r *exactTimeTaskData) ResetTimeToLaunch() (timeToLaunch time.Duration) {
if r.ExactLaunchTime.Zero() {
panic("unexpected zero ExactLaunchTime")
}
now := time.Now()
hour := now.Hour()
minute := now.Minute()
second := now.Second()
if r.Hour >= 0 {
r.intervalType = exactTimeDay
} else if r.Minute >= 0 {
r.intervalType = exactTimeHour
} else if r.Second >= 0 {
r.intervalType = exactTimeMinute
}
interval := time.Duration(r.intervalType)
switch r.intervalType {
case exactTimeMinute:
second = r.Second
break
case exactTimeHour:
if r.Second >= 0 {
second = r.Second
}
minute = r.Minute
default:
if r.Second >= 0 {
second = r.Second
}
if r.Minute >= 0 {
minute = r.Minute
}
hour = r.Hour
}
nextTimeToLaunch := time.Date(now.Year(), now.Month(), now.Day(), hour, minute, second, 0, time.Local)
// Default: Call will be in the future or now
nextTimeDelta := nextTimeToLaunch.Sub(now)
// Call should be in the past
if nextTimeDelta < 0 {
// Default: Actually was
nextTimeDelta += interval - nextTimeToLaunch.Sub(*r.LastLaunchTime)
// Actually wasn't
if r.LastLaunchTime.Year() <= zeroYear {
nextTimeDelta = 0
}
}
r.TimeToLaunch = nextTimeDelta
return r.TimeToLaunch
}
func (r *exactTimeTaskData) UpdateTimeToLaunch() (timeToLaunch time.Duration) {
now := time.Now()
r.TimeToLaunch -= now.Sub(r.lastScanTime)
r.lastScanTime = now
return r.TimeToLaunch
}