Repository: zeromicro/go-zero
Pull request #3808 (2023-12-22 08:57:00)

feat: retry ignore specified errors

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/zeromicro/go-zero/pull/3808?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=zeromicro) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 94.55%. Comparing base [(`8e97c58`)](https://app.codecov.io/gh/zeromicro/go-zero/commit/8e97c5819fa3768ac81e64b6c21277d9b4ff8439?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=zeromicro) to head [(`81f0039`)](https://app.codecov.io/gh/zeromicro/go-zero/pull/3808?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=zeromicro).

<details><summary>Additional details and impacted files</summary>



| [Files](https://app.codecov.io/gh/zeromicro/go-zero/pull/3808?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=zeromicro) | Coverage Δ | |
|---|---|---|
| [core/fx/retry.go](https://app.codecov.io/gh/zeromicro/go-zero/pull/3808?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=zeromicro#diff-Y29yZS9meC9yZXRyeS5nbw==) | `100.00% <100.00%> (ø)` | |

... and [1 file with indirect coverage changes](https://app.codecov.io/gh/zeromicro/go-zero/pull/3808/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=zeromicro)

</details>

Patch:
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,


Test patch:
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 {