Skip to content

Commit

Permalink
Merge ad75acf into 382faa4
Browse files Browse the repository at this point in the history
  • Loading branch information
ptrus committed Oct 7, 2020
2 parents 382faa4 + ad75acf commit 7411c02
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 23 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
language: go
go:
- 1.12
- 1.13
- 1.x
- tip
before_install:
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/cenkalti/backoff/v4

go 1.12
go 1.13
13 changes: 11 additions & 2 deletions retry.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package backoff

import "time"
import (
"errors"
"time"
)

// An Operation is executing by Retry() or RetryNotify().
// The operation will be retried using a backoff policy if it returns an error.
Expand Down Expand Up @@ -53,7 +56,8 @@ func RetryNotifyWithTimer(operation Operation, b BackOff, notify Notify, t Timer
return nil
}

if permanent, ok := err.(*PermanentError); ok {
var permanent *PermanentError
if errors.As(err, &permanent) {
return permanent.Err
}

Expand Down Expand Up @@ -88,6 +92,11 @@ func (e *PermanentError) Unwrap() error {
return e.Err
}

func (e *PermanentError) Is(target error) bool {
_, ok := target.(*PermanentError)
return ok
}

// Permanent wraps the given err in a *PermanentError.
func Permanent(err error) error {
if err == nil {
Expand Down
92 changes: 73 additions & 19 deletions retry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"io"
"log"
"testing"
"time"
Expand Down Expand Up @@ -89,41 +90,94 @@ func TestRetryContext(t *testing.T) {
}

func TestRetryPermanent(t *testing.T) {
const permanentOn = 3
var i = 0

// This function fails permanently after permanentOn tries
f := func() error {
i++
log.Printf("function is called %d. time\n", i)

if i == permanentOn {
log.Println("permanent error")
return Permanent(errors.New("permanent error"))
ensureRetries := func(test string, shouldRetry bool, f func() error) {
numRetries := -1
maxRetries := 1

_ = RetryNotifyWithTimer(
func() error {
numRetries++
if numRetries >= maxRetries {
return Permanent(errors.New("forced"))
}
return f()
},
NewExponentialBackOff(),
nil,
&testTimer{},
)

if shouldRetry && numRetries == 0 {
t.Errorf("Test: '%s', backoff should have retried", test)
}

log.Println("error")
return errors.New("error")
if !shouldRetry && numRetries > 0 {
t.Errorf("Test: '%s', backoff should not have retried", test)
}
}

err := RetryNotifyWithTimer(f, NewExponentialBackOff(), nil, &testTimer{})
if err == nil || err.Error() != "permanent error" {
t.Errorf("unexpected error: %s", err)
}
if i != permanentOn {
t.Errorf("invalid number of retries: %d", i)
for _, testCase := range []struct {
name string
f func() error
shouldRetry bool
}{
{
"nil test",
func() error {
return nil
},
false,
},
{
"io.EOF",
func() error {
return io.EOF
},
true,
},
{
"Permanent(io.EOF)",
func() error {
return Permanent(io.EOF)
},
false,
},
{
"Wrapped: Permanent(io.EOF)",
func() error {
return fmt.Errorf("Wrapped error: %w", Permanent(io.EOF))
},
false,
},
} {
ensureRetries(testCase.name, testCase.shouldRetry, testCase.f)
}
}

func TestPermanent(t *testing.T) {
want := errors.New("foo")
other := errors.New("bar")
var err error = Permanent(want)

got := errors.Unwrap(err)
if got != want {
t.Errorf("got %v, want %v", got, want)
}

if is := errors.Is(err, want); !is {
t.Errorf("err: %v is not %v", err, want)
}

if is := errors.Is(err, other); is {
t.Errorf("err: %v is %v", err, other)
}

wrapped := fmt.Errorf("wrapped: %w", err)
var permanent *PermanentError
if !errors.As(wrapped, &permanent) {
t.Errorf("errors.As(%v, %v)", wrapped, permanent)
}

err = Permanent(nil)
if err != nil {
t.Errorf("got %v, want nil", err)
Expand Down

0 comments on commit 7411c02

Please sign in to comment.