From 5f92630a6ca6a40c454619c1653df0f58a870fc1 Mon Sep 17 00:00:00 2001 From: Shunpoco Date: Tue, 5 May 2026 17:30:13 +0200 Subject: [PATCH 1/3] modify backoff --- internal/controller/bucket/helpers.go | 2 +- internal/controller/providerconfig/healthcheck/helpers.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/controller/bucket/helpers.go b/internal/controller/bucket/helpers.go index 64549d37..db22f83e 100644 --- a/internal/controller/bucket/helpers.go +++ b/internal/controller/bucket/helpers.go @@ -244,7 +244,7 @@ func (c *external) updateBucketCR(ctx context.Context, bucket *v1alpha1.Bucket, ctx, log := traces.InjectTraceAndLogger(ctx, c.log) for i, cb := range callbacks { - err := retry.OnError(retry.DefaultRetry, resource.IsAPIError, func() error { + err := retry.OnError(retry.DefaultBackoff, resource.IsAPIError, func() error { // If there are multiple callbacks, we can only use the cached kube client for // the first Get(). Subsequent Get() calls must use the kube reader which reads // directly from the API. This is necessary as we are doing Patch and Get calls diff --git a/internal/controller/providerconfig/healthcheck/helpers.go b/internal/controller/providerconfig/healthcheck/helpers.go index 31a449e7..f12c9f10 100644 --- a/internal/controller/providerconfig/healthcheck/helpers.go +++ b/internal/controller/providerconfig/healthcheck/helpers.go @@ -47,7 +47,7 @@ import ( func UpdateProviderConfigStatus(ctx context.Context, kubeClient client.Client, pc *apisv1alpha1.ProviderConfig, callback func(*apisv1alpha1.ProviderConfig, *apisv1alpha1.ProviderConfig)) error { const ( steps = 4 - factor = 0.5 + factor = 5.0 jitter = 0.1 ) From 3f1567385e3c59ed34df3d1e59358153de21d5ed Mon Sep 17 00:00:00 2001 From: Shunpoco Date: Tue, 5 May 2026 18:01:56 +0200 Subject: [PATCH 2/3] modify retry errors --- internal/controller/bucket/helpers.go | 12 +++++-- .../providerconfig/healthcheck/helpers.go | 34 ++++++++++++------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/internal/controller/bucket/helpers.go b/internal/controller/bucket/helpers.go index db22f83e..deb888d1 100644 --- a/internal/controller/bucket/helpers.go +++ b/internal/controller/bucket/helpers.go @@ -9,7 +9,6 @@ import ( xpv1 "github.com/crossplane/crossplane-runtime/v2/apis/common/v1" "github.com/crossplane/crossplane-runtime/v2/pkg/errors" "github.com/crossplane/crossplane-runtime/v2/pkg/meta" - "github.com/crossplane/crossplane-runtime/v2/pkg/resource" "github.com/linode/provider-ceph/apis/provider-ceph/v1alpha1" "github.com/linode/provider-ceph/internal/backendstore" "github.com/linode/provider-ceph/internal/consts" @@ -238,13 +237,22 @@ const ( // if err != nil { // // Handle error // } +// +//nolint:cyclop // cyclomatic complexity is accepted. func (c *external) updateBucketCR(ctx context.Context, bucket *v1alpha1.Bucket, callbacks ...func(*v1alpha1.Bucket) UpdateRequired) error { ctx, span := otel.Tracer("").Start(ctx, "bucket.external.updateBucketCR") defer span.End() ctx, log := traces.InjectTraceAndLogger(ctx, c.log) + shouldRetry := func(err error) bool { + return kerrors.IsConflict(err) || + kerrors.IsInternalError(err) || + kerrors.IsServerTimeout(err) || + kerrors.IsServiceUnavailable(err) + } + for i, cb := range callbacks { - err := retry.OnError(retry.DefaultBackoff, resource.IsAPIError, func() error { + err := retry.OnError(retry.DefaultBackoff, shouldRetry, func() error { // If there are multiple callbacks, we can only use the cached kube client for // the first Get(). Subsequent Get() calls must use the kube reader which reads // directly from the API. This is necessary as we are doing Patch and Get calls diff --git a/internal/controller/providerconfig/healthcheck/helpers.go b/internal/controller/providerconfig/healthcheck/helpers.go index f12c9f10..31b1fe56 100644 --- a/internal/controller/providerconfig/healthcheck/helpers.go +++ b/internal/controller/providerconfig/healthcheck/helpers.go @@ -6,7 +6,6 @@ import ( "time" "github.com/crossplane/crossplane-runtime/v2/pkg/errors" - "github.com/crossplane/crossplane-runtime/v2/pkg/resource" apisv1alpha1 "github.com/linode/provider-ceph/apis/v1alpha1" kerrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" @@ -54,19 +53,28 @@ func UpdateProviderConfigStatus(ctx context.Context, kubeClient client.Client, p nn := types.NamespacedName{Name: pc.GetName(), Namespace: pc.Namespace} pcDeepCopy := pc.DeepCopy() - err := retry.OnError(wait.Backoff{ - Steps: steps, - Duration: (time.Duration(pc.Spec.HealthCheckIntervalSeconds) * time.Second) - time.Second, - Factor: factor, - Jitter: jitter, - }, resource.IsAPIError, func() error { - if err := kubeClient.Get(ctx, nn, pc); err != nil { - return err - } - callback(pcDeepCopy, pc) + err := retry.OnError( + wait.Backoff{ + Steps: steps, + Duration: (time.Duration(pc.Spec.HealthCheckIntervalSeconds) * time.Second) - time.Second, + Factor: factor, + Jitter: jitter, + }, + func(err error) bool { + return kerrors.IsConflict(err) || + kerrors.IsInternalError(err) || + kerrors.IsServerTimeout(err) || + kerrors.IsServiceUnavailable(err) + }, + func() error { + if err := kubeClient.Get(ctx, nn, pc); err != nil { + return err + } + callback(pcDeepCopy, pc) - return kubeClient.Status().Update(ctx, pc) - }) + return kubeClient.Status().Update(ctx, pc) + }, + ) if err != nil { if kerrors.IsNotFound(err) { From 21f5f8220e9659c0a8d79f0bd358456f84acb6a6 Mon Sep 17 00:00:00 2001 From: Shunpoco Date: Tue, 5 May 2026 18:19:12 +0200 Subject: [PATCH 3/3] make generate-pkg --- .../providerconfig/healthcheck/helpers.go | 40 +++++++++---------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/internal/controller/providerconfig/healthcheck/helpers.go b/internal/controller/providerconfig/healthcheck/helpers.go index 31b1fe56..cfe70ead 100644 --- a/internal/controller/providerconfig/healthcheck/helpers.go +++ b/internal/controller/providerconfig/healthcheck/helpers.go @@ -53,28 +53,26 @@ func UpdateProviderConfigStatus(ctx context.Context, kubeClient client.Client, p nn := types.NamespacedName{Name: pc.GetName(), Namespace: pc.Namespace} pcDeepCopy := pc.DeepCopy() - err := retry.OnError( - wait.Backoff{ - Steps: steps, - Duration: (time.Duration(pc.Spec.HealthCheckIntervalSeconds) * time.Second) - time.Second, - Factor: factor, - Jitter: jitter, - }, - func(err error) bool { - return kerrors.IsConflict(err) || - kerrors.IsInternalError(err) || - kerrors.IsServerTimeout(err) || - kerrors.IsServiceUnavailable(err) - }, - func() error { - if err := kubeClient.Get(ctx, nn, pc); err != nil { - return err - } - callback(pcDeepCopy, pc) + shouldRetry := func(err error) bool { + return kerrors.IsConflict(err) || + kerrors.IsInternalError(err) || + kerrors.IsServerTimeout(err) || + kerrors.IsServiceUnavailable(err) + } - return kubeClient.Status().Update(ctx, pc) - }, - ) + err := retry.OnError(wait.Backoff{ + Steps: steps, + Duration: (time.Duration(pc.Spec.HealthCheckIntervalSeconds) * time.Second) - time.Second, + Factor: factor, + Jitter: jitter, + }, shouldRetry, func() error { + if err := kubeClient.Get(ctx, nn, pc); err != nil { + return err + } + callback(pcDeepCopy, pc) + + return kubeClient.Status().Update(ctx, pc) + }) if err != nil { if kerrors.IsNotFound(err) {