Modify mostRecentScheduleTime to return more detailed information about missed schedules
Initially this method was returning a number of missed schedules, but that turned out to be not reliable for some complex schedules. For example, those which are being run only during week days. The second approach was to only return a boolean indicating the too many missed information. It turns out that we need to return all three values: none missed, few missed and many missed, to let consumers know what to do, but don't leak the wrong number out of mostRecentScheduleTime.
This commit is contained in:
@@ -364,7 +364,7 @@ func TestMostRecentScheduleTime(t *testing.T) {
|
||||
now time.Time
|
||||
expectedEarliestTime time.Time
|
||||
expectedRecentTime *time.Time
|
||||
expectedTooManyMissed bool
|
||||
expectedTooManyMissed missedSchedulesType
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
@@ -405,9 +405,10 @@ func TestMostRecentScheduleTime(t *testing.T) {
|
||||
Schedule: "0 * * * *",
|
||||
},
|
||||
},
|
||||
now: *deltaTimeAfterTopOfTheHour(301 * time.Minute),
|
||||
expectedRecentTime: deltaTimeAfterTopOfTheHour(300 * time.Minute),
|
||||
expectedEarliestTime: *deltaTimeAfterTopOfTheHour(10 * time.Second),
|
||||
now: *deltaTimeAfterTopOfTheHour(301 * time.Minute),
|
||||
expectedRecentTime: deltaTimeAfterTopOfTheHour(300 * time.Minute),
|
||||
expectedEarliestTime: *deltaTimeAfterTopOfTheHour(10 * time.Second),
|
||||
expectedTooManyMissed: fewMissed,
|
||||
},
|
||||
{
|
||||
name: "complex schedule",
|
||||
@@ -422,9 +423,10 @@ func TestMostRecentScheduleTime(t *testing.T) {
|
||||
LastScheduleTime: &metav1HalfPastTheHour,
|
||||
},
|
||||
},
|
||||
now: *deltaTimeAfterTopOfTheHour(24*time.Hour + 31*time.Minute),
|
||||
expectedRecentTime: deltaTimeAfterTopOfTheHour(24*time.Hour + 30*time.Minute),
|
||||
expectedEarliestTime: *deltaTimeAfterTopOfTheHour(30 * time.Minute),
|
||||
now: *deltaTimeAfterTopOfTheHour(24*time.Hour + 31*time.Minute),
|
||||
expectedRecentTime: deltaTimeAfterTopOfTheHour(24*time.Hour + 30*time.Minute),
|
||||
expectedEarliestTime: *deltaTimeAfterTopOfTheHour(30 * time.Minute),
|
||||
expectedTooManyMissed: fewMissed,
|
||||
},
|
||||
{
|
||||
name: "another complex schedule",
|
||||
@@ -439,9 +441,10 @@ func TestMostRecentScheduleTime(t *testing.T) {
|
||||
LastScheduleTime: &metav1HalfPastTheHour,
|
||||
},
|
||||
},
|
||||
now: *deltaTimeAfterTopOfTheHour(30*time.Hour + 30*time.Minute),
|
||||
expectedRecentTime: nil,
|
||||
expectedEarliestTime: *deltaTimeAfterTopOfTheHour(30 * time.Minute),
|
||||
now: *deltaTimeAfterTopOfTheHour(30*time.Hour + 30*time.Minute),
|
||||
expectedRecentTime: nil,
|
||||
expectedEarliestTime: *deltaTimeAfterTopOfTheHour(30 * time.Minute),
|
||||
expectedTooManyMissed: fewMissed,
|
||||
},
|
||||
{
|
||||
name: "complex schedule with longer diff between executions",
|
||||
@@ -456,9 +459,10 @@ func TestMostRecentScheduleTime(t *testing.T) {
|
||||
LastScheduleTime: &metav1HalfPastTheHour,
|
||||
},
|
||||
},
|
||||
now: *deltaTimeAfterTopOfTheHour(96*time.Hour + 31*time.Minute),
|
||||
expectedRecentTime: deltaTimeAfterTopOfTheHour(96*time.Hour + 30*time.Minute),
|
||||
expectedEarliestTime: *deltaTimeAfterTopOfTheHour(30 * time.Minute),
|
||||
now: *deltaTimeAfterTopOfTheHour(96*time.Hour + 31*time.Minute),
|
||||
expectedRecentTime: deltaTimeAfterTopOfTheHour(96*time.Hour + 30*time.Minute),
|
||||
expectedEarliestTime: *deltaTimeAfterTopOfTheHour(30 * time.Minute),
|
||||
expectedTooManyMissed: fewMissed,
|
||||
},
|
||||
{
|
||||
name: "complex schedule with shorter diff between executions",
|
||||
@@ -470,9 +474,10 @@ func TestMostRecentScheduleTime(t *testing.T) {
|
||||
Schedule: "30 6-16/4 * * 1-5",
|
||||
},
|
||||
},
|
||||
now: *deltaTimeAfterTopOfTheHour(24*time.Hour + 31*time.Minute),
|
||||
expectedRecentTime: deltaTimeAfterTopOfTheHour(24*time.Hour + 30*time.Minute),
|
||||
expectedEarliestTime: *topOfTheHour(),
|
||||
now: *deltaTimeAfterTopOfTheHour(24*time.Hour + 31*time.Minute),
|
||||
expectedRecentTime: deltaTimeAfterTopOfTheHour(24*time.Hour + 30*time.Minute),
|
||||
expectedEarliestTime: *topOfTheHour(),
|
||||
expectedTooManyMissed: fewMissed,
|
||||
},
|
||||
{
|
||||
name: "@every schedule",
|
||||
@@ -491,7 +496,7 @@ func TestMostRecentScheduleTime(t *testing.T) {
|
||||
now: *deltaTimeAfterTopOfTheHour(7 * 24 * time.Hour),
|
||||
expectedRecentTime: deltaTimeAfterTopOfTheHour((6 * 24 * time.Hour) + 23*time.Hour + 1*time.Minute),
|
||||
expectedEarliestTime: *deltaTimeAfterTopOfTheHour(1 * time.Minute),
|
||||
expectedTooManyMissed: true,
|
||||
expectedTooManyMissed: manyMissed,
|
||||
},
|
||||
{
|
||||
name: "rogue cronjob",
|
||||
@@ -611,6 +616,63 @@ func TestMostRecentScheduleTime(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestNextScheduleTimeDuration(t *testing.T) {
|
||||
metav1TopOfTheHour := metav1.NewTime(*topOfTheHour())
|
||||
metav1HalfPastTheHour := metav1.NewTime(*deltaTimeAfterTopOfTheHour(30 * time.Minute))
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
cj *batchv1.CronJob
|
||||
now time.Time
|
||||
expectedDuration time.Duration
|
||||
}{
|
||||
{
|
||||
name: "complex schedule skipping weekend",
|
||||
cj: &batchv1.CronJob{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
CreationTimestamp: metav1TopOfTheHour,
|
||||
},
|
||||
Spec: batchv1.CronJobSpec{
|
||||
Schedule: "30 6-16/4 * * 1-5",
|
||||
},
|
||||
Status: batchv1.CronJobStatus{
|
||||
LastScheduleTime: &metav1HalfPastTheHour,
|
||||
},
|
||||
},
|
||||
now: *deltaTimeAfterTopOfTheHour(24*time.Hour + 31*time.Minute),
|
||||
expectedDuration: 3*time.Hour + 59*time.Minute + nextScheduleDelta,
|
||||
},
|
||||
{
|
||||
name: "another complex schedule skipping weekend",
|
||||
cj: &batchv1.CronJob{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
CreationTimestamp: metav1TopOfTheHour,
|
||||
},
|
||||
Spec: batchv1.CronJobSpec{
|
||||
Schedule: "30 10,11,12 * * 1-5",
|
||||
},
|
||||
Status: batchv1.CronJobStatus{
|
||||
LastScheduleTime: &metav1HalfPastTheHour,
|
||||
},
|
||||
},
|
||||
now: *deltaTimeAfterTopOfTheHour(30*time.Hour + 30*time.Minute),
|
||||
expectedDuration: 66*time.Hour + nextScheduleDelta,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
sched, err := cron.ParseStandard(tt.cj.Spec.Schedule)
|
||||
if err != nil {
|
||||
t.Errorf("error setting up the test, %s", err)
|
||||
}
|
||||
gotScheduleTimeDuration := nextScheduleTimeDuration(tt.cj, tt.now, sched)
|
||||
if !reflect.DeepEqual(gotScheduleTimeDuration, &tt.expectedDuration) {
|
||||
t.Errorf("scheduleTimeDuration - got %s, want %s", gotScheduleTimeDuration, tt.expectedDuration)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func topOfTheHour() *time.Time {
|
||||
T1, err := time.Parse(time.RFC3339, "2016-05-19T10:00:00Z")
|
||||
if err != nil {
|
||||
|
Reference in New Issue
Block a user