From 25af456786dac61a2d2b4c103206918c844044be Mon Sep 17 00:00:00 2001 From: Renato Torres Date: Tue, 19 Mar 2024 09:10:32 +0000 Subject: [PATCH] feat: longer poll interval if resource is ready --- pkg/reconciler/managed/reconciler.go | 9 +- pkg/reconciler/managed/reconciler_test.go | 103 ++++++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/pkg/reconciler/managed/reconciler.go b/pkg/reconciler/managed/reconciler.go index e0325eae7..90dd46bf4 100644 --- a/pkg/reconciler/managed/reconciler.go +++ b/pkg/reconciler/managed/reconciler.go @@ -22,6 +22,7 @@ import ( "strings" "time" + v1 "k8s.io/api/core/v1" kerrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/sets" @@ -549,7 +550,13 @@ func WithPollInterval(after time.Duration) ReconcilerOption { // interval. type PollIntervalHook func(managed resource.Managed, pollInterval time.Duration) time.Duration -func defaultPollIntervalHook(_ resource.Managed, pollInterval time.Duration) time.Duration { +func defaultPollIntervalHook(managed resource.Managed, pollInterval time.Duration) time.Duration { + if managed != nil && + managed.GetCondition(xpv1.TypeSynced).Status == v1.ConditionTrue && + managed.GetCondition(xpv1.TypeReady).Status == v1.ConditionTrue { + jitter := 30 * time.Minute + return time.Hour + time.Duration((rand.Float64()-0.5)*2*float64(jitter)).Round(time.Second) + } return pollInterval } diff --git a/pkg/reconciler/managed/reconciler_test.go b/pkg/reconciler/managed/reconciler_test.go index 60973e931..6b1e77a37 100644 --- a/pkg/reconciler/managed/reconciler_test.go +++ b/pkg/reconciler/managed/reconciler_test.go @@ -24,6 +24,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" + v1 "k8s.io/api/core/v1" kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -2240,3 +2241,105 @@ func TestShouldDelete(t *testing.T) { }) } } + +func TestDefaultPollIntervalHook(t *testing.T) { + type args struct { + duration time.Duration + managed resource.Managed + } + type want struct { + expected time.Duration + margin time.Duration + } + cases := map[string]struct { + reason string + args args + want want + }{ + "ResourceIsNil": { + reason: "Should return the default poll interval if the managed resource is nil.", + args: args{ + duration: defaultPollInterval, + managed: nil, + }, + want: want{expected: defaultPollInterval, margin: 0}, + }, + "ResourceNotReady": { + reason: "Should return the default poll interval if the managed resource is not ready.", + args: args{ + duration: defaultPollInterval, + managed: &fake.Managed{ + ConditionedStatus: xpv1.ConditionedStatus{ + Conditions: []xpv1.Condition{ + { + Type: xpv1.TypeReady, + Status: v1.ConditionFalse, + }, + { + Type: xpv1.TypeSynced, + Status: v1.ConditionTrue, + }, + }, + }, + }, + }, + want: want{expected: defaultPollInterval, margin: 0}, + }, + "ResourceNotSynced": { + reason: "Should return the default poll interval if the managed resource is not synced.", + args: args{ + duration: defaultPollInterval, + managed: &fake.Managed{ + ConditionedStatus: xpv1.ConditionedStatus{ + Conditions: []xpv1.Condition{ + { + Type: xpv1.TypeReady, + Status: v1.ConditionTrue, + }, + { + Type: xpv1.TypeSynced, + Status: v1.ConditionFalse, + }, + }, + }, + }, + }, + want: want{expected: defaultPollInterval, margin: 0}, + }, + "ResourceReady": { + reason: "Should return the provided duration if the managed resource is ready.", + args: args{ + duration: 1 * time.Minute, + managed: &fake.Managed{ + ConditionedStatus: xpv1.ConditionedStatus{ + Conditions: []xpv1.Condition{ + { + Type: xpv1.TypeReady, + Status: v1.ConditionTrue, + }, + { + Type: xpv1.TypeSynced, + Status: v1.ConditionTrue, + }, + }, + }, + }, + }, + want: want{expected: 1 * time.Hour, margin: 30 * time.Minute}, + }, + } + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + r := defaultPollIntervalHook(tc.args.managed, tc.args.duration) + if tc.want.margin == 0 { + if diff := cmp.Diff(tc.want.expected, r); diff != "" { + t.Errorf("\nReason: %s\ndefaultPollIntervalHook(...): -want, +got:\n%s", tc.reason, diff) + } + } else { + if r < tc.want.expected-tc.want.margin || r > tc.want.expected+tc.want.margin { + t.Errorf("defaultPollIntervalHook(...): expected %v, got %v", tc.want.expected, r) + } + } + }) + } +}