Skip to content

Commit

Permalink
a bunch of things (#137)
Browse files Browse the repository at this point in the history
* a bunch of things

* fixing linter

* fixing linter

* only test latest go version

Co-authored-by: streppel <streppels@gmail.com>
  • Loading branch information
JohnRoesler and Streppel committed Mar 8, 2021
1 parent b70ec13 commit d401c08
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 103 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/go_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ jobs:
strategy:
matrix:
go-version:
- 1.14
- 1.15
- 1.16
name: lint and test
runs-on: ubuntu-latest
Expand Down
25 changes: 2 additions & 23 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ var task = func() {}
// ----------------------JOB-FUNCTIONS----------------------------------
// ---------------------------------------------------------------------

func ExampleJob_Err() {
func ExampleJob_Error() {
s := gocron.NewScheduler(time.UTC)
s.Every(1).Day().At("bad time")
j := s.Jobs()[0]
fmt.Println(j.Err())
fmt.Println(j.Error())
// Output:
// the given time format is not supported
}
Expand Down Expand Up @@ -49,14 +49,6 @@ func ExampleJob_NextRun() {
s.StartAsync()
}

func ExampleJob_RemoveAfterLastRun() {
s := gocron.NewScheduler(time.UTC)
job, _ := s.Every(1).Second().Do(task)
job.LimitRunsTo(1)
job.RemoveAfterLastRun()
s.StartAsync()
}

func ExampleJob_RunCount() {
s := gocron.NewScheduler(time.UTC)
job, _ := s.Every(1).Second().Do(task)
Expand Down Expand Up @@ -361,19 +353,6 @@ func ExampleScheduler_Remove() {
// 0
}

func ExampleScheduler_RemoveAfterLastRun() {
s := gocron.NewScheduler(time.UTC)

j, _ := s.Every(1).Second().LimitRunsTo(1).RemoveAfterLastRun().Do(task)
s.StartAsync()
s.Stop()
fmt.Println(j.RunCount())
fmt.Println(s.Len())
// Output:
// 1
// 0
}

func ExampleScheduler_RemoveByReference() {
s := gocron.NewScheduler(time.UTC)

Expand Down
10 changes: 6 additions & 4 deletions gocron.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ var (
ErrInvalidInterval = errors.New(".Every() interval must be greater than 0")
ErrInvalidIntervalType = errors.New(".Every() interval must be int, time.Duration, or string")
ErrInvalidIntervalUnitsSelection = errors.New("an .Every() duration interval cannot be used with units (e.g. .Seconds())")
ErrAtTimeNotSupported = errors.New("the At() not supported for time unit")
ErrWeekdayNotSupported = errors.New("weekday is not supported for time unit")
ErrTagsUnique = func(tag string) error { return fmt.Errorf("a non-unique tag was set on the job: %s", tag) }

ErrAtTimeNotSupported = errors.New("the At() method is not supported for this time unit")
ErrWeekdayNotSupported = errors.New("weekday is not supported for time unit")
ErrTagsUnique = func(tag string) error { return fmt.Errorf("a non-unique tag was set on the job: %s", tag) }
)

func wrapOrError(toWrap error, err error) error {
Expand All @@ -49,7 +50,8 @@ type timeUnit int

const (
// default unit is seconds
seconds timeUnit = iota
milliseconds timeUnit = iota
seconds
minutes
hours
days
Expand Down
28 changes: 10 additions & 18 deletions job.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type Job struct {
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
err error // error related to Job
error error // error related to Job
lastRun time.Time // datetime of last run
nextRun time.Time // datetime of next run
scheduledWeekday *time.Weekday // Specific day of the week to start on
Expand All @@ -40,10 +40,9 @@ type jobFunction struct {
}

type runConfig struct {
finiteRuns bool
maxRuns int
mode mode
removeAfterLastRun bool
finiteRuns bool
maxRuns int
mode mode
}

// mode is the Job's running mode
Expand All @@ -62,6 +61,7 @@ func NewJob(interval int) *Job {
ctx, cancel := context.WithCancel(context.Background())
return &Job{
interval: interval,
unit: seconds,
lastRun: time.Time{},
nextRun: time.Time{},
jobFunction: jobFunction{
Expand Down Expand Up @@ -109,9 +109,11 @@ func (j *Job) setStartAtTime(t time.Time) {
j.startAtTime = t
}

// Err returns an error if one occurred while creating the Job
func (j *Job) Err() error {
return j.err
// Error returns an error if one occurred while creating the Job.
// If multiple errors occurred, they will be wrapped and can be
// checked using the standard unwrap options.
func (j *Job) Error() error {
return j.error
}

// Tag allows you to add arbitrary labels to a Job that do not
Expand Down Expand Up @@ -184,16 +186,6 @@ func (j *Job) SingletonMode() {

}

// RemoveAfterLastRun sets the job to be removed after it's last run (when limited)
func (j *Job) RemoveAfterLastRun() *Job {
j.runConfig.removeAfterLastRun = true
return j
}

func (j *Job) getRemoveAfterLastRun() bool {
return j.runConfig.removeAfterLastRun
}

// shouldRun evaluates if this job should run again
// based on the runConfig
func (j *Job) shouldRun() bool {
Expand Down
71 changes: 42 additions & 29 deletions scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,7 @@ func (s *Scheduler) scheduleNextRun(job *Job) {
}

if !job.shouldRun() {
if job.getRemoveAfterLastRun() {
s.RemoveByReference(job)
}
s.RemoveByReference(job)
return
}

Expand All @@ -182,7 +180,7 @@ func (s *Scheduler) durationToNextRun(lastRun time.Time, job *Job) time.Duration

var d time.Duration
switch job.unit {
case seconds, minutes, hours:
case milliseconds, seconds, minutes, hours:
d = s.calculateDuration(job)
case days:
d = s.calculateDays(job, lastRun)
Expand Down Expand Up @@ -282,6 +280,8 @@ func (s *Scheduler) calculateDuration(job *Job) time.Duration {

interval := job.interval
switch job.unit {
case milliseconds:
return time.Duration(interval) * time.Millisecond
case seconds:
return time.Duration(interval) * time.Second
case minutes:
Expand Down Expand Up @@ -328,7 +328,7 @@ func (s *Scheduler) Every(interval interface{}) *Scheduler {
case int:
job := NewJob(interval)
if interval <= 0 {
job.err = wrapOrError(job.err, ErrInvalidInterval)
job.error = wrapOrError(job.error, ErrInvalidInterval)
}
s.setJobs(append(s.Jobs(), job))
case time.Duration:
Expand All @@ -340,14 +340,14 @@ func (s *Scheduler) Every(interval interface{}) *Scheduler {
job := NewJob(0)
d, err := time.ParseDuration(interval)
if err != nil {
job.err = wrapOrError(job.err, err)
job.error = wrapOrError(job.error, err)
}
job.duration = d
job.unit = duration
s.setJobs(append(s.Jobs(), job))
default:
job := NewJob(0)
job.err = wrapOrError(job.err, ErrInvalidIntervalType)
job.error = wrapOrError(job.error, ErrInvalidIntervalType)
s.setJobs(append(s.Jobs(), job))
}
return s
Expand Down Expand Up @@ -444,8 +444,8 @@ func removeAtIndex(jobs []*Job, i int) []*Job {
return jobs
}

// LimitRunsTo limits the number of executions of this job to n. However,
// the job will still remain in the scheduler
// LimitRunsTo limits the number of executions of this job to n.
// Upon reaching the limit, the job is removed from the scheduler.
func (s *Scheduler) LimitRunsTo(i int) *Scheduler {
job := s.getCurrentJob()
job.LimitRunsTo(i)
Expand All @@ -460,13 +460,6 @@ func (s *Scheduler) SingletonMode() *Scheduler {
return s
}

// RemoveAfterLastRun sets the job to be removed after it's last run (when limited)
func (s *Scheduler) RemoveAfterLastRun() *Scheduler {
job := s.getCurrentJob()
job.RemoveAfterLastRun()
return s
}

// TaskPresent checks if specific job's function was added to the scheduler.
func (s *Scheduler) TaskPresent(j interface{}) bool {
s.jobsMutex.RLock()
Expand Down Expand Up @@ -515,18 +508,18 @@ func (s *Scheduler) Do(jobFun interface{}, params ...interface{}) (*Job, error)
job := s.getCurrentJob()

if job.atTime != 0 && job.unit <= hours {
job.err = wrapOrError(job.err, ErrAtTimeNotSupported)
job.error = wrapOrError(job.error, ErrAtTimeNotSupported)
}

if job.scheduledWeekday != nil && job.unit != weeks {
job.err = wrapOrError(job.err, ErrWeekdayNotSupported)
job.error = wrapOrError(job.error, ErrWeekdayNotSupported)
}

if job.err != nil {
if job.error != nil {
// delete the job from the scheduler as this job
// cannot be executed
s.RemoveByReference(job)
return nil, job.err
return nil, job.error
}

typ := reflect.TypeOf(jobFun)
Expand All @@ -550,15 +543,24 @@ func (s *Scheduler) Do(jobFun interface{}, params ...interface{}) (*Job, error)
}

// At schedules the Job at a specific time of day in the form "HH:MM:SS" or "HH:MM"
func (s *Scheduler) At(t string) *Scheduler {
// or time.Time (note that only the hours, minutes, seconds and nanos are used).
func (s *Scheduler) At(i interface{}) *Scheduler {
job := s.getCurrentJob()
hour, min, sec, err := parseTime(t)
if err != nil {
job.err = wrapOrError(job.err, err)
return s

switch t := i.(type) {
case string:
hour, min, sec, err := parseTime(t)
if err != nil {
job.error = wrapOrError(job.error, err)
return s
}
// save atTime start as duration from midnight
job.setAtTime(time.Duration(hour)*time.Hour + time.Duration(min)*time.Minute + time.Duration(sec)*time.Second)
case time.Time:
job.setAtTime(time.Duration(t.Hour())*time.Hour + time.Duration(t.Minute())*time.Minute + time.Duration(t.Second())*time.Second + time.Duration(t.Nanosecond())*time.Nanosecond)
default:
job.error = wrapOrError(job.error, ErrUnsupportedTimeFormat)
}
// save atTime start as duration from midnight
job.setAtTime(time.Duration(hour)*time.Hour + time.Duration(min)*time.Minute + time.Duration(sec)*time.Second)
job.startsImmediately = false
return s
}
Expand All @@ -570,7 +572,7 @@ func (s *Scheduler) Tag(t ...string) *Scheduler {
if s.tags != nil {
for _, tag := range t {
if _, ok := s.tags[tag]; ok {
job.err = wrapOrError(job.err, ErrTagsUnique(tag))
job.error = wrapOrError(job.error, ErrTagsUnique(tag))
return s
}
s.tags[tag] = struct{}{}
Expand All @@ -594,11 +596,22 @@ func (s *Scheduler) StartAt(t time.Time) *Scheduler {
func (s *Scheduler) setUnit(unit timeUnit) {
job := s.getCurrentJob()
if job.unit == duration {
job.err = wrapOrError(job.err, ErrInvalidIntervalUnitsSelection)
job.error = wrapOrError(job.error, ErrInvalidIntervalUnitsSelection)
}
job.unit = unit
}

// Second sets the unit with seconds
func (s *Scheduler) Millisecond() *Scheduler {
return s.Milliseconds()
}

// Seconds sets the unit with seconds
func (s *Scheduler) Milliseconds() *Scheduler {
s.setUnit(milliseconds)
return s
}

// Second sets the unit with seconds
func (s *Scheduler) Second() *Scheduler {
return s.Seconds()
Expand Down
27 changes: 0 additions & 27 deletions scheduler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,6 @@ func TestRunJobsWithLimit(t *testing.T) {
})
require.NoError(t, err)
j.LimitRunsTo(1)
j.RemoveAfterLastRun()

s.StartAsync()
time.Sleep(2 * time.Second)
Expand Down Expand Up @@ -1033,32 +1032,6 @@ func TestScheduler_SetMaxConcurrentJobs(t *testing.T) {
}
}

func TestScheduler_RemoveAfterLastRun(t *testing.T) {
t.Run("job removed after the last run", func(t *testing.T) {
semaphore := make(chan bool)

s := NewScheduler(time.UTC)

_, err := s.Every(1).Second().LimitRunsTo(1).RemoveAfterLastRun().Do(func() {
semaphore <- true
})
require.NoError(t, err)

s.StartAsync()
time.Sleep(2 * time.Second)

var counter int
select {
case <-time.After(2 * time.Second):
assert.Equal(t, 1, counter)
assert.Zero(t, s.Len())
case <-semaphore:
counter++
require.LessOrEqual(t, counter, 1)
}
})
}

func TestScheduler_TagsUnique(t *testing.T) {
const (
foo = "foo"
Expand Down

0 comments on commit d401c08

Please sign in to comment.