From 3c688e44a8960052d93334f23c4b0ae0c98065ca Mon Sep 17 00:00:00 2001 From: jxskiss Date: Thu, 10 Oct 2024 16:39:49 +0800 Subject: [PATCH] [retry] support pointer Stop error Change-Id: Ie2013aac9ea6950ff47642c6ee54345cf22f3adf --- utils/retry/retry.go | 9 ++++++++- utils/retry/retry_test.go | 42 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/utils/retry/retry.go b/utils/retry/retry.go index 9e77edd8..0a5fb6cc 100644 --- a/utils/retry/retry.go +++ b/utils/retry/retry.go @@ -83,6 +83,9 @@ func retry(opt options, f func() error, opts ...Option) (r Result) { if _, ok := err.(Stop); ok { break } + if s, ok := err.(*Stop); ok && s != nil { + break + } // attempts <= 0 means retry forever. if opt.Attempts > 0 && r.Attempts >= opt.Attempts { break @@ -119,10 +122,14 @@ func retry(opt options, f func() error, opts ...Option) (r Result) { if err != nil { if s, ok := err.(Stop); ok { // Return the original error for later checking. + // Stop error from caller don't count for circuit breaker. merr.Append(s.Err) opt.Hook(r.Attempts, s.Err) - + } else if s, ok := err.(*Stop); ok && s != nil { + // Return the original error for later checking. // Stop error from caller don't count for circuit breaker. + merr.Append(s.Err) + opt.Hook(r.Attempts, s.Err) } else { merr.Append(err) opt.Hook(r.Attempts, err) diff --git a/utils/retry/retry_test.go b/utils/retry/retry_test.go index 693149db..2fa432c0 100644 --- a/utils/retry/retry_test.go +++ b/utils/retry/retry_test.go @@ -46,6 +46,48 @@ func Test_Retry(t *testing.T) { is.Equal(merrors[2].Error(), "error 1") } +func Test_Stop(t *testing.T) { + is := assert.New(t) + + t.Run("struct Stop", func(t *testing.T) { + fakeErrFunc := fakeErrors(1) + r := Retry(3, 100*time.Millisecond, func() error { + err := fakeErrFunc() + if err != nil { + return err + } + return Stop{Err: fmt.Errorf("stop")} + }) + is.True(!r.Ok) + is.Equal(r.Attempts, 2) + merr, ok := r.Error.(*SizedError) + is.True(ok) + merrors := merr.Errors() + is.Equal(len(merrors), 2) + is.Equal(merrors[0].Error(), "stop") + is.Equal(merrors[1].Error(), "error 1") + }) + + t.Run("pointer of struct Stop", func(t *testing.T) { + fakeErrFunc := fakeErrors(1) + r := Retry(3, 100*time.Millisecond, func() error { + err := fakeErrFunc() + if err != nil { + return err + } + return &Stop{Err: fmt.Errorf("stop")} + }) + is.True(!r.Ok) + is.Equal(r.Attempts, 2) + merr, ok := r.Error.(*SizedError) + is.True(ok) + merrors := merr.Errors() + is.Equal(len(merrors), 2) + is.Equal(merrors[0].Error(), "stop") + is.Equal(merrors[1].Error(), "error 1") + }) +} + func Test_Hook(t *testing.T) { is := assert.New(t) target := fakeErrors(3)