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

add start immediately func #229

Merged
merged 2 commits into from
Sep 9, 2021
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
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