Skip to content

Commit 0feb54c

Browse files
authored
scheduler: Update (#47)
1 parent 51ee424 commit 0feb54c

File tree

7 files changed

+53
-63
lines changed

7 files changed

+53
-63
lines changed

ptr.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package utils
2+
3+
func Ptr[T any](t T) *T { return &t }

scheduler/clock.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func AtClock(hour, min, sec int) *Clock {
5050
return &c
5151
}
5252

53-
func FullClock() *Clock { return AtClock(-1, -1, -1) }
53+
func FullClock() *Clock { return new(Clock) }
5454

5555
func AtHour(hour int) *Clock {
5656
return AtClock(hour, 0, 0)

scheduler/clock_test.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func TestClock(t *testing.T) {
2626
}
2727
}
2828

29-
func TestClockNext(t *testing.T) {
29+
func TestClockNext1(t *testing.T) {
3030
ct := AtClock(12, 30, 30).Time()
3131
for _, testcase := range []struct {
3232
clock *Clock
@@ -58,6 +58,29 @@ func TestClockNext(t *testing.T) {
5858
}
5959
}
6060

61+
func TestClockNext2(t *testing.T) {
62+
for _, testcase := range []struct {
63+
clock *Clock
64+
t time.Time
65+
s string
66+
d time.Duration
67+
}{
68+
{AtClock(0, 0, -1), AtClock(0, 0, 59).Time(), "00:00:59", 0},
69+
{AtClock(0, -1, 0), AtClock(0, 59, 59).Time(), "00:00:00", 23*time.Hour + time.Second},
70+
{AtClock(-1, 0, 0), AtClock(23, 59, 0).Time(), "00:00:00", time.Minute},
71+
{AtClock(0, -1, 0), AtClock(0, 0, 59).Time(), "00:01:00", time.Second},
72+
{AtClock(0, 0, -1), AtClock(23, 59, 59).Time(), "00:00:00", time.Second},
73+
} {
74+
next := testcase.clock.Next(testcase.t)
75+
if res := next.Format("15:04:05"); res != testcase.s {
76+
t.Errorf("%s expected %q; got %q", testcase.clock, testcase.s, res)
77+
}
78+
if res := next.Sub(testcase.t); res != testcase.d {
79+
t.Errorf("%s expected %v; got %v", testcase.clock, testcase.d, res)
80+
}
81+
}
82+
}
83+
6184
func TestClockTickerDuration(t *testing.T) {
6285
for _, testcase := range []struct {
6386
clock *Clock

scheduler/notify.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
)
77

88
var (
9-
subscriber = make(map[chan struct{}]struct{})
9+
subscriber = make(map[chan time.Time]struct{})
1010
mu sync.Mutex
1111
)
1212

@@ -20,7 +20,7 @@ func init() {
2020
if sub := t.Sub(last.Add(time.Second)); sub >= 10*time.Millisecond || sub <= -10*time.Millisecond {
2121
mu.Lock()
2222
for k := range subscriber {
23-
k <- struct{}{}
23+
k <- t
2424
}
2525
mu.Unlock()
2626
}
@@ -30,13 +30,13 @@ func init() {
3030
}()
3131
}
3232

33-
func subscribeNotify(c chan struct{}) {
33+
func subscribeNotify(c chan time.Time) {
3434
mu.Lock()
3535
defer mu.Unlock()
3636
subscriber[c] = struct{}{}
3737
}
3838

39-
func unsubscribeNotify(c chan struct{}) {
39+
func unsubscribeNotify(c chan time.Time) {
4040
mu.Lock()
4141
defer mu.Unlock()
4242
delete(subscriber, c)

scheduler/schedule.go

Lines changed: 11 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"time"
66

7+
"github.com/sunshineplan/utils"
78
"github.com/sunshineplan/utils/clock"
89
)
910

@@ -52,6 +53,9 @@ type sched struct {
5253
}
5354

5455
func NewSchedule(year int, month time.Month, day int, clock *Clock) Schedule {
56+
if clock == nil {
57+
clock = new(Clock)
58+
}
5559
return sched{year, month, day, clock}
5660
}
5761

@@ -69,25 +73,16 @@ func (s sched) IsMatched(t time.Time) bool {
6973
if (s.year == 0 || s.year == year) &&
7074
(s.month == 0 || s.month == month) &&
7175
(s.day == 0 || s.day == day) {
72-
if s.clock == nil {
73-
s.clock = &Clock{}
74-
}
7576
return s.clock.IsMatched(t)
7677
}
7778
return false
7879
}
7980

8081
func (s sched) Next(t time.Time) time.Time {
81-
if s.clock == nil {
82-
s.clock = &Clock{}
83-
}
8482
return s.clock.Next(t)
8583
}
8684

8785
func (s sched) TickerDuration() time.Duration {
88-
if s.clock == nil {
89-
return 24 * time.Hour
90-
}
9186
return s.clock.TickerDuration()
9287
}
9388

@@ -108,9 +103,6 @@ func (s sched) String() string {
108103
} else {
109104
day = fmt.Sprintf("%02d", s.day)
110105
}
111-
if s.clock == nil {
112-
s.clock = &Clock{}
113-
}
114106
return fmt.Sprintf("%s/%s/%s %s", year, month, day, s.clock)
115107
}
116108

@@ -121,6 +113,9 @@ type weekSched struct {
121113
}
122114

123115
func ISOWeekSchedule(year int, week int, weekday *time.Weekday, clock *Clock) Schedule {
116+
if clock == nil {
117+
clock = new(Clock)
118+
}
124119
return weekSched{year, week, weekday, clock}
125120
}
126121

@@ -130,25 +125,16 @@ func (s weekSched) IsMatched(t time.Time) bool {
130125
if (s.year == 0 || s.year == year) &&
131126
(s.week == 0 || s.week == week) &&
132127
(s.weekday == nil || *s.weekday == weekday) {
133-
if s.clock == nil {
134-
s.clock = &Clock{}
135-
}
136128
return s.clock.IsMatched(t)
137129
}
138130
return false
139131
}
140132

141133
func (s weekSched) Next(t time.Time) time.Time {
142-
if s.clock == nil {
143-
s.clock = &Clock{}
144-
}
145134
return s.clock.Next(t)
146135
}
147136

148137
func (s weekSched) TickerDuration() time.Duration {
149-
if s.clock == nil {
150-
return 24 * time.Hour
151-
}
152138
return s.clock.TickerDuration()
153139
}
154140

@@ -169,9 +155,6 @@ func (s weekSched) String() string {
169155
} else {
170156
weekday = fmt.Sprint(s.weekday)
171157
}
172-
if s.clock == nil {
173-
s.clock = &Clock{}
174-
}
175158
return fmt.Sprintf("%s/ISOWeek:%s/Weekday:%s %s", year, week, weekday, s.clock)
176159
}
177160

@@ -183,17 +166,16 @@ type weekdaySched struct {
183166
}
184167

185168
func WeekdaySchedule(year int, month time.Month, weekday *time.Weekday, clock *Clock) Schedule {
169+
if clock == nil {
170+
clock = new(Clock)
171+
}
186172
return weekdaySched{year, month, weekday, clock}
187173
}
188174

189-
func ptrWeekday(weekday time.Weekday) *time.Weekday {
190-
return &weekday
191-
}
192-
193175
func Weekday(weekday ...time.Weekday) Schedule {
194176
var s multiSched
195177
for _, weekday := range weekday {
196-
s = append(s, WeekdaySchedule(0, 0, ptrWeekday(weekday), FullClock()))
178+
s = append(s, WeekdaySchedule(0, 0, utils.Ptr(weekday), FullClock()))
197179
}
198180
return s
199181
}
@@ -209,25 +191,16 @@ func (s weekdaySched) IsMatched(t time.Time) bool {
209191
if (s.year == 0 || s.year == year) &&
210192
(s.month == 0 || s.month == month) &&
211193
(s.weekday == nil || *s.weekday == weekday) {
212-
if s.clock == nil {
213-
s.clock = &Clock{}
214-
}
215194
return s.clock.IsMatched(t)
216195
}
217196
return false
218197
}
219198

220199
func (s weekdaySched) Next(t time.Time) time.Time {
221-
if s.clock == nil {
222-
s.clock = &Clock{}
223-
}
224200
return s.clock.Next(t)
225201
}
226202

227203
func (s weekdaySched) TickerDuration() time.Duration {
228-
if s.clock == nil {
229-
return 24 * time.Hour
230-
}
231204
return s.clock.TickerDuration()
232205
}
233206

@@ -248,9 +221,6 @@ func (s weekdaySched) String() string {
248221
} else {
249222
weekday = fmt.Sprint(s.weekday)
250223
}
251-
if s.clock == nil {
252-
s.clock = &Clock{}
253-
}
254224
return fmt.Sprintf("%s/%s/Weekday:%s %s", year, month, weekday, s.clock)
255225
}
256226

scheduler/scheduler.go

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ var (
1515

1616
type Scheduler struct {
1717
mu sync.Mutex
18-
notify chan struct{}
18+
notify chan time.Time
1919

2020
timer *time.Timer
2121
ticker *time.Ticker
@@ -29,7 +29,7 @@ type Scheduler struct {
2929
}
3030

3131
func NewScheduler() *Scheduler {
32-
return &Scheduler{notify: make(chan struct{}, 1), tc: make(chan time.Time, 1)}
32+
return &Scheduler{notify: make(chan time.Time, 1), tc: make(chan time.Time, 1)}
3333
}
3434

3535
func (sched *Scheduler) At(schedules ...Schedule) *Scheduler {
@@ -86,18 +86,18 @@ func (sched *Scheduler) init(d time.Duration) error {
8686
}
8787

8888
func (sched *Scheduler) checkMatched(t time.Time) {
89+
sched.mu.Lock()
90+
defer sched.mu.Unlock()
8991
if sched.sched.IsMatched(t) {
9092
sched.tc <- t
9193
} else if sched.sched.TickerDuration() >= time.Minute {
9294
if minus1s := t.Add(-time.Second); sched.sched.IsMatched(minus1s) {
9395
sched.tc <- minus1s
94-
sched.notify <- struct{}{}
96+
sched.notify <- t
9597
} else if plus1s := t.Add(time.Second); sched.sched.IsMatched(plus1s) {
9698
sched.tc <- plus1s
97-
go func() {
98-
time.Sleep(2 * time.Second)
99-
sched.notify <- struct{}{}
100-
}()
99+
time.Sleep(2 * time.Second)
100+
sched.notify <- time.Now()
101101
}
102102
}
103103
}
@@ -112,14 +112,11 @@ func (sched *Scheduler) newTimer(first, duration time.Duration) {
112112
for {
113113
select {
114114
case t := <-sched.ticker.C:
115-
sched.mu.Lock()
116115
sched.checkMatched(t)
117-
sched.mu.Unlock()
118-
case <-sched.notify:
116+
case t := <-sched.notify:
119117
sched.ticker.Stop()
120118
sched.mu.Lock()
121119
defer sched.mu.Unlock()
122-
t := time.Now()
123120
sched.newTimer(sched.sched.Next(t).Sub(t), duration)
124121
return
125122
case <-sched.ctx.Done():
@@ -128,17 +125,14 @@ func (sched *Scheduler) newTimer(first, duration time.Duration) {
128125
}
129126
}
130127
}()
131-
sched.mu.Lock()
132-
defer sched.mu.Unlock()
133128
sched.checkMatched(now)
134129
})
135130
go func() {
136131
for {
137132
select {
138-
case <-sched.notify:
133+
case t := <-sched.notify:
139134
sched.mu.Lock()
140135
if sched.timer.Stop() {
141-
t := time.Now()
142136
sched.timer.Reset(sched.sched.Next(t).Sub(t))
143137
}
144138
sched.mu.Unlock()

scheduler/scheduler_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func TestTickerScheduler2(t *testing.T) {
5757
}
5858
s.mu.Unlock()
5959

60-
s.notify <- struct{}{}
60+
s.notify <- time.Now()
6161
time.Sleep(500 * time.Millisecond)
6262

6363
s.mu.Lock()

0 commit comments

Comments
 (0)