-
Notifications
You must be signed in to change notification settings - Fork 0
/
cronticker.go
92 lines (78 loc) · 2.66 KB
/
cronticker.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
/*
Cron 문법으로 Ticker를 실행할 수 있습니다
CronTicker의 문법은 다음과 같습니다
공식 문법과는 다르게, 초 단위를 Optional로 제공합니다
┌───────────── 초 (0 - 59) (Optional)
│ ┌───────────── 분 (0 - 59)
│ │ ┌───────────── 시 (0 - 23)
│ │ │ ┌───────────── 일 (1 - 31)
│ │ │ │ ┌───────────── 월 (1 - 12)
│ │ │ │ │ ┌───────────── 요일 (0 - 6) (일요일부터 토요일까지;
│ │ │ │ │ │ 특정 시스템에서는 7도 일요일)
│ │ │ │ │ │
│ │ │ │ │ │
│ │ │ │ │ │
* * * * * *
위 문법 외에도 Descriptor 문법을 제공합니다
참고: https://pkg.go.dev/github.com/robfig/cron#hdr-Predefined_schedules
Entry | Description | Equivalent To
----- | ----------- | -------------
@yearly (or @annually) | Run once a year, midnight, Jan. 1st | 0 0 1 1 *
@monthly | Run once a month, midnight, first of month | 0 0 1 * *
@weekly | Run once a week, midnight between Sat/Sun | 0 0 * * 0
@daily (or @midnight) | Run once a day, midnight | 0 0 * * *
@hourly | Run once an hour, beginning of hour | 0 * * * *
*/
package cronticker
import (
"time"
"github.com/robfig/cron/v3"
)
const SOME_RANDOM_BIG_MILLISECOND_PREVENTS_MULTIPLE_TICKS = 7
type CronTicker struct {
C chan time.Time
k chan bool
currentTick time.Time
nextTick time.Time
cron.Schedule
}
func NewCronWithOptionalSecondsTicker(spec string) (*CronTicker, error) {
sch, err := cron.NewParser(cron.SecondOptional |
cron.Minute |
cron.Hour |
cron.Dom |
cron.Month |
cron.Dow |
cron.Descriptor).Parse(spec)
if err != nil {
return nil, err
}
return &CronTicker{
C: make(chan time.Time, 1),
k: make(chan bool, 1),
Schedule: sch,
}, nil
}
func (c *CronTicker) Start() {
c.currentTick = time.Now()
go c.runTimer()
}
func (c *CronTicker) Stop() {
c.k <- true
}
func (c *CronTicker) runTimer() {
c.nextTick = c.Schedule.Next(c.currentTick)
timer := time.NewTimer(time.Until(c.nextTick))
defer timer.Stop()
for {
select {
case <-c.k:
return
case c.currentTick = <-timer.C:
c.C <- c.currentTick
c.nextTick = c.Schedule.Next(
c.currentTick.Add(SOME_RANDOM_BIG_MILLISECOND_PREVENTS_MULTIPLE_TICKS * time.Millisecond))
timer.Reset(time.Until(c.nextTick))
}
}
}