Skip to content

Commit

Permalink
Gocron: Delaying job start and increasing ticker frequency
Browse files Browse the repository at this point in the history
  • Loading branch information
marcsantiago committed Apr 18, 2018
1 parent a9b7e2d commit c8aa208
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 46 deletions.
45 changes: 27 additions & 18 deletions gocron.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ type Job struct {
funcs map[string]interface{} // Map for the function task store
fparams map[string]([]interface{}) // Map for function and params of function
err error
shouldDo bool // indicates that jobs should start before scheduling
}

// NewJob creates a new job with the time interval.
Expand All @@ -93,29 +94,35 @@ func (j *Job) shouldRun() bool {
return b
}

// Run the job and immdiately reschedulei it
// Run the job and immdiately reschedule it
func (j *Job) run() ([]reflect.Value, error) {
f := reflect.ValueOf(j.funcs[j.jobFunc])
params := j.fparams[j.jobFunc]
if len(params) != f.Type().NumIn() {
return nil, ErrParamsNotAdapted
}

in := make([]reflect.Value, len(params))
for k, param := range params {
// should check for nil items to avoid a panic
if param == nil {
return nil, ErrParameterCannotBeNil
var result []reflect.Value
if j.shouldDo {
in := make([]reflect.Value, len(params))
for k, param := range params {
// should check for nil items to avoid a panic
if param == nil {
return nil, ErrParameterCannotBeNil
}
in[k] = reflect.ValueOf(param)
}
in[k] = reflect.ValueOf(param)
result = f.Call(in)
}
result := f.Call(in)

j.mu.Lock()
j.lastRun = time.Now()
j.mu.Unlock()

j.scheduleNextRun()
err := j.scheduleNextRun()
if err != nil {
return result, err
}

return result, nil
}
Expand Down Expand Up @@ -243,12 +250,14 @@ func (j *Job) scheduleNextRun() error {
j.mu.Unlock()
}

period, err := j.periodDuration()
if err != nil {
return err
}

// advance to next possible schedule
for j.nextRun.Before(now) || j.nextRun.Before(j.lastRun) {
period, err := j.periodDuration()
if err != nil {
return err
}
j.shouldDo = true
j.mu.Lock()
j.nextRun = j.nextRun.Add(period)
j.mu.Unlock()
Expand Down Expand Up @@ -429,8 +438,9 @@ func (s *Scheduler) NextRun() (*Job, time.Time) {
}

// Every schedule a new periodic job with interval
func (s *Scheduler) Every(interval uint64) *Job {
func (s *Scheduler) Every(interval uint64, startImmediately bool) *Job {
job := NewJob(interval)
job.shouldDo = startImmediately
s.mu.Lock()
s.jobs = append(s.jobs, job)
s.mu.Unlock()
Expand Down Expand Up @@ -507,20 +517,19 @@ func (s *Scheduler) Clear() {
// Add seconds ticker
func (s *Scheduler) Start() chan bool {
stopped := make(chan bool, 1)
ticker := time.NewTicker(1 * time.Second)
ticker := time.NewTicker(100 * time.Millisecond)

go func() {
defer ticker.Stop()
for {
select {
case <-ticker.C:
err := s.RunPending()
if err != nil {
s.err = err
ticker.Stop()
return
}
case <-stopped:
ticker.Stop()
return
}
}
Expand All @@ -535,7 +544,7 @@ var defaultScheduler = NewScheduler()

// Every schedules a new periodic job running in specific interval
func Every(interval uint64) *Job {
return defaultScheduler.Every(interval)
return defaultScheduler.Every(interval, false)
}

// RunPending run all jobs that are scheduled to run
Expand Down
56 changes: 28 additions & 28 deletions gocron_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ func assertEqualTime(name string, t *testing.T, actual, expected time.Time) {
}

func TestSecond(t *testing.T) {
defaultScheduler.Every(1).Second().Do(task)
defaultScheduler.Every(1).Second().Do(taskWithParams, 1, "hello")
defaultScheduler.Every(1, true).Second().Do(task)
defaultScheduler.Every(1, true).Second().Do(taskWithParams, 1, "hello")
stop := defaultScheduler.Start()
time.Sleep(5 * time.Second)
close(stop)
Expand Down Expand Up @@ -114,7 +114,7 @@ func TestTaskAt(t *testing.T) {

// Schedule every day At
startAt := fmt.Sprintf("%02d:%02d", now.Hour(), now.Minute()+1)
dayJob := s.Every(1).Day().At(startAt)
dayJob := s.Every(1, true).Day().At(startAt)
if err := dayJob.Err(); err != nil {
t.Error(err)
}
Expand Down Expand Up @@ -149,19 +149,19 @@ func TestDaily(t *testing.T) {
s := NewScheduler()

// schedule next run 1 day
dayJob := s.Every(1).Day()
dayJob := s.Every(1, true).Day()
dayJob.scheduleNextRun()
exp := time.Date(now.Year(), now.Month(), now.Day()+1, 0, 0, 0, 0, loc)
assertEqualTime("1 day", t, dayJob.nextRun, exp)

// schedule next run 2 days
dayJob = s.Every(2).Days()
dayJob = s.Every(2, true).Days()
dayJob.scheduleNextRun()
exp = time.Date(now.Year(), now.Month(), now.Day()+2, 0, 0, 0, 0, loc)
assertEqualTime("2 days", t, dayJob.nextRun, exp)

// Job running longer than next schedule 1day 2 hours
dayJob = s.Every(1).Day()
dayJob = s.Every(1, true).Day()
dayJob.lastRun = time.Date(now.Year(), now.Month(), now.Day(), now.Hour()+2, 0, 0, 0, loc)
dayJob.scheduleNextRun()
exp = time.Date(now.Year(), now.Month(), now.Day()+1, 0, 0, 0, 0, loc)
Expand All @@ -171,7 +171,7 @@ func TestDaily(t *testing.T) {
hour := now.Hour() - 2
minute := now.Minute()
startAt := fmt.Sprintf("%02d:%02d", hour, minute)
dayJob = s.Every(1).Day().At(startAt)
dayJob = s.Every(1, true).Day().At(startAt)
if err := dayJob.Err(); err != nil {
t.Error(err)
}
Expand All @@ -191,19 +191,19 @@ func TestWeekdayAfterToday(t *testing.T) {
var weekJob *Job
switch now.Weekday() {
case time.Monday:
weekJob = s.Every(1).Tuesday()
weekJob = s.Every(1, true).Tuesday()
case time.Tuesday:
weekJob = s.Every(1).Wednesday()
weekJob = s.Every(1, true).Wednesday()
case time.Wednesday:
weekJob = s.Every(1).Thursday()
weekJob = s.Every(1, true).Thursday()
case time.Thursday:
weekJob = s.Every(1).Friday()
weekJob = s.Every(1, true).Friday()
case time.Friday:
weekJob = s.Every(1).Saturday()
weekJob = s.Every(1, true).Saturday()
case time.Saturday:
weekJob = s.Every(1).Sunday()
weekJob = s.Every(1, true).Sunday()
case time.Sunday:
weekJob = s.Every(1).Monday()
weekJob = s.Every(1, true).Monday()
}

// First run
Expand All @@ -229,19 +229,19 @@ func TestWeekdayBeforeToday(t *testing.T) {
var weekJob *Job
switch now.Weekday() {
case time.Monday:
weekJob = s.Every(1).Sunday()
weekJob = s.Every(1, true).Sunday()
case time.Tuesday:
weekJob = s.Every(1).Monday()
weekJob = s.Every(1, true).Monday()
case time.Wednesday:
weekJob = s.Every(1).Tuesday()
weekJob = s.Every(1, true).Tuesday()
case time.Thursday:
weekJob = s.Every(1).Wednesday()
weekJob = s.Every(1, true).Wednesday()
case time.Friday:
weekJob = s.Every(1).Thursday()
weekJob = s.Every(1, true).Thursday()
case time.Saturday:
weekJob = s.Every(1).Friday()
weekJob = s.Every(1, true).Friday()
case time.Sunday:
weekJob = s.Every(1).Saturday()
weekJob = s.Every(1, true).Saturday()
}

weekJob.scheduleNextRun()
Expand Down Expand Up @@ -270,37 +270,37 @@ func TestWeekdayAt(t *testing.T) {
var weekJob *Job
switch now.Weekday() {
case time.Monday:
weekJob = s.Every(1).Tuesday().At(startAt)
weekJob = s.Every(1, true).Tuesday().At(startAt)
if err := weekJob.Err(); err != nil {
t.Error(err)
}
case time.Tuesday:
weekJob = s.Every(1).Wednesday().At(startAt)
weekJob = s.Every(1, true).Wednesday().At(startAt)
if err := weekJob.Err(); err != nil {
t.Error(err)
}
case time.Wednesday:
weekJob = s.Every(1).Thursday().At(startAt)
weekJob = s.Every(1, true).Thursday().At(startAt)
if err := weekJob.Err(); err != nil {
t.Error(err)
}
case time.Thursday:
weekJob = s.Every(1).Friday().At(startAt)
weekJob = s.Every(1, true).Friday().At(startAt)
if err := weekJob.Err(); err != nil {
t.Error(err)
}
case time.Friday:
weekJob = s.Every(1).Saturday().At(startAt)
weekJob = s.Every(1, true).Saturday().At(startAt)
if err := weekJob.Err(); err != nil {
t.Error(err)
}
case time.Saturday:
weekJob = s.Every(1).Sunday().At(startAt)
weekJob = s.Every(1, true).Sunday().At(startAt)
if err := weekJob.Err(); err != nil {
t.Error(err)
}
case time.Sunday:
weekJob = s.Every(1).Monday().At(startAt)
weekJob = s.Every(1, true).Monday().At(startAt)
if err := weekJob.Err(); err != nil {
t.Error(err)
}
Expand Down

0 comments on commit c8aa208

Please sign in to comment.