Skip to content

Commit

Permalink
fix: the cron job with precise second time pattern might be executed …
Browse files Browse the repository at this point in the history
…twice in the same time (#3437)
  • Loading branch information
gqcn committed Mar 28, 2024
1 parent 1c12f3a commit 6df0a9c
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 30 deletions.
2 changes: 1 addition & 1 deletion contrib/config/consul/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/gogf/gf/contrib/config/consul/v2

go 1.19
go 1.18

require (
github.com/gogf/gf/v2 v2.6.4
Expand Down
2 changes: 1 addition & 1 deletion contrib/config/kubecm/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/gogf/gf/contrib/config/kubecm/v2

go 1.19
go 1.18

require (
github.com/gogf/gf/v2 v2.6.4
Expand Down
2 changes: 1 addition & 1 deletion contrib/metric/otelmetric/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/gogf/gf/contrib/metric/otelmetric/v2

go 1.20
go 1.18

require (
github.com/gogf/gf/v2 v2.6.1
Expand Down
2 changes: 1 addition & 1 deletion contrib/trace/otlpgrpc/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/gogf/gf/contrib/trace/otlpgrpc/v2

go 1.20
go 1.18

require (
github.com/gogf/gf/v2 v2.6.1
Expand Down
2 changes: 1 addition & 1 deletion contrib/trace/otlphttp/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/gogf/gf/contrib/trace/otlphttp/v2

go 1.20
go 1.18

require (
github.com/gogf/gf/v2 v2.6.1
Expand Down
9 changes: 7 additions & 2 deletions os/gcron/gcron_cron.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ func (c *Cron) GetLogger() glog.ILogger {

// AddEntry creates and returns a new Entry object.
func (c *Cron) AddEntry(
ctx context.Context, pattern string, job JobFunc, times int, isSingleton bool, name ...string,
ctx context.Context,
pattern string,
job JobFunc,
times int,
isSingleton bool,
name ...string,
) (*Entry, error) {
var (
entryName = ""
Expand Down Expand Up @@ -204,7 +209,7 @@ func (c *Cron) Entries() []*Entry {
array := garray.NewSortedArraySize(c.entries.Size(), func(v1, v2 interface{}) int {
entry1 := v1.(*Entry)
entry2 := v2.(*Entry)
if entry1.Time.Nanosecond() > entry2.Time.Nanosecond() {
if entry1.RegisterTime.Nanosecond() > entry2.RegisterTime.Nanosecond() {
return 1
}
return -1
Expand Down
32 changes: 16 additions & 16 deletions os/gcron/gcron_entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ type JobFunc = gtimer.JobFunc

// Entry is timing task entry.
type Entry struct {
cron *Cron // Cron object belonged to.
timerEntry *gtimer.Entry // Associated timer Entry.
schedule *cronSchedule // Timed schedule object.
jobName string // Callback function name(address info).
times *gtype.Int // Running times limit.
infinite *gtype.Bool // No times limit.
Name string // Entry name.
Job JobFunc `json:"-"` // Callback function.
Time time.Time // Registered time.
cron *Cron // Cron object belonged to.
timerEntry *gtimer.Entry // Associated timer Entry.
schedule *cronSchedule // Timed schedule object.
jobName string // Callback function name(address info).
times *gtype.Int // Running times limit.
infinite *gtype.Bool // No times limit.
Name string // Entry name.
RegisterTime time.Time // Registered time.
Job JobFunc `json:"-"` // Callback function.
}

type doAddEntryInput struct {
Expand Down Expand Up @@ -64,13 +64,13 @@ func (c *Cron) doAddEntry(in doAddEntryInput) (*Entry, error) {
}
// No limit for `times`, for timer checking scheduling every second.
entry := &Entry{
cron: c,
schedule: schedule,
jobName: runtime.FuncForPC(reflect.ValueOf(in.Job).Pointer()).Name(),
times: gtype.NewInt(in.Times),
infinite: gtype.NewBool(in.Infinite),
Job: in.Job,
Time: time.Now(),
cron: c,
schedule: schedule,
jobName: runtime.FuncForPC(reflect.ValueOf(in.Job).Pointer()).Name(),
times: gtype.NewInt(in.Times),
infinite: gtype.NewBool(in.Infinite),
RegisterTime: time.Now(),
Job: in.Job,
}
if in.Name != "" {
entry.Name = in.Name
Expand Down
5 changes: 5 additions & 0 deletions os/gcron/gcron_schedule_check.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ func (s *cronSchedule) checkMeetSecond(lastMeetTime, currentTime time.Time) (ok
return false
}
} else {
// If this pattern is set in precise second time,
// it is not allowed executed in the same time.
if len(s.secondMap) == 1 && lastMeetTime.Format(time.RFC3339) == currentTime.Format(time.RFC3339) {
return false
}
if !s.keyMatch(s.secondMap, currentTime.Second()) {
return false
}
Expand Down
14 changes: 7 additions & 7 deletions os/gcron/gcron_schedule_fix.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,26 @@ func (s *cronSchedule) getAndUpdateLastCheckTimestamp(ctx context.Context, t tim
lastCheckTimestamp = s.lastCheckTimestamp.Val()
)
switch {
// Often happens, timer triggers in the same second.
// Often happens, timer triggers in the same second, but the millisecond is different.
// Example:
// lastCheckTimestamp: 10
// currentTimestamp: 10
// lastCheckTimestamp: 2024-03-26 19:47:34.000
// currentTimestamp: 2024-03-26 19:47:34.999
case
lastCheckTimestamp == currentTimestamp:
lastCheckTimestamp += 1

// Often happens, no latency.
// Example:
// lastCheckTimestamp: 9
// currentTimestamp: 10
// lastCheckTimestamp: 2024-03-26 19:47:34.000
// currentTimestamp: 2024-03-26 19:47:35.000
case
lastCheckTimestamp == currentTimestamp-1:
lastCheckTimestamp = currentTimestamp

// Latency in 3 seconds, which can be tolerant.
// Example:
// lastCheckTimestamp: 7/8
// currentTimestamp: 10
// lastCheckTimestamp: 2024-03-26 19:47:31.000、2024-03-26 19:47:32.000
// currentTimestamp: 2024-03-26 19:47:34.000
case
lastCheckTimestamp == currentTimestamp-2,
lastCheckTimestamp == currentTimestamp-3:
Expand Down

0 comments on commit 6df0a9c

Please sign in to comment.