Skip to content

Commit

Permalink
Merge pull request #39 from go-co-op/bugfix/38
Browse files Browse the repository at this point in the history
fixes 38
  • Loading branch information
Streppel committed May 25, 2020
2 parents 8c7e3da + e6d47c5 commit 4cc1bfb
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 17 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func main() {
s2.Every(1).Week().SetTag(tag2).Do(task)

// Removing Job Based on Tag
scheduler.RemoveJobByTag("tag1")
s2.RemoveJobByTag("tag1")

// Do jobs on specific weekday
s2.Every(1).Monday().Do(task)
Expand Down Expand Up @@ -98,6 +98,9 @@ func main() {
// Clear all scheduled jobs
s2.Clear()

// stop our first scheduler (it still exists but doesn't run anymore)
s1.Stop()

// executes the scheduler and blocks current thread
s2.StartBlocking()

Expand Down
2 changes: 1 addition & 1 deletion job.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type Job struct {

// NewJob creates a new Job with the provided interval
func NewJob(interval uint64) *Job {
th := newTimeHelper()
th := newTimeWrapper()
return &Job{
interval: interval,
lastRun: th.Unix(0, 0),
Expand Down
42 changes: 29 additions & 13 deletions scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,21 @@ import (
type Scheduler struct {
jobs []*Job
loc *time.Location
time timeHelper // an instance of timeHelper to interact with the time package

running bool
stopChan chan struct{} // signal to stop scheduling

time timeWrapper // wrapper around time.Time
}

// NewScheduler creates a new Scheduler
func NewScheduler(loc *time.Location) *Scheduler {
return &Scheduler{
jobs: newEmptyJobSlice(),
loc: loc,
time: newTimeHelper(),
jobs: make([]*Job, 0),
loc: loc,
running: false,
stopChan: make(chan struct{}),
time: newTimeWrapper(),
}
}

Expand All @@ -32,22 +38,26 @@ func (s *Scheduler) StartBlocking() {

// StartAsync starts a goroutine that runs all the pending using a second-long ticker
func (s *Scheduler) StartAsync() chan struct{} {
stopped := make(chan struct{})
ticker := s.time.NewTicker(1 * time.Second)
if s.running {
return s.stopChan
}
s.running = true

ticker := s.time.NewTicker(1 * time.Second)
go func() {
for {
select {
case <-ticker.C:
s.RunPending()
case <-stopped:
case <-s.stopChan:
ticker.Stop()
s.running = false
return
}
}
}()

return stopped
return s.stopChan
}

// Jobs returns the list of Jobs from the Scheduler
Expand Down Expand Up @@ -249,14 +259,20 @@ func (s *Scheduler) Scheduled(j interface{}) bool {
return false
}

// Clear delete all scheduled Jobs
// Clear clear all Jobs from this scheduler
func (s *Scheduler) Clear() {
s.jobs = newEmptyJobSlice()
s.jobs = make([]*Job, 0)
}

// Stop stops the scheduler. This is a no-op if the scheduler is already stopped .
func (s *Scheduler) Stop() {
if s.running {
s.stopScheduler()
}
}

func newEmptyJobSlice() []*Job {
const initialCapacity = 256
return make([]*Job, 0, initialCapacity)
func (s *Scheduler) stopScheduler() {
s.stopChan <- struct{}{}
}

// Do specifies the jobFunc that should be called every time the Job runs
Expand Down
13 changes: 13 additions & 0 deletions scheduler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -518,5 +518,18 @@ func TestSetUnit(t *testing.T) {
assert.Equal(t, tc.timeUnit, j.unit)
})
}
}

func TestScheduler_Stop(t *testing.T) {
t.Run("stops a running scheduler", func(t *testing.T) {
sched := NewScheduler(time.UTC)
sched.StartAsync()
sched.Stop()
assert.False(t, sched.running)
})
t.Run("noop on stopped scheduler", func(t *testing.T) {
sched := NewScheduler(time.UTC)
sched.Stop()
assert.False(t, sched.running)
})
}
4 changes: 2 additions & 2 deletions timeHelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ package gocron

import "time"

type timeHelper interface {
type timeWrapper interface {
Now(*time.Location) time.Time
Unix(int64, int64) time.Time
Sleep(time.Duration)
Date(int, time.Month, int, int, int, int, int, *time.Location) time.Time
NewTicker(time.Duration) *time.Ticker
}

func newTimeHelper() timeHelper {
func newTimeWrapper() timeWrapper {
return &trueTime{}
}

Expand Down

0 comments on commit 4cc1bfb

Please sign in to comment.