From 8c7e3da6cc039f13733861a8e467dfc38caed052 Mon Sep 17 00:00:00 2001 From: Yusuf Date: Wed, 29 Apr 2020 09:55:51 +0700 Subject: [PATCH] Add Feature Delete Job By Tag (#33) * Update README.md * Add Feature Delete Job By Tag Update Readme How to Use Add Tag and Remove Job By Tag Add Test Create and Delete Job By Tag * Add Feature Delete Job By Tag Update Readme How to Use Add Tag and Remove Job By Tag Add Test Create and Delete Job By Tag * Add Exported Error Message Change logic when deleting jobs with tag function * Update Logic RemoveTag Return Rerr Update logic to golang best practice error checking Co-authored-by: John Roesler Co-authored-by: Streppel --- README.md | 12 ++++++++++++ gocron.go | 1 + scheduler.go | 29 +++++++++++++++++++++++++++++ scheduler_test.go | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+) diff --git a/README.md b/README.md index de0a0e29..26a9256c 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,18 @@ func main() { // Do jobs with params s2.Every(1).Second().Do(taskWithParams, 1, "hello") + // Do Jobs with tags + // initialize tag + tag1 := []string{"tag1"} + tag2 := []string{"tag2"} + + + s2.Every(1).Week().SetTag(tag1).Do(task) + s2.Every(1).Week().SetTag(tag2).Do(task) + + // Removing Job Based on Tag + scheduler.RemoveJobByTag("tag1") + // Do jobs on specific weekday s2.Every(1).Monday().Do(task) s2.Every(1).Thursday().Do(task) diff --git a/gocron.go b/gocron.go index 641b0d89..d5a303e6 100644 --- a/gocron.go +++ b/gocron.go @@ -27,6 +27,7 @@ var ( ErrNotAFunction = errors.New("only functions can be schedule into the job queue") ErrPeriodNotSpecified = errors.New("unspecified job period") ErrNotScheduledWeekday = errors.New("job not scheduled weekly on a weekday") + ErrJobNotFoundWithTag = errors.New("no jobs found with given tag") ) type timeUnit int diff --git a/scheduler.go b/scheduler.go index e35952f1..da30db34 100644 --- a/scheduler.go +++ b/scheduler.go @@ -4,6 +4,7 @@ import ( "fmt" "reflect" "sort" + "strings" "time" ) @@ -209,6 +210,27 @@ func (s *Scheduler) removeByCondition(shouldRemove func(*Job) bool) { } } +// RemoveJobByTag will Remove Jobs by Tag +func (s *Scheduler) RemoveJobByTag(tag string) error { + jobindex, err := s.findJobsIndexByTag(tag) + if err != nil { + return err + } + // Remove job if jobindex is valid + s.jobs = removeAtIndex(s.jobs, jobindex) + return nil +} + +// Find first job index by given string +func (s *Scheduler) findJobsIndexByTag(tag string) (int, error) { + for i, job := range s.jobs { + if strings.Contains(strings.Join(job.Tags(), " "), tag) { + return i, nil + } + } + return -1, ErrJobNotFoundWithTag +} + func removeAtIndex(jobs []*Job, i int) []*Job { if i == len(jobs)-1 { return jobs[:i] @@ -292,6 +314,13 @@ func (s *Scheduler) At(t string) *Scheduler { return s } +// SetTag will add tag when creating a job +func (s *Scheduler) SetTag(t []string) *Scheduler { + job := s.getCurrentJob() + job.tags = t + return s +} + // StartAt schedules the next run of the Job func (s *Scheduler) StartAt(t time.Time) *Scheduler { s.getCurrentJob().nextRun = t diff --git a/scheduler_test.go b/scheduler_test.go index c020bd80..1adce944 100644 --- a/scheduler_test.go +++ b/scheduler_test.go @@ -59,6 +59,15 @@ func TestScheduled(t *testing.T) { } } +func TestScheduledWithTag(t *testing.T) { + sched := NewScheduler(time.UTC) + customtag := []string{"mycustomtag"} + sched.Every(1).Hour().SetTag(customtag).Do(task) + if !sched.Scheduled(task) { + t.Fatal("Task was scheduled but function couldn't find it") + } +} + func TestStartImmediately(t *testing.T) { sched := NewScheduler(time.UTC) now := time.Now().UTC() @@ -381,6 +390,31 @@ func TestRemoveByRef(t *testing.T) { assert.ElementsMatch(t, []*Job{job2}, scheduler.Jobs()) } +func TestRemoveByTag(t *testing.T) { + scheduler := NewScheduler(time.UTC) + + // Creating 2 Jobs with Unique tags + customtag1 := []string{"tag one"} + customtag2 := []string{"tag two"} + scheduler.Every(1).Minute().SetTag(customtag1).Do(taskWithParams, 1, "hello") // index 0 + scheduler.Every(1).Minute().SetTag(customtag2).Do(taskWithParams, 2, "world") // index 1 + + assert.Equal(t, 2, scheduler.Len(), "Incorrect number of jobs") + + // check Jobs()[0] tags is equal with tag "tag one" (customtag1) + assert.Equal(t, scheduler.Jobs()[0].Tags(), customtag1, "Job With Tag 'tag one' is removed from index 0") + + scheduler.RemoveJobByTag("tag one") + assert.Equal(t, 1, scheduler.Len(), "Incorrect number of jobs after removing 1 job") + + // check Jobs()[0] tags is equal with tag "tag two" (customtag2) after removing "tag one" + assert.Equal(t, scheduler.Jobs()[0].Tags(), customtag2, "Job With Tag 'tag two' is removed from index 0") + + // Removing Non Existent Job with "tag one" because already removed above (will not removing any jobs because tag not match) + scheduler.RemoveJobByTag("tag one") + assert.Equal(t, 1, scheduler.Len(), "Incorrect number of jobs after removing non-existent job") +} + func TestJobs(t *testing.T) { s := NewScheduler(time.UTC) s.Every(1).Minute().Do(task)