Skip to content

Commit e4edd23

Browse files
author
penglj
committed
origin modules not active,thanks robfig#317
1 parent 457b79b commit e4edd23

File tree

7 files changed

+66
-8
lines changed

7 files changed

+66
-8
lines changed

constantdelay.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ func (schedule ConstantDelaySchedule) Next(t time.Time) time.Time {
2626
return t.Add(schedule.Delay - time.Duration(t.Nanosecond())*time.Nanosecond)
2727
}
2828

29+
func (schedule ConstantDelaySchedule) IsOnce() bool {
30+
return false
31+
}
32+
2933
// Prev returns the previous time this should be run.
3034
// This rounds so that the previous activation time will be on the second.
3135
func (schedule ConstantDelaySchedule) Prev(t time.Time) time.Time {

cron.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ type Schedule interface {
5454

5555
// Prev returns the previous activation time, earlier than the given time.
5656
Prev(time.Time) time.Time
57+
IsOnce() bool
5758
}
5859

5960
// EntryID identifies an entry within a Cron instance
@@ -319,16 +320,26 @@ func (c *Cron) run() {
319320
now = now.In(c.location)
320321
c.logger.Info("wake", "now", now)
321322

323+
del := 0
324+
322325
// Run every entry whose next time was less than now
323-
for _, e := range c.entries {
326+
for k, e := range c.entries {
324327
if e.Next.After(now) || e.Next.IsZero() {
325328
break
326329
}
330+
327331
c.startJob(e.WrappedJob)
328332
e.Prev = e.Next
329333
e.Next = e.Schedule.Next(now)
330334
c.logger.Info("run", "now", now, "entry", e.ID, "next", e.Next)
335+
// only run once
336+
if e.Schedule.IsOnce() {
337+
c.entries[k] = c.entries[del]
338+
del++
339+
}
340+
331341
}
342+
c.entries = c.entries[del:]
332343

333344
case newEntry := <-c.add:
334345
timer.Stop()

cron_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,10 @@ func (*ZeroSchedule) Prev(time.Time) time.Time {
545545
return time.Time{}
546546
}
547547

548+
func (*ZeroSchedule) IsOnce() bool {
549+
return false
550+
}
551+
548552
// Tests that job without time does not run
549553
func TestJobWithZeroTimeDoesNotRun(t *testing.T) {
550554
cron := newWithSeconds()

doc.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ them in their own goroutines.
2424
c.AddFunc("CRON_TZ=Asia/Tokyo 30 04 * * *", func() { fmt.Println("Runs at 04:30 Tokyo time every day") })
2525
c.AddFunc("@hourly", func() { fmt.Println("Every hour, starting an hour from now") })
2626
c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty, starting an hour thirty from now") })
27+
c.AddFunc("@once 2020-06-02 17:04:31", func() { fmt.Println("Hello! Now is 2020-06-02 17:04:31") })
2728
c.Start()
2829
..
2930
// Funcs are invoked in their own goroutine, asynchronously.

parser.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,6 @@ func mustParseInt(expr string) (uint, error) {
358358
// getBits sets all bits in the range [min, max], modulo the given step size.
359359
func getBits(min, max, step uint) uint64 {
360360
var bits uint64
361-
362361
// If step is 1, use shifts.
363362
if step == 1 {
364363
return ^(math.MaxUint64 << (max + 1)) & (math.MaxUint64 << min)
@@ -445,5 +444,35 @@ func parseDescriptor(descriptor string, loc *time.Location) (Schedule, error) {
445444
return Every(duration), nil
446445
}
447446

447+
const once = "@once "
448+
if strings.HasPrefix(descriptor, once) {
449+
runDate, err := time.Parse("2006-01-02 15:04:05", strings.Replace(descriptor, once, "", 1))
450+
if err != nil {
451+
return nil, fmt.Errorf("failed to parse duration %s: %s", descriptor, err)
452+
}
453+
454+
var (
455+
second = uint(runDate.Second())
456+
minute = uint(runDate.Minute())
457+
hour = uint(runDate.Hour())
458+
dom = uint(runDate.Day())
459+
month = uint(runDate.Month())
460+
year = uint(runDate.Year())
461+
)
462+
463+
ret := &SpecSchedule{
464+
Second: uint64(second),
465+
Minute: uint64(minute),
466+
Hour: uint64(hour),
467+
Dom: uint64(dom),
468+
Month: uint64(month),
469+
Year: uint64(year),
470+
Dow: all(dow),
471+
Once: true,
472+
Location: loc,
473+
}
474+
return ret, nil
475+
}
476+
448477
return nil, fmt.Errorf("unrecognized descriptor: %s", descriptor)
449478
}

parser_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ func TestStandardSpecSchedule(t *testing.T) {
320320
}{
321321
{
322322
expr: "5 * * * *",
323-
expected: &SpecSchedule{1 << seconds.min, 1 << 5, all(hours), all(dom), all(months), all(dow), time.Local},
323+
expected: &SpecSchedule{1 << seconds.min, 1 << 5, all(hours), all(dom), all(months), all(dow), 0, false, time.Local},
324324
},
325325
{
326326
expr: "@every 5m",
@@ -359,15 +359,15 @@ func TestNoDescriptorParser(t *testing.T) {
359359
}
360360

361361
func every5min(loc *time.Location) *SpecSchedule {
362-
return &SpecSchedule{1 << 0, 1 << 5, all(hours), all(dom), all(months), all(dow), loc}
362+
return &SpecSchedule{1 << 0, 1 << 5, all(hours), all(dom), all(months), all(dow), 0, false, loc}
363363
}
364364

365365
func every5min5s(loc *time.Location) *SpecSchedule {
366-
return &SpecSchedule{1 << 5, 1 << 5, all(hours), all(dom), all(months), all(dow), loc}
366+
return &SpecSchedule{1 << 5, 1 << 5, all(hours), all(dom), all(months), all(dow), 0, false, loc}
367367
}
368368

369369
func midnight(loc *time.Location) *SpecSchedule {
370-
return &SpecSchedule{1, 1, 1, all(dom), all(months), all(dow), loc}
370+
return &SpecSchedule{1, 1, 1, all(dom), all(months), all(dow), 0, false, loc}
371371
}
372372

373373
func annual(loc *time.Location) *SpecSchedule {

spec.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import (
77
// SpecSchedule specifies a duty cycle (to the second granularity), based on a
88
// traditional crontab specification. It is computed initially and stored as bit sets.
99
type SpecSchedule struct {
10-
Second, Minute, Hour, Dom, Month, Dow uint64
11-
10+
Second, Minute, Hour, Dom, Month, Dow, Year uint64
11+
Once bool
1212
// Override location for this schedule.
1313
Location *time.Location
1414
}
@@ -78,9 +78,18 @@ const (
7878
starBit = 1 << 63
7979
)
8080

81+
func (s *SpecSchedule) IsOnce() bool {
82+
return s.Once
83+
}
84+
8185
// Next returns the next time this schedule is activated, greater than the given
8286
// time. If no time can be found to satisfy the schedule, return the zero time.
8387
func (s *SpecSchedule) Next(t time.Time) time.Time {
88+
// Once Task is definite datetime
89+
if s.Once {
90+
return time.Date(int(s.Year), time.Month(s.Month), int(s.Dom), int(s.Hour), int(s.Minute), int(s.Second), 0, s.Location)
91+
}
92+
8493
// General approach
8594
//
8695
// For Month, Day, Hour, Minute, Second:

0 commit comments

Comments
 (0)