Skip to content

Commit

Permalink
Merge pull request #51 from slizco/slizco-add-opt-surface-work-error
Browse files Browse the repository at this point in the history
Add a SurfaceWorkErrors() opt to the retrier
  • Loading branch information
eapache authored Jul 19, 2024
2 parents 6a6d489 + 029d178 commit 96d183b
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 6 deletions.
23 changes: 17 additions & 6 deletions retrier/retrier.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ import (
// Retrier implements the "retriable" resiliency pattern, abstracting out the process of retrying a failed action
// a certain number of times with an optional back-off between each retry.
type Retrier struct {
backoff []time.Duration
infiniteRetry bool
class Classifier
jitter float64
rand *rand.Rand
randMu sync.Mutex
backoff []time.Duration
infiniteRetry bool
surfaceWorkErrors bool
class Classifier
jitter float64
rand *rand.Rand
randMu sync.Mutex
}

// New constructs a Retrier with the given backoff pattern and classifier. The length of the backoff pattern
Expand All @@ -43,6 +44,13 @@ func (r *Retrier) WithInfiniteRetry() *Retrier {
return r
}

// WithSurfaceWorkErrors configures the retrier to always return the last error received from work function
// even if a context timeout/deadline is hit.
func (r *Retrier) WithSurfaceWorkErrors() *Retrier {
r.surfaceWorkErrors = true
return r
}

// Run executes the given work function by executing RunCtx without context.Context.
func (r *Retrier) Run(work func() error) error {
return r.RunFn(context.Background(), func(c context.Context, r int) error {
Expand Down Expand Up @@ -83,6 +91,9 @@ func (r *Retrier) RunFn(ctx context.Context, work func(ctx context.Context, retr

timer := time.NewTimer(r.calcSleep(retries))
if err := r.sleep(ctx, timer); err != nil {
if r.surfaceWorkErrors {
return ret
}
return err
}

Expand Down
46 changes: 46 additions & 0 deletions retrier/retrier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,52 @@ func TestRetrierRunFnWithInfinite(t *testing.T) {
}
}

func TestRetrierRunFnWithSurfaceWorkErrors(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
r := New([]time.Duration{0, 10 * time.Millisecond}, nil).WithSurfaceWorkErrors()
errExpected := []error{errFoo, errBar, errBaz}

err := r.RunFn(ctx, func(ctx context.Context, retries int) error {
if retries >= len(errExpected) {
return nil
}
if retries == 1 {
// Context canceled inside second call to work function.
cancel()
}
err := errExpected[retries]
retries++
return err
})
if err != errBar {
t.Error(err)
}
}

func TestRetrierRunFnWithoutSurfaceWorkErrors(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
r := New([]time.Duration{0, 10 * time.Millisecond}, nil)
errExpected := []error{errFoo, errBar, errBaz}

err := r.RunFn(ctx, func(ctx context.Context, retries int) error {
if retries >= len(errExpected) {
return nil
}
if retries == 1 {
// Context canceled inside second call to work function.
cancel()
}
err := errExpected[retries]
retries++
return err
})
if err != context.Canceled {
t.Error(err)
}
}

func TestRetrierNone(t *testing.T) {
r := New(nil, nil)

Expand Down

0 comments on commit 96d183b

Please sign in to comment.