mirror of https://github.com/go-co-op/gocron.git
update the functionality for singleton mode jobs
This commit is contained in:
parent
e94379147a
commit
1ee2481e48
|
|
@ -862,6 +862,31 @@ func ExampleWithIdentifier() {
|
|||
// 87b95dfc-3e71-11ef-9454-0242ac120002
|
||||
}
|
||||
|
||||
func ExampleWithIntervalFromCompletion() {
|
||||
s, _ := gocron.NewScheduler()
|
||||
defer func() { _ = s.Shutdown() }()
|
||||
|
||||
_, _ = s.NewJob(
|
||||
gocron.DurationJob(
|
||||
5*time.Minute,
|
||||
),
|
||||
gocron.NewTask(
|
||||
func() {
|
||||
time.Sleep(30 * time.Second)
|
||||
},
|
||||
),
|
||||
gocron.WithIntervalFromCompletion(),
|
||||
)
|
||||
|
||||
// Without WithIntervalFromCompletion (default behavior):
|
||||
// If the job starts at 00:00 and completes at 00:00:30,
|
||||
// the next job starts at 00:05:00 (only 4m30s rest).
|
||||
|
||||
// With WithIntervalFromCompletion:
|
||||
// If the job starts at 00:00 and completes at 00:00:30,
|
||||
// the next job starts at 00:05:30 (full 5m rest).
|
||||
}
|
||||
|
||||
func ExampleWithLimitConcurrentJobs() {
|
||||
_, _ = gocron.NewScheduler(
|
||||
gocron.WithLimitConcurrentJobs(
|
||||
|
|
@ -1016,31 +1041,6 @@ func ExampleWithSingletonMode() {
|
|||
)
|
||||
}
|
||||
|
||||
func ExampleWithIntervalFromCompletion() {
|
||||
s, _ := gocron.NewScheduler()
|
||||
defer func() { _ = s.Shutdown() }()
|
||||
|
||||
_, _ = s.NewJob(
|
||||
gocron.DurationJob(
|
||||
5*time.Minute,
|
||||
),
|
||||
gocron.NewTask(
|
||||
func() {
|
||||
time.Sleep(30 * time.Second)
|
||||
},
|
||||
),
|
||||
gocron.WithIntervalFromCompletion(),
|
||||
)
|
||||
|
||||
// Without WithIntervalFromCompletion (default behavior):
|
||||
// If the job starts at 00:00 and completes at 00:00:30,
|
||||
// the next job starts at 00:05:00 (only 4m30s rest).
|
||||
|
||||
// With WithIntervalFromCompletion:
|
||||
// If the job starts at 00:00 and completes at 00:00:30,
|
||||
// the next job starts at 00:05:30 (full 5m rest).
|
||||
}
|
||||
|
||||
func ExampleWithStartAt() {
|
||||
s, _ := gocron.NewScheduler()
|
||||
defer func() { _ = s.Shutdown() }()
|
||||
|
|
|
|||
15
executor.go
15
executor.go
|
|
@ -200,7 +200,10 @@ func (e *executor) start() {
|
|||
select {
|
||||
case runner.rescheduleLimiter <- struct{}{}:
|
||||
runner.in <- jIn
|
||||
e.sendOutForRescheduling(&jIn)
|
||||
// For intervalFromCompletion, skip rescheduling here - it will happen after job completes
|
||||
if !j.intervalFromCompletion {
|
||||
e.sendOutForRescheduling(&jIn)
|
||||
}
|
||||
default:
|
||||
// runner is busy, reschedule the work for later
|
||||
// which means we just skip it here and do nothing
|
||||
|
|
@ -210,7 +213,10 @@ func (e *executor) start() {
|
|||
} else {
|
||||
// wait mode, fill up that queue (buffered channel, so it's ok)
|
||||
runner.in <- jIn
|
||||
e.sendOutForRescheduling(&jIn)
|
||||
// For intervalFromCompletion, skip rescheduling here - it will happen after job completes
|
||||
if !j.intervalFromCompletion {
|
||||
e.sendOutForRescheduling(&jIn)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
select {
|
||||
|
|
@ -345,7 +351,10 @@ func (e *executor) singletonModeRunner(name string, in chan jobIn, wg *waitGroup
|
|||
// need to set shouldSendOut = false here, as there is a duplicative call to sendOutForRescheduling
|
||||
// inside the runJob function that needs to be skipped. sendOutForRescheduling is previously called
|
||||
// when the job is sent to the singleton mode runner.
|
||||
jIn.shouldSendOut = false
|
||||
// Exception: for intervalFromCompletion, we want rescheduling to happen AFTER job completion
|
||||
if !j.intervalFromCompletion {
|
||||
jIn.shouldSendOut = false
|
||||
}
|
||||
e.runJob(*j, jIn)
|
||||
}
|
||||
|
||||
|
|
|
|||
2
job.go
2
job.go
|
|
@ -701,7 +701,7 @@ func WithSingletonMode(mode LimitMode) JobOption {
|
|||
// Note: This option only makes sense with interval-based jobs (DurationJob, DurationRandomJob).
|
||||
// For time-based jobs (CronJob, DailyJob, etc.) that run at specific times, this option
|
||||
// will be ignored as those jobs are inherently scheduled at fixed times.
|
||||
//
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// s.NewJob(
|
||||
|
|
|
|||
|
|
@ -964,13 +964,18 @@ func TestWithIntervalFromCompletion_LongRunningJob(t *testing.T) {
|
|||
// Execution 1: 0s-6s, wait 3s → next at 9s
|
||||
// Execution 2: 9s-15s, wait 3s → next at 18s
|
||||
// Need to wait at least 16 seconds for 2 executions + buffer
|
||||
time.Sleep(20 * time.Second)
|
||||
time.Sleep(22 * time.Second)
|
||||
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
require.GreaterOrEqual(t, len(executions), 2, "Expected at least 2 executions")
|
||||
|
||||
if len(executions) < 2 {
|
||||
t.Logf("Only got %d execution(s), skipping gap assertion", len(executions))
|
||||
return
|
||||
}
|
||||
|
||||
prev := executions[0]
|
||||
curr := executions[1]
|
||||
|
||||
|
|
|
|||
|
|
@ -347,7 +347,7 @@ func (s *scheduler) selectExecJobsOutForRescheduling(id uuid.UUID) {
|
|||
}
|
||||
|
||||
var scheduleFrom time.Time
|
||||
|
||||
|
||||
// If intervalFromCompletion is enabled, calculate the next run time
|
||||
// from when the job completed (lastRun) rather than when it was scheduled.
|
||||
if j.intervalFromCompletion {
|
||||
|
|
|
|||
Loading…
Reference in New Issue