Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

start jobs immediately by default #82

Merged
merged 3 commits into from
Nov 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ See also these two great articles:

If you want to chat, you can find us at Slack! [<img src="https://img.shields.io/badge/gophers-gocron-brightgreen?logo=slack">](https://gophers.slack.com/archives/CQ7T0T1FW)

# Examples:
## Examples:

```go
package main
Expand Down Expand Up @@ -71,7 +71,6 @@ func main() {
tag1 := []string{"tag1"}
tag2 := []string{"tag2"}


s2.Every(1).Week().SetTag(tag1).Do(task)
s2.Every(1).Week().SetTag(tag2).Do(task)

Expand All @@ -89,13 +88,15 @@ func main() {
s2.Every(1).Wednesday().At("1:01").Do(task)

// Begin job at a specific date/time.
// Attention: scheduler timezone has precedence over job's timezone!
t := time.Date(2019, time.November, 10, 15, 0, 0, 0, time.UTC)
s2.Every(1).Hour().StartAt(t).Do(task)

// use .StartImmediately() to run job upon scheduler start
s2.Every(1).Hour().StartImmediately().Do(task)
// Delay start of job
s2.Every(1).Hour().StartAt(time.Now().Add(time.Duration(1 * time.Hour)).Do(task)

// Deprecated: Jobs start immediately by default
// use StartImmediately() to run job upon scheduler start
s2.Every(1).Hour().StartImmediately().Do(task)

// NextRun gets the next running time
_, time := s2.NextRun()
Expand Down
3 changes: 2 additions & 1 deletion example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ func ExampleScheduler_StartBlocking() {
func ExampleScheduler_StartAsync() {
s := gocron.NewScheduler(time.UTC)
_, _ = s.Every(3).Seconds().Do(task)
<-s.StartAsync()
s.StartAsync()
}

// Deprecated: All jobs start immediately by default unless set to a specific date or time
func ExampleScheduler_StartImmediately() {
s := gocron.NewScheduler(time.UTC)
_, _ = s.Every(1).Hour().StartImmediately().Do(task)
Expand Down
13 changes: 7 additions & 6 deletions job.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,13 @@ type runConfig struct {
// NewJob creates a new Job with the provided interval
func NewJob(interval uint64) *Job {
return &Job{
interval: jobInterval(interval),
lastRun: time.Time{},
nextRun: time.Time{},
funcs: make(map[string]interface{}),
fparams: make(map[string][]interface{}),
tags: []string{},
interval: jobInterval(interval),
lastRun: time.Time{},
nextRun: time.Time{},
funcs: make(map[string]interface{}),
fparams: make(map[string][]interface{}),
tags: []string{},
startsImmediately: true,
}
}

Expand Down
30 changes: 20 additions & 10 deletions scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,17 @@ func (s *Scheduler) scheduleNextRun(job *Job) {
defer job.Unlock()
now := s.time.Now(s.loc)

if job.startsImmediately {
job.nextRun = now
job.startsImmediately = false
return
if job.neverRan() {
if !job.nextRun.IsZero() {
return // scheduled for future run and should skip scheduling
}
// default is for jobs to start immediately unless scheduled at a specific time or day
if job.startsImmediately {
job.nextRun = now
return
}
}

if job.neverRan() && !job.nextRun.IsZero() {
return // scheduled for future run and should skip scheduling
}
job.lastRun = now

durationToNextRun := s.durationToNextRun(job)
Expand Down Expand Up @@ -422,6 +424,7 @@ func (s *Scheduler) At(t string) *Scheduler {
}
// save atTime start as duration from midnight
j.atTime = time.Duration(hour)*time.Hour + time.Duration(min)*time.Minute + time.Duration(sec)*time.Second
j.startsImmediately = false
return s
}

Expand All @@ -434,11 +437,14 @@ func (s *Scheduler) SetTag(t []string) *Scheduler {

// StartAt schedules the next run of the Job
func (s *Scheduler) StartAt(t time.Time) *Scheduler {
s.getCurrentJob().nextRun = t
job := s.getCurrentJob()
job.nextRun = t
job.startsImmediately = false
return s
}

// StartImmediately sets the Jobs next run as soon as the scheduler starts
// Deprecated: Jobs start immediately by default unless a specific start day or time is set
func (s *Scheduler) StartImmediately() *Scheduler {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a backward-incompatible change, right?
Is that ok?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could deprecate the fuction before removing it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like deprecating. Also, I made some updates. Setting the starts immediately value as true in the constructor and then false where appropriate in At, Start At, Weekday and Day of the Month

job := s.getCurrentJob()
job.startsImmediately = true
Expand Down Expand Up @@ -520,7 +526,9 @@ func (s *Scheduler) Month(dayOfTheMonth int) *Scheduler {

// Months sets the unit with months
func (s *Scheduler) Months(dayOfTheMonth int) *Scheduler {
s.getCurrentJob().dayOfTheMonth = dayOfTheMonth
job := s.getCurrentJob()
job.dayOfTheMonth = dayOfTheMonth
job.startsImmediately = false
s.setUnit(months)
return s
}
Expand All @@ -532,7 +540,9 @@ func (s *Scheduler) Months(dayOfTheMonth int) *Scheduler {

// Weekday sets the start with a specific weekday weekday
func (s *Scheduler) Weekday(startDay time.Weekday) *Scheduler {
s.getCurrentJob().scheduledWeekday = &startDay
job := s.getCurrentJob()
job.scheduledWeekday = &startDay
job.startsImmediately = false
s.setUnit(weeks)
return s
}
Expand Down
68 changes: 40 additions & 28 deletions scheduler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func TestExecutionSeconds(t *testing.T) {
var (
executions []int64
interval uint64 = 2
expectedExecutions = 3
expectedExecutions = 4
)

runTime := time.Duration(6 * time.Second)
Expand Down Expand Up @@ -135,22 +135,50 @@ func TestAtFuture(t *testing.T) {
assert.Equal(t, false, shouldBeFalse, "Day job was not expected to run as it was in the future")
}

func schedulerForNextWeekdayEveryNTimes(weekday time.Weekday, n uint64, s *Scheduler) *Scheduler {
func schedulerForNextOrPreviousWeekdayEveryNTimes(weekday time.Weekday, next bool, n uint64, s *Scheduler) *Scheduler {
switch weekday {
case time.Monday:
s = s.Every(n).Tuesday()
if next {
s = s.Every(n).Tuesday()
} else {
s = s.Every(n).Sunday()
}
case time.Tuesday:
s = s.Every(n).Wednesday()
if next {
s = s.Every(n).Wednesday()
} else {
s = s.Every(n).Monday()
}
case time.Wednesday:
s = s.Every(n).Thursday()
if next {
s = s.Every(n).Thursday()
} else {
s = s.Every(n).Tuesday()
}
case time.Thursday:
s = s.Every(n).Friday()
if next {
s = s.Every(n).Friday()
} else {
s = s.Every(n).Wednesday()
}
case time.Friday:
s = s.Every(n).Saturday()
if next {
s = s.Every(n).Saturday()
} else {
s = s.Every(n).Thursday()
}
case time.Saturday:
s = s.Every(n).Sunday()
if next {
s = s.Every(n).Sunday()
} else {
s = s.Every(n).Friday()
}
case time.Sunday:
s = s.Every(n).Monday()
if next {
s = s.Every(n).Monday()
} else {
s = s.Every(n).Saturday()
}
}
return s
}
Expand All @@ -159,23 +187,7 @@ func TestWeekdayBeforeToday(t *testing.T) {
now := time.Now().In(time.UTC)
s := NewScheduler(time.UTC)

// Schedule job at day before
switch now.Weekday() {
case time.Monday:
s = s.Every(1).Sunday()
case time.Tuesday:
s = s.Every(1).Monday()
case time.Wednesday:
s = s.Every(1).Tuesday()
case time.Thursday:
s = s.Every(1).Wednesday()
case time.Friday:
s = s.Every(1).Thursday()
case time.Saturday:
s = s.Every(1).Friday()
case time.Sunday:
s = s.Every(1).Saturday()
}
s = schedulerForNextOrPreviousWeekdayEveryNTimes(now.Weekday(), false, 1, s)
weekJob, _ := s.Do(task)
s.scheduleNextRun(weekJob)
sixDaysFromNow := now.AddDate(0, 0, 6)
Expand All @@ -188,7 +200,7 @@ func TestWeekdayAt(t *testing.T) {
t.Run("asserts weekday scheduling starts at the current week", func(t *testing.T) {
s := NewScheduler(time.UTC)
now := time.Now().UTC()
s = schedulerForNextWeekdayEveryNTimes(now.Weekday(), 1, s)
s = schedulerForNextOrPreviousWeekdayEveryNTimes(now.Weekday(), true, 1, s)
weekdayJob, _ := s.Do(task)

s.scheduleNextRun(weekdayJob)
Expand Down Expand Up @@ -386,7 +398,7 @@ func TestScheduler_StartAt(t *testing.T) {
job, _ = scheduler.Every(3).Seconds().Do(func() {})
scheduler.scheduleNextRun(job)
_, nextRun = scheduler.NextRun()
assert.Equal(t, now.Add(time.Second*3).Second(), nextRun.Second())
assert.Equal(t, now.Second(), nextRun.Second())
}

func TestScheduler_CalculateNextRun(t *testing.T) {
Expand Down