From e38036cea2e0ee6c3fe8c2709e5a4065bb2a7c9f Mon Sep 17 00:00:00 2001 From: fearlessfei <573088370@qq.com> Date: Sat, 2 Mar 2024 18:53:20 +0800 Subject: [PATCH] feat: retry ignore specified errors (#3808) --- core/fx/retry.go | 20 +++++++++++++++++--- core/fx/retry_test.go | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/core/fx/retry.go b/core/fx/retry.go index e79c9002..1aa002a2 100644 --- a/core/fx/retry.go +++ b/core/fx/retry.go @@ -2,6 +2,7 @@ package fx import ( "context" + "errors" "time" "github.com/zeromicro/go-zero/core/errorx" @@ -14,9 +15,10 @@ type ( RetryOption func(*retryOptions) retryOptions struct { - times int - interval time.Duration - timeout time.Duration + times int + interval time.Duration + timeout time.Duration + IgnoreErrors []error } ) @@ -62,6 +64,11 @@ func retry(ctx context.Context, fn func(errChan chan error, retryCount int), opt select { case err := <-errChan: if err != nil { + for _, ignoreErr := range options.IgnoreErrors { + if errors.Is(err, ignoreErr) { + return nil + } + } berr.Add(err) } else { return nil @@ -103,6 +110,13 @@ func WithTimeout(timeout time.Duration) RetryOption { } } +// WithIgnoreErrors Ignore the specified errors +func WithIgnoreErrors(IgnoreErrors []error) RetryOption { + return func(options *retryOptions) { + options.IgnoreErrors = IgnoreErrors + } +} + func newRetryOptions() *retryOptions { return &retryOptions{ times: defaultRetryTimes, diff --git a/core/fx/retry_test.go b/core/fx/retry_test.go index 045d782a..5a8d06b6 100644 --- a/core/fx/retry_test.go +++ b/core/fx/retry_test.go @@ -97,6 +97,24 @@ func TestRetryWithInterval(t *testing.T) { } +func TestRetryWithWithIgnoreErrors(t *testing.T) { + ignoreErr1 := errors.New("ignore error1") + ignoreErr2 := errors.New("ignore error2") + ignoreErrs := []error{ignoreErr1, ignoreErr2} + + assert.Nil(t, DoWithRetry(func() error { + return ignoreErr1 + }, WithIgnoreErrors(ignoreErrs))) + + assert.Nil(t, DoWithRetry(func() error { + return ignoreErr2 + }, WithIgnoreErrors(ignoreErrs))) + + assert.NotNil(t, DoWithRetry(func() error { + return errors.New("any") + })) +} + func TestRetryCtx(t *testing.T) { t.Run("with timeout", func(t *testing.T) { assert.NotNil(t, DoWithRetryCtx(context.Background(), func(ctx context.Context, retryCount int) error {