diff --git a/example_test.go b/example_test.go index e7b8cd06..229c64d1 100644 --- a/example_test.go +++ b/example_test.go @@ -84,6 +84,14 @@ func ExampleJob_NextRun() { s.StartAsync() } +func ExampleJob_PreviousRun() { + s := gocron.NewScheduler(time.UTC) + job, _ := s.Every(1).Second().Do(task) + s.StartAsync() + + fmt.Println("Previous run:", job.PreviousRun()) +} + func ExampleJob_RunCount() { s := gocron.NewScheduler(time.UTC) job, _ := s.Every(1).Second().Do(task) diff --git a/job.go b/job.go index 87918fa6..fdada82e 100644 --- a/job.go +++ b/job.go @@ -24,6 +24,7 @@ type Job struct { atTimes []time.Duration // optional time(s) at which this Job runs when interval is day startAtTime time.Time // optional time at which the Job starts error error // error related to Job + previousRun time.Time // datetime of the run before last run lastRun time.Time // datetime of last run nextRun time.Time // datetime of next run scheduledWeekdays []time.Weekday // Specific days of the week to start on @@ -435,6 +436,7 @@ func (j *Job) LastRun() time.Time { } func (j *Job) setLastRun(t time.Time) { + j.previousRun = j.lastRun j.lastRun = t } @@ -452,6 +454,13 @@ func (j *Job) setNextRun(t time.Time) { j.jobFunction.jobFuncNextRun = t } +// PreviousRun returns the job run time previous to LastRun +func (j *Job) PreviousRun() time.Time { + j.mu.RLock() + defer j.mu.RUnlock() + return j.previousRun +} + // RunCount returns the number of times the job has been started func (j *Job) RunCount() int { j.mu.Lock() @@ -498,6 +507,7 @@ func (j *Job) copy() Job { error: j.error, lastRun: j.lastRun, nextRun: j.nextRun, + previousRun: j.previousRun, scheduledWeekdays: j.scheduledWeekdays, daysOfTheMonth: j.daysOfTheMonth, tags: j.tags, diff --git a/job_test.go b/job_test.go index 5afacbbe..6483a85b 100644 --- a/job_test.go +++ b/job_test.go @@ -285,3 +285,40 @@ func TestJob_Stop(t *testing.T) { assert.True(t, errors.Is(jobCtx.Err(), context.Canceled)) }) } + +func TestJob_PreviousRun(t *testing.T) { + t.Run("at time", func(t *testing.T) { + s := NewScheduler(time.UTC) + atTime := time.Now().UTC().Add(time.Millisecond * 150) + _, err := s.Every(1).Day().At(atTime).DoWithJobDetails(func(job Job) { + assert.Zero(t, job.PreviousRun()) + assert.Equal(t, atTime.Truncate(time.Second), job.LastRun()) + }) + require.NoError(t, err) + s.StartAsync() + time.Sleep(500 * time.Millisecond) + s.Stop() + }) + + t.Run("duration", func(t *testing.T) { + s := NewScheduler(time.UTC) + var counter int + var lastRunTime time.Time + var mu sync.Mutex + _, err := s.Every("250ms").DoWithJobDetails(func(job Job) { + mu.Lock() + defer mu.Unlock() + if counter == 0 { + assert.Zero(t, job.PreviousRun()) + lastRunTime = job.LastRun() + } else { + assert.Equalf(t, lastRunTime, job.PreviousRun(), "last lastRun and previous") + } + counter++ + }) + require.NoError(t, err) + s.StartAsync() + time.Sleep(450 * time.Millisecond) + s.Stop() + }) +} diff --git a/scheduler.go b/scheduler.go index 583951e8..50fa7d10 100644 --- a/scheduler.go +++ b/scheduler.go @@ -600,6 +600,9 @@ func (s *Scheduler) runContinuous(job *Job) { if !job.getStartsImmediately() { job.setStartsImmediately(true) } else { + //if job.neverRan() { + // job.setLastRun(s.now()) + //} s.run(job) } nr := next.dateTime.Sub(s.now())