Skip to content

Commit

Permalink
introduce myError
Browse files Browse the repository at this point in the history
  • Loading branch information
shogo82148 committed Jun 20, 2024
1 parent dcd4f97 commit 566c8a5
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 28 deletions.
11 changes: 9 additions & 2 deletions func.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@ func DoValue[T any](ctx context.Context, policy *Policy, f func() (T, error)) (T
return v, nil
}

// short cut for calling isPermanent and Unwrap
if err, ok := err.(*permanentError); ok {
// short cut for calling Unwrap
if err, ok := err.(*myError); ok {
if err.temporary {
continue
}
return zero, err.error
}

Expand All @@ -41,5 +44,9 @@ func DoValue[T any](ctx context.Context, policy *Policy, f func() (T, error)) (T
if err := retrier.err; err != nil {
return zero, err
}
if err, ok := err.(*myError); ok {
// Unwrap the error if it's marked as temporary.
return zero, err.error
}
return zero, err
}
23 changes: 22 additions & 1 deletion func_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,32 @@ func TestDoValue_Success(t *testing.T) {

func TestDoValue_MarkPermanent(t *testing.T) {
permanentErr := errors.New("permanent error")
policy := &Policy{}
policy := &Policy{MaxCount: 10}
count := 0
_, err := DoValue(context.Background(), policy, func() (int, error) {
count++
return 0, MarkPermanent(permanentErr)
})
if err != permanentErr {
t.Errorf("want error is %#v, got %#v", err, permanentErr)
}
if count != 1 {
t.Errorf("want %d, got %d", 1, count)
}
}

func TestDoValue_MarkTemporary(t *testing.T) {
temporaryErr := errors.New("temporary error")
policy := &Policy{MaxCount: 10}
count := 0
_, err := DoValue(context.Background(), policy, func() (int, error) {
count++
return 0, MarkTemporary(temporaryErr)
})
if err != temporaryErr {
t.Errorf("want error is %#v, got %#v", err, temporaryErr)
}
if count != 10 {
t.Errorf("want %d, got %d", 10, count)
}
}
39 changes: 14 additions & 25 deletions retry.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,11 @@ func (p *Policy) Do(ctx context.Context, f func() error) error {
return nil
}

// short cut for calling isPermanent and Unwrap
if err, ok := err.(*permanentError); ok {
// short cut for calling Unwrap
if err, ok := err.(*myError); ok {
if err.temporary {
continue
}
return err.error
}

Expand All @@ -88,7 +91,7 @@ func (p *Policy) Do(ctx context.Context, f func() error) error {
if err := retrier.err; err != nil {
return err
}
if err, ok := err.(*temporaryError); ok {
if err, ok := err.(*myError); ok {
// Unwrap the error if it's marked as temporary.
return err.error
}
Expand All @@ -99,49 +102,35 @@ type temporary interface {
Temporary() bool
}

var _ temporary = (*permanentError)(nil)
var _ temporary = (*myError)(nil)

type permanentError struct {
type myError struct {
error
temporary bool
}

// implements interface{ Temporary() bool }
// Inspecting errors https://dave.cheney.net/2014/12/24/inspecting-errors
func (e *permanentError) Temporary() bool {
return false
func (e *myError) Temporary() bool {
return e.temporary
}

// Unwrap implements errors.Wrapper.
func (e *permanentError) Unwrap() error {
func (e *myError) Unwrap() error {
return e.error
}

// MarkPermanent marks err as a permanent error.
// It returns the error that implements interface{ Temporary() bool } and Temporary() returns false.
func MarkPermanent(err error) error {
return &permanentError{err}
}

type temporaryError struct {
error
}

// implements interface{ Temporary() bool }
// Inspecting errors https://dave.cheney.net/2014/12/24/inspecting-errors
func (e *temporaryError) Temporary() bool {
return true
}

// Unwrap implements errors.Wrapper.
func (e *temporaryError) Unwrap() error {
return e.error
return &myError{err, false}
}

// MarkTemporary wraps an error as a temporary error, allowing retry mechanisms to handle it appropriately.
// This is especially useful in scenarios where errors may not require immediate termination of a process,
// but rather can be resolved through retrying operations.
func MarkTemporary(err error) error {
return &temporaryError{err}
return &myError{err, true}
}

// Continue returns whether retrying should be continued.
Expand Down

0 comments on commit 566c8a5

Please sign in to comment.