Skip to content

Commit

Permalink
adding Job.NextRuns to provide n next run times
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnRoesler committed May 6, 2024
1 parent d808cd9 commit e0f232e
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 2 deletions.
20 changes: 19 additions & 1 deletion example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,25 @@ func ExampleJob_nextRun() {
),
)

fmt.Println(j.NextRun())
nextRun, _ := j.NextRun()
fmt.Println(nextRun)
}

func ExampleJob_nextRuns() {
s, _ := NewScheduler()
defer func() { _ = s.Shutdown() }()

j, _ := s.NewJob(
DurationJob(
time.Second,
),
NewTask(
func() {},
),
)

nextRuns, _ := j.NextRuns(5)
fmt.Println(nextRuns)
}

func ExampleJob_runNow() {
Expand Down
29 changes: 29 additions & 0 deletions job.go
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,8 @@ type Job interface {
Name() string
// NextRun returns the time of the job's next scheduled run.
NextRun() (time.Time, error)
// NextRuns returns the requested number of calculated next run values.
NextRuns(int) ([]time.Time, error)
// RunNow runs the job once, now. This does not alter
// the existing run schedule, and will respect all job
// and scheduler limits. This means that running a job now may
Expand Down Expand Up @@ -921,6 +923,33 @@ func (j job) NextRun() (time.Time, error) {
return ij.nextScheduled[0], nil
}

func (j job) NextRuns(count int) ([]time.Time, error) {
ij := requestJob(j.id, j.jobOutRequest)
if ij == nil || ij.id == uuid.Nil {
return nil, ErrJobNotFound
}

lengthNextScheduled := len(ij.nextScheduled)
if lengthNextScheduled == 0 {
return nil, nil
} else if count <= lengthNextScheduled {
return ij.nextScheduled[:count], nil
}

out := make([]time.Time, count)
for i := 0; i < count; i++ {
if i < lengthNextScheduled {
out[i] = ij.nextScheduled[i]
continue
}

from := out[i-1]
out[i] = ij.next(from)
}

return out, nil
}

func (j job) Tags() []string {
return j.tags
}
Expand Down
76 changes: 75 additions & 1 deletion job_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,6 @@ func TestJob_NextRun(t *testing.T) {

s := newTestScheduler(t)

// run a job every 10 milliseconds that starts 10 milliseconds after the current time
j, err := s.NewJob(
DurationJob(
100*time.Millisecond,
Expand Down Expand Up @@ -548,3 +547,78 @@ func TestJob_NextRun(t *testing.T) {
})
}
}

func TestJob_NextRuns(t *testing.T) {
tests := []struct {
name string
jd JobDefinition
assertion func(t *testing.T, iteration int, previousRun, nextRun time.Time)
}{
{
"simple - milliseconds",
DurationJob(
100 * time.Millisecond,
),
func(t *testing.T, _ int, previousRun, nextRun time.Time) {
assert.Equal(t, previousRun.UnixMilli()+100, nextRun.UnixMilli())
},
},
{
"weekly",
WeeklyJob(
2,
NewWeekdays(time.Tuesday),
NewAtTimes(
NewAtTime(0, 0, 0),
),
),
func(t *testing.T, iteration int, previousRun, nextRun time.Time) {
diff := time.Hour * 14 * 24
if iteration == 1 {
// because the job is run immediately, the first run is on
// Saturday 1/1/2000. The following run is then on Tuesday 1/11/2000
diff = time.Hour * 10 * 24
}
assert.Equal(t, previousRun.Add(diff).Day(), nextRun.Day())
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
testTime := time.Date(2000, 1, 1, 0, 0, 0, 0, time.Local)
fakeClock := clockwork.NewFakeClockAt(testTime)

s := newTestScheduler(t,
WithClock(fakeClock),
)

j, err := s.NewJob(
tt.jd,
NewTask(
func() {},
),
WithStartAt(WithStartImmediately()),
)
require.NoError(t, err)

s.Start()
time.Sleep(10 * time.Millisecond)

nextRuns, err := j.NextRuns(5)
require.NoError(t, err)

assert.Len(t, nextRuns, 5)

for i := range nextRuns {
if i == 0 {
// skipping because there is no previous run
continue
}
tt.assertion(t, i, nextRuns[i-1], nextRuns[i])
}

assert.NoError(t, s.Shutdown())
})
}
}

0 comments on commit e0f232e

Please sign in to comment.