@@ -3,6 +3,7 @@ package scheduler
33import (
44 "context"
55 "errors"
6+ "log/slog"
67 "sync"
78 "time"
89)
@@ -28,12 +29,25 @@ type Scheduler struct {
2829
2930 ctx context.Context
3031 cancel context.CancelFunc
32+
33+ debugLogger * slog.Logger
3134}
3235
3336func NewScheduler () * Scheduler {
3437 return & Scheduler {notify : make (chan time.Time , 1 ), tc : make (chan time.Time , 1 )}
3538}
3639
40+ func (sched * Scheduler ) WithDebug (debug * slog.Logger ) * Scheduler {
41+ sched .debugLogger = debug
42+ return sched
43+ }
44+
45+ func (sched * Scheduler ) debug (msg string , args ... any ) {
46+ if sched .debugLogger != nil {
47+ sched .debugLogger .Debug (msg , args ... )
48+ }
49+ }
50+
3751func (sched * Scheduler ) At (schedules ... Schedule ) * Scheduler {
3852 if len (schedules ) == 0 {
3953 panic ("no schedules" )
@@ -42,6 +56,7 @@ func (sched *Scheduler) At(schedules ...Schedule) *Scheduler {
4256 defer sched .mu .Unlock ()
4357 sched .sched = multiSched (schedules )
4458 sched .d = sched .sched .TickerDuration ()
59+ sched .debug ("Scheduler At" , "schedules" , sched .sched , "duration" , sched .d )
4560 return sched
4661}
4762
@@ -53,9 +68,19 @@ func (sched *Scheduler) AtCondition(schedules ...Schedule) *Scheduler {
5368 defer sched .mu .Unlock ()
5469 sched .sched = condSched (schedules )
5570 sched .d = sched .sched .TickerDuration ()
71+ sched .debug ("Scheduler At Condition" , "schedules" , sched .sched , "duration" , sched .d )
5672 return sched
5773}
5874
75+ func (sched * Scheduler ) String () string {
76+ sched .mu .Lock ()
77+ defer sched .mu .Unlock ()
78+ if sched .sched == nil {
79+ return ""
80+ }
81+ return sched .sched .String ()
82+ }
83+
5984func (sched * Scheduler ) Clear () {
6085 sched .mu .Lock ()
6186 defer sched .mu .Unlock ()
@@ -93,6 +118,7 @@ func (sched *Scheduler) init() error {
93118 t := <- timer .C
94119 sched .sched .init (t )
95120 sched .next = sched .sched .Next (t )
121+ sched .debug ("Scheduler Next Run Time" , "Name" , sched .sched , "Next" , sched .next )
96122 subscribeNotify (sched .notify )
97123 sched .newTimer (time .Now ())
98124 return nil
@@ -103,39 +129,22 @@ func (sched *Scheduler) init() error {
103129func (sched * Scheduler ) checkMatched (t time.Time ) {
104130 sched .mu .Lock ()
105131 defer sched .mu .Unlock ()
106- var matched time.Time
107- var notify bool
108132 if sched .sched .IsMatched (t ) {
109133 sched .tc <- t
110- matched = t
111- } else if sched .sched .TickerDuration () >= time .Minute {
112- if minus1s := t .Add (- time .Second ); sched .sched .IsMatched (minus1s ) {
113- sched .tc <- minus1s
114- matched = minus1s
115- notify = true
116- } else if plus1s := t .Add (time .Second ); sched .sched .IsMatched (plus1s ) {
117- sched .tc <- plus1s
118- matched = plus1s
119- time .Sleep (2 * time .Second )
120- notify = true
121- }
122- }
123- if ! matched .IsZero () && ! notify {
124- if sched .next = sched .sched .Next (matched .Truncate (time .Second ).Add (time .Second )); sched .next .IsZero () {
134+ sched .debug ("Scheduler Matched Time" , "Name" , sched .sched , "Time" , t )
135+ if sched .next = sched .sched .Next (t .Truncate (time .Second ).Add (time .Second )); sched .next .IsZero () {
125136 sched .Stop ()
137+ sched .debug ("Scheduler No More Next" , "Name" , sched .sched )
126138 return
127139 }
128- } else if t .After (sched .next ) {
129- notify = true
130- }
131- if notify {
132- sched .notify <- time .Now ()
140+ sched .debug ("Scheduler Next Run Time" , "Name" , sched .sched , "Next" , sched .next )
133141 }
134142}
135143
136144func (sched * Scheduler ) newTimer (t time.Time ) {
137145 if sched .next .IsZero () {
138146 sched .Stop ()
147+ sched .debug ("Scheduler No More Next" , "Name" , sched .sched )
139148 return
140149 }
141150 ctx , cancel := context .WithCancel (context .Background ())
@@ -148,10 +157,12 @@ func (sched *Scheduler) newTimer(t time.Time) {
148157 case t := <- sched .ticker .C :
149158 sched .checkMatched (t )
150159 case t := <- sched .notify :
160+ sched .debug ("Time Change Detected" , "Name" , sched .sched )
151161 sched .ticker .Stop ()
152162 sched .mu .Lock ()
153163 defer sched .mu .Unlock ()
154164 sched .next = sched .sched .Next (t )
165+ sched .debug ("Scheduler Next Run Time" , "Name" , sched .sched , "Next" , sched .next )
155166 sched .newTimer (t )
156167 return
157168 case <- sched .ctx .Done ():
@@ -166,15 +177,18 @@ func (sched *Scheduler) newTimer(t time.Time) {
166177 for {
167178 select {
168179 case t := <- sched .notify :
180+ sched .debug ("Time Change Detected" , "Name" , sched .sched )
169181 sched .mu .Lock ()
170182 if sched .timer .Stop () {
171183 sched .next = sched .sched .Next (t )
172184 if sched .next .IsZero () {
173185 cancel ()
174186 sched .Stop ()
187+ sched .debug ("Scheduler No More Next" , "Name" , sched .sched )
175188 return
176189 }
177190 sched .timer .Reset (sched .next .Sub (t ))
191+ sched .debug ("Scheduler Next Run Time" , "Name" , sched .sched , "Next" , sched .next )
178192 }
179193 sched .mu .Unlock ()
180194 case <- sched .ctx .Done ():
0 commit comments