Skip to content

Commit

Permalink
add start immediately func (#229)
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnRoesler authored Sep 9, 2021
1 parent 177e5d5 commit cd3ac43
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 74 deletions.
50 changes: 28 additions & 22 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,22 @@ func ExampleScheduler_RunAllWithDelay() {
s.RunAllWithDelay(10 * time.Second)
}

func ExampleScheduler_RunByTag() {
s := gocron.NewScheduler(time.UTC)
_, _ = s.Every(1).Day().At("10:00").Do(task)
_, _ = s.Every(2).Day().Tag("tag").At("10:00").Do(task)
s.StartAsync()
_ = s.RunByTag("tag")
}

func ExampleScheduler_RunByTagWithDelay() {
s := gocron.NewScheduler(time.UTC)
_, _ = s.Every(1).Day().Tag("tag").At("10:00").Do(task)
_, _ = s.Every(2).Day().Tag("tag").At("10:00").Do(task)
s.StartAsync()
_ = s.RunByTagWithDelay("tag", 2*time.Second)
}

func ExampleScheduler_Saturday() {
s := gocron.NewScheduler(time.UTC)
j, _ := s.Every(1).Day().Saturday().Do(task)
Expand Down Expand Up @@ -502,12 +518,6 @@ func ExampleScheduler_SingletonMode() {
_, _ = s.Every(1).Second().SingletonMode().Do(task)
}

func ExampleScheduler_StartBlocking() {
s := gocron.NewScheduler(time.UTC)
_, _ = s.Every(3).Seconds().Do(task)
s.StartBlocking()
}

func ExampleScheduler_StartAsync() {
s := gocron.NewScheduler(time.UTC)
_, _ = s.Every(3).Seconds().Do(task)
Expand All @@ -521,6 +531,18 @@ func ExampleScheduler_StartAt() {
s.StartBlocking()
}

func ExampleScheduler_StartBlocking() {
s := gocron.NewScheduler(time.UTC)
_, _ = s.Every(3).Seconds().Do(task)
s.StartBlocking()
}

func ExampleScheduler_StartImmediately() {
s := gocron.NewScheduler(time.UTC)
_, _ = s.Cron("0 0 * * 6,0").StartImmediately().Do(task)
s.StartBlocking()
}

func ExampleScheduler_Stop() {
s := gocron.NewScheduler(time.UTC)
_, _ = s.Every(1).Second().Do(task)
Expand Down Expand Up @@ -671,19 +693,3 @@ func ExampleScheduler_Weeks() {

_, _ = s.Every(2).Weeks().Monday().Wednesday().Friday().Do(task)
}

func ExampleScheduler_RunByTag() {
s := gocron.NewScheduler(time.UTC)
_, _ = s.Every(1).Day().At("10:00").Do(task)
_, _ = s.Every(2).Day().Tag("tag").At("10:00").Do(task)
s.StartAsync()
_ = s.RunByTag("tag")
}

func ExampleScheduler_RunByTagWithDelay() {
s := gocron.NewScheduler(time.UTC)
_, _ = s.Every(1).Day().Tag("tag").At("10:00").Do(task)
_, _ = s.Every(2).Day().Tag("tag").At("10:00").Do(task)
s.StartAsync()
_ = s.RunByTagWithDelay("tag", 2*time.Second)
}
2 changes: 1 addition & 1 deletion gocron.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (

// Error declarations for gocron related errors
var (
ErrNotAFunction = errors.New("only functions can be schedule into the job queue")
ErrNotAFunction = errors.New("only functions can be scheduled into the job queue")
ErrNotScheduledWeekday = errors.New("job not scheduled weekly on a weekday")
ErrJobNotFoundWithTag = errors.New("no jobs found with given tag")
ErrUnsupportedTimeFormat = errors.New("the given time format is not supported")
Expand Down
64 changes: 32 additions & 32 deletions job.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@ import (

// Job struct stores the information necessary to run a Job
type Job struct {
sync.RWMutex
mu sync.RWMutex
jobFunction
interval int // pause interval * unit between runs
duration time.Duration // time duration between runs
unit schedulingUnit // time units, ,e.g. 'minutes', 'hours'...
unit schedulingUnit // time units, e.g. 'minutes', 'hours'...
startsImmediately bool // if the Job should run upon scheduler start
atTime time.Duration // optional time at which this Job runs when interval is day
startAtTime time.Time // optional time at which the Job starts
error error // error related to Job
lastRun time.Time // datetime of last run
nextRun time.Time // datetime of next run
scheduledWeekday []time.Weekday // Specific days of the week to start on
scheduledWeekdays []time.Weekday // Specific days of the week to start on
daysOfTheMonth []int // Specific days of the month to run the job
tags []string // allow the user to tag Jobs with certain labels
runCount int // number of times the job ran
Expand Down Expand Up @@ -88,8 +88,8 @@ func (j *Job) setStartsImmediately(b bool) {
}

func (j *Job) setTimer(t *time.Timer) {
j.Lock()
defer j.Unlock()
j.mu.Lock()
defer j.mu.Unlock()
j.timer = t
}

Expand All @@ -110,26 +110,26 @@ func (j *Job) setStartAtTime(t time.Time) {
}

func (j *Job) getUnit() schedulingUnit {
j.RLock()
defer j.RUnlock()
j.mu.RLock()
defer j.mu.RUnlock()
return j.unit
}

func (j *Job) setUnit(t schedulingUnit) {
j.Lock()
defer j.Unlock()
j.mu.Lock()
defer j.mu.Unlock()
j.unit = t
}

func (j *Job) getDuration() time.Duration {
j.RLock()
defer j.RUnlock()
j.mu.RLock()
defer j.mu.RUnlock()
return j.duration
}

func (j *Job) setDuration(t time.Duration) {
j.Lock()
defer j.Unlock()
j.mu.Lock()
defer j.mu.Unlock()
j.duration = t
}

Expand Down Expand Up @@ -165,8 +165,8 @@ func (j *Job) Tags() []string {

// ScheduledTime returns the time of the Job's next scheduled run
func (j *Job) ScheduledTime() time.Time {
j.RLock()
defer j.RUnlock()
j.mu.RLock()
defer j.mu.RUnlock()
return j.nextRun
}

Expand All @@ -178,21 +178,21 @@ func (j *Job) ScheduledAtTime() string {
// Weekday returns which day of the week the Job will run on and
// will return an error if the Job is not scheduled weekly
func (j *Job) Weekday() (time.Weekday, error) {
if len(j.scheduledWeekday) == 0 {
if len(j.scheduledWeekdays) == 0 {
return time.Sunday, ErrNotScheduledWeekday
}
return j.scheduledWeekday[0], nil
return j.scheduledWeekdays[0], nil
}

// Weekdays returns a slice of time.Weekday that the Job will run in a week and
// will return an error if the Job is not scheduled weekly
func (j *Job) Weekdays() []time.Weekday {
// appending on j.scheduledWeekday may cause a side effect
if len(j.scheduledWeekday) == 0 {
// appending on j.scheduledWeekdays may cause a side effect
if len(j.scheduledWeekdays) == 0 {
return []time.Weekday{time.Sunday}
}

return j.scheduledWeekday
return j.scheduledWeekdays
}

// LimitRunsTo limits the number of executions of this job to n.
Expand All @@ -204,8 +204,8 @@ func (j *Job) Weekdays() []time.Weekday {
// LimitRunsTo() func on the scheduler chain when scheduling the job.
// For example: scheduler.LimitRunsTo(1).Do()
func (j *Job) LimitRunsTo(n int) {
j.Lock()
defer j.Unlock()
j.mu.Lock()
defer j.mu.Unlock()
j.runConfig.finiteRuns = true
j.runConfig.maxRuns = n
}
Expand All @@ -217,8 +217,8 @@ func (j *Job) LimitRunsTo(n int) {
// by default upon being added to the scheduler. It is recommended to use the
// SingletonMode() func on the scheduler chain when scheduling the job.
func (j *Job) SingletonMode() {
j.Lock()
defer j.Unlock()
j.mu.Lock()
defer j.mu.Unlock()
j.runConfig.mode = singletonMode
j.jobFunction.limiter = &singleflight.Group{}

Expand All @@ -227,8 +227,8 @@ func (j *Job) SingletonMode() {
// shouldRun evaluates if this job should run again
// based on the runConfig
func (j *Job) shouldRun() bool {
j.RLock()
defer j.RUnlock()
j.mu.RLock()
defer j.mu.RUnlock()
return !j.runConfig.finiteRuns || j.runCount < j.runConfig.maxRuns
}

Expand All @@ -243,14 +243,14 @@ func (j *Job) setLastRun(t time.Time) {

// NextRun returns the time the job will run next
func (j *Job) NextRun() time.Time {
j.RLock()
defer j.RUnlock()
j.mu.RLock()
defer j.mu.RUnlock()
return j.nextRun
}

func (j *Job) setNextRun(t time.Time) {
j.Lock()
defer j.Unlock()
j.mu.Lock()
defer j.mu.Unlock()
j.nextRun = t
}

Expand All @@ -260,8 +260,8 @@ func (j *Job) RunCount() int {
}

func (j *Job) stop() {
j.Lock()
defer j.Unlock()
j.mu.Lock()
defer j.mu.Unlock()
if j.timer != nil {
j.timer.Stop()
}
Expand Down
39 changes: 27 additions & 12 deletions scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import (

type limitMode int8

// Scheduler struct stores a list of Jobs and the location of time Scheduler
// Scheduler implements the sort.Interface{} for sorting Jobs, by the time of nextRun
// Scheduler struct stores a list of Jobs and the location of time used by the Scheduler,
// and implements the sort.Interface{} for sorting Jobs, by the time of nextRun
type Scheduler struct {
jobsMutex sync.RWMutex
jobs []*Job
Expand Down Expand Up @@ -222,7 +222,7 @@ func (s *Scheduler) durationToNextRun(lastRun time.Time, job *Job) nextRun {
case days:
next = s.calculateDays(job, lastRun)
case weeks:
if len(job.scheduledWeekday) != 0 { // weekday selected, Every().Monday(), for example
if len(job.scheduledWeekdays) != 0 { // weekday selected, Every().Monday(), for example
next = s.calculateWeekday(job, lastRun)
} else {
next = s.calculateWeeks(job, lastRun)
Expand Down Expand Up @@ -496,8 +496,8 @@ func (s *Scheduler) run(job *Job) {
return
}

job.Lock()
defer job.Unlock()
job.mu.Lock()
defer job.mu.Unlock()
job.setLastRun(s.now())
job.runCount++
s.executor.jobFunctions <- job.jobFunction
Expand Down Expand Up @@ -556,8 +556,8 @@ func (s *Scheduler) Remove(job interface{}) {
func (s *Scheduler) RemoveByReference(job *Job) {
s.removeJobsUniqueTags(job)
s.removeByCondition(func(someJob *Job) bool {
job.RLock()
defer job.RUnlock()
job.mu.RLock()
defer job.mu.RUnlock()
return someJob == job
})
}
Expand Down Expand Up @@ -706,7 +706,7 @@ func (s *Scheduler) Do(jobFun interface{}, params ...interface{}) (*Job, error)
job.error = wrapOrError(job.error, ErrAtTimeNotSupported)
}

if len(job.scheduledWeekday) != 0 && jobUnit != weeks {
if len(job.scheduledWeekdays) != 0 && jobUnit != weeks {
job.error = wrapOrError(job.error, ErrWeekdayNotSupported)
}

Expand Down Expand Up @@ -738,7 +738,7 @@ func (s *Scheduler) Do(jobFun interface{}, params ...interface{}) (*Job, error)
job.name = fname
}

// we should not schedule if not running since we cant foresee how long it will take for the scheduler to start
// we should not schedule if not running since we can't foresee how long it will take for the scheduler to start
if s.IsRunning() {
s.scheduleNextRun(job)
}
Expand Down Expand Up @@ -928,12 +928,12 @@ func (s *Scheduler) Months(daysOfTheMonth ...int) *Scheduler {
// spill over to the next month. Similarly, if it's less than 0,
// it will go back to the month before

// Weekday sets the scheduledWeekday with a specifics weekdays
// Weekday sets the scheduledWeekdays with a specifics weekdays
func (s *Scheduler) Weekday(weekDay time.Weekday) *Scheduler {
job := s.getCurrentJob()

if in := in(job.scheduledWeekday, weekDay); !in {
job.scheduledWeekday = append(job.scheduledWeekday, weekDay)
if in := in(job.scheduledWeekdays, weekDay); !in {
job.scheduledWeekdays = append(job.scheduledWeekdays, weekDay)
}

job.startsImmediately = false
Expand Down Expand Up @@ -1085,3 +1085,18 @@ func (s *Scheduler) WaitForSchedule() *Scheduler {
job.startsImmediately = false
return s
}

// StartImmediately sets the job to run immediately upon
// starting the scheduler or adding the job to a running
// scheduler. This overrides the jobs start status of any
// previously called methods in the chain.
//
// Note: This is the default behavior of the scheduler
// for most jobs, but is useful for overriding the default
// behavior of Cron scheduled jobs which default to
// WaitForSchedule.
func (s *Scheduler) StartImmediately() *Scheduler {
job := s.getCurrentJob()
job.startsImmediately = true
return s
}
Loading

0 comments on commit cd3ac43

Please sign in to comment.