From 1de7639aa1bac926f3612177e8ff0fdd97a8e37e Mon Sep 17 00:00:00 2001 From: Arjun Mahishi Date: Fri, 2 Apr 2021 18:44:56 +0530 Subject: [PATCH] Add 2 new functions to Scheduler * 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 --- example_test.go | 16 +++++++++++++++ scheduler.go | 51 ++++++++++++++++++++++++++++++----------------- scheduler_test.go | 20 +++++++++++++++++++ 3 files changed, 69 insertions(+), 18 deletions(-) diff --git a/example_test.go b/example_test.go index e2292235..de400731 100644 --- a/example_test.go +++ b/example_test.go @@ -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) +} diff --git a/scheduler.go b/scheduler.go index 683a291f..d9eb030d 100644 --- a/scheduler.go +++ b/scheduler.go @@ -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 @@ -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() @@ -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. diff --git a/scheduler_test.go b/scheduler_test.go index 5168a6b2..75653c95 100644 --- a/scheduler_test.go +++ b/scheduler_test.go @@ -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")) +}