Skip to content

Commit

Permalink
Add 2 new functions to Scheduler (#149)
Browse files Browse the repository at this point in the history
* `RunByTag` - Run all jobs that have a specific tag
* `RunByTagWithDelay` - Run all jobs that have a specific tag with a
delay in between executions

Fix: `RemoveByTag` function should remove all jobs with the given tag. Not
just the first job encountered
  • Loading branch information
arjunmahishi authored Apr 2, 2021
1 parent 3de459d commit 4cd458f
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 18 deletions.
16 changes: 16 additions & 0 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -617,3 +617,19 @@ func ExampleScheduler_Weeks() {
_, _ = s.Every(1).Week().Do(task)
_, _ = s.Every(1).Weeks().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)
}
51 changes: 33 additions & 18 deletions scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,27 @@ func (s *Scheduler) RunAllWithDelay(d time.Duration) {
}
}

// Remove specific Job job by function
// RunByTag runs all the jobs containing a specific tag
// regardless of whether they are scheduled to run or not
func (s *Scheduler) RunByTag(tag string) error {
return s.RunByTagWithDelay(tag, 0)
}

// RunByTagWithDelay is same as RunByTag but introduces a delay between
// each job execution
func (s *Scheduler) RunByTagWithDelay(tag string, d time.Duration) error {
jobs, err := s.findJobsByTag(tag)
if err != nil {
return err
}
for _, job := range jobs {
s.run(job)
s.time.Sleep(d)
}
return nil
}

// Remove specific Job by function
//
// Removing a job stops that job's timer. However, if a job has already
// been started by by the job's timer before being removed, there is no way to stop
Expand All @@ -417,7 +437,7 @@ func (s *Scheduler) Remove(job interface{}) {
})
}

// RemoveByReference removes specific Job job by reference
// RemoveByReference removes specific Job by reference
func (s *Scheduler) RemoveByReference(job *Job) {
s.removeByCondition(func(someJob *Job) bool {
job.RLock()
Expand All @@ -440,32 +460,27 @@ func (s *Scheduler) removeByCondition(shouldRemove func(*Job) bool) {

// RemoveByTag will remove a job by a given tag.
func (s *Scheduler) RemoveByTag(tag string) error {
index, err := s.findJobsIndexByTag(tag)
jobs, err := s.findJobsByTag(tag)
if err != nil {
return err
}
// Remove job if job index is valid
s.jobs[index].stop()
s.setJobs(removeAtIndex(s.jobs, index))
for _, job := range jobs {
s.RemoveByReference(job)
}
return nil
}

// Find first job index by given string
func (s *Scheduler) findJobsIndexByTag(tag string) (int, error) {
for i, job := range s.Jobs() {
func (s *Scheduler) findJobsByTag(tag string) ([]*Job, error) {
jobs := []*Job{}
for _, job := range s.Jobs() {
if strings.Contains(strings.Join(job.Tags(), " "), tag) {
return i, nil
jobs = append(jobs, job)
}
}
return -1, ErrJobNotFoundWithTag
}

func removeAtIndex(jobs []*Job, i int) []*Job {
if i == len(jobs)-1 {
return jobs[:i]
if len(jobs) > 0 {
return jobs, nil
}
jobs = append(jobs[:i], jobs[i+1:]...)
return jobs
return nil, ErrJobNotFoundWithTag
}

// LimitRunsTo limits the number of executions of this job to n.
Expand Down
20 changes: 20 additions & 0 deletions scheduler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1135,3 +1135,23 @@ func TestScheduler_Update(t *testing.T) {
assert.EqualError(t, err, ErrUpdateCalledWithoutJob.Error())
})
}

func TestScheduler_RunByTag(t *testing.T) {
var (
s = NewScheduler(time.Local)
count = 0
wg sync.WaitGroup
)

s.Every(1).Day().StartAt(time.Now().Add(time.Hour)).Tag("tag").Do(func() {
count++
wg.Done()
})
wg.Add(1)
s.StartAsync()
assert.NoError(t, s.RunByTag("tag"))

wg.Wait()
assert.Equal(t, 1, count)
assert.Error(t, s.RunByTag("wrong-tag"))
}

0 comments on commit 4cd458f

Please sign in to comment.