Skip to content

Commit

Permalink
Gocron: Using functional options to keep the API while adding customi…
Browse files Browse the repository at this point in the history
…zations
  • Loading branch information
marcsantiago committed Jul 20, 2019
1 parent c8aa208 commit c18ed51
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 35 deletions.
22 changes: 15 additions & 7 deletions gocron.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ func ChangeLoc(newLocation *time.Location) {

// Job struct keeping information about job
type Job struct {
ShouldDoImmediately bool // indicates that jobs should start before scheduling

mu *sync.Mutex
interval uint64 // pause interval * unit bettween runs
jobFunc string // the job jobFunc to run, func[jobFunc]
Expand All @@ -67,7 +69,6 @@ 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 Down Expand Up @@ -103,7 +104,7 @@ func (j *Job) run() ([]reflect.Value, error) {
}

var result []reflect.Value
if j.shouldDo {
if j.ShouldDoImmediately {
in := make([]reflect.Value, len(params))
for k, param := range params {
// should check for nil items to avoid a panic
Expand Down Expand Up @@ -257,7 +258,7 @@ func (j *Job) scheduleNextRun() error {

// advance to next possible schedule
for j.nextRun.Before(now) || j.nextRun.Before(j.lastRun) {
j.shouldDo = true
j.ShouldDoImmediately = true
j.mu.Lock()
j.nextRun = j.nextRun.Add(period)
j.mu.Unlock()
Expand Down Expand Up @@ -438,9 +439,12 @@ func (s *Scheduler) NextRun() (*Job, time.Time) {
}

// Every schedule a new periodic job with interval
func (s *Scheduler) Every(interval uint64, startImmediately bool) *Job {
func (s *Scheduler) Every(interval uint64, options ...func(*Job)) *Job {
job := NewJob(interval)
job.shouldDo = startImmediately
for _, option := range options {
option(job)
}

s.mu.Lock()
s.jobs = append(s.jobs, job)
s.mu.Unlock()
Expand Down Expand Up @@ -543,8 +547,12 @@ func (s *Scheduler) Start() chan bool {
var defaultScheduler = NewScheduler()

// Every schedules a new periodic job running in specific interval
func Every(interval uint64) *Job {
return defaultScheduler.Every(interval, false)
func Every(interval uint64, options ...func(*Job)) *Job {
job := defaultScheduler.Every(interval)
for _, option := range options {
option(job)
}
return job
}

// RunPending run all jobs that are scheduled to run
Expand Down
61 changes: 33 additions & 28 deletions gocron_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import (
"time"
)

var defaultOption = func(j *Job) {
j.ShouldDoImmediately = true
}

func task() {
fmt.Println("I am a running job.")
}
Expand All @@ -21,8 +25,9 @@ func assertEqualTime(name string, t *testing.T, actual, expected time.Time) {
}

func TestSecond(t *testing.T) {
defaultScheduler.Every(1, true).Second().Do(task)
defaultScheduler.Every(1, true).Second().Do(taskWithParams, 1, "hello")

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

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

// schedule next run 1 day
dayJob := s.Every(1, true).Day()
dayJob := s.Every(1, defaultOption).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, true).Days()
dayJob = s.Every(2, defaultOption).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, true).Day()
dayJob = s.Every(1, defaultOption).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 +176,7 @@ func TestDaily(t *testing.T) {
hour := now.Hour() - 2
minute := now.Minute()
startAt := fmt.Sprintf("%02d:%02d", hour, minute)
dayJob = s.Every(1, true).Day().At(startAt)
dayJob = s.Every(1, defaultOption).Day().At(startAt)
if err := dayJob.Err(); err != nil {
t.Error(err)
}
Expand All @@ -191,19 +196,19 @@ func TestWeekdayAfterToday(t *testing.T) {
var weekJob *Job
switch now.Weekday() {
case time.Monday:
weekJob = s.Every(1, true).Tuesday()
weekJob = s.Every(1, defaultOption).Tuesday()
case time.Tuesday:
weekJob = s.Every(1, true).Wednesday()
weekJob = s.Every(1, defaultOption).Wednesday()
case time.Wednesday:
weekJob = s.Every(1, true).Thursday()
weekJob = s.Every(1, defaultOption).Thursday()
case time.Thursday:
weekJob = s.Every(1, true).Friday()
weekJob = s.Every(1, defaultOption).Friday()
case time.Friday:
weekJob = s.Every(1, true).Saturday()
weekJob = s.Every(1, defaultOption).Saturday()
case time.Saturday:
weekJob = s.Every(1, true).Sunday()
weekJob = s.Every(1, defaultOption).Sunday()
case time.Sunday:
weekJob = s.Every(1, true).Monday()
weekJob = s.Every(1, defaultOption).Monday()
}

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

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

0 comments on commit c18ed51

Please sign in to comment.