Skip to content

Commit

Permalink
Add Backoff.ErrCause() instead
Browse files Browse the repository at this point in the history
Signed-off-by: Marco Pracucci <[email protected]>
  • Loading branch information
pracucci committed Jul 3, 2024
1 parent 88aff0f commit 9b0cfc8
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 14 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@
* [CHANGE] Removed unused `time.Duration` parameter from `ShouldLog()` function in `middleware.OptionalLogging` interface. #513
* [CHANGE] Changed `ShouldLog()` function signature in `middleware.OptionalLogging` interface to `ShouldLog(context.Context) (bool, string)`: the returned `string` contains an optional reason. When reason is valued, `GRPCServerLog` adds `(<reason>)` suffix to the error. #514
* [CHANGE] Cache: Remove superfluous `cache.RemoteCacheClient` interface and unify all caches using the `cache.Cache` interface. #520
* [CHANGE] Backoff: `Backoff.Err()` now returns the context cancellation cause when provided to the context passed to `Backoff`. #538
* [FEATURE] Cache: Add support for configuring a Redis cache backend. #268 #271 #276
* [FEATURE] Add support for waiting on the rate limiter using the new `WaitN` method. #279
* [FEATURE] Add `log.BufferedLogger` type. #338
Expand Down Expand Up @@ -214,6 +213,7 @@
* [ENHANCEMENT] SpanProfiler: do less work on unsampled traces. #528
* [ENHANCEMENT] Log Middleware: if the trace is not sampled, log its ID as `trace_id_unsampled` instead of `trace_id`. #529
* [EHNANCEMENT] httpgrpc: httpgrpc Server can now use error message from special HTTP header when converting HTTP response to an error. This is useful when HTTP response body contains binary data that doesn't form valid utf-8 string, otherwise grpc would fail to marshal returned error. #531
* [CHANGE] Backoff: added `Backoff.ErrCause()` which is like `Backoff.Err()` but returns the context cause if backoff is terminated because the context has been canceled. #538
* [BUGFIX] spanlogger: Support multiple tenant IDs. #59
* [BUGFIX] Memberlist: fixed corrupted packets when sending compound messages with more than 255 messages or messages bigger than 64KB. #85
* [BUGFIX] Ring: `ring_member_ownership_percent` and `ring_tokens_owned` metrics are not updated on scale down. #109
Expand Down
13 changes: 10 additions & 3 deletions backoff/backoff.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,25 @@ func (b *Backoff) Ongoing() bool {
}

// Err returns the reason for terminating the backoff, or nil if it didn't terminate.
// If backoff is terminated because the context has been canceled, then this function
// returns the context cancellation cause.
func (b *Backoff) Err() error {
if b.ctx.Err() != nil {
return context.Cause(b.ctx)
return b.ctx.Err()
}
if b.cfg.MaxRetries != 0 && b.numRetries >= b.cfg.MaxRetries {
return fmt.Errorf("terminated after %d retries", b.numRetries)
}
return nil
}

// ErrCause is like Err() but returns the context cause if backoff is terminated because the
// context has been canceled.
func (b *Backoff) ErrCause() error {
if b.ctx.Err() != nil {
return context.Cause(b.ctx)
}
return b.Err()
}

// NumRetries returns the number of retries so far
func (b *Backoff) NumRetries() int {
return b.numRetries
Expand Down
26 changes: 16 additions & 10 deletions backoff/backoff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,44 +109,49 @@ func TestBackoff_Err(t *testing.T) {
cause := errors.New("my cause")

tests := map[string]struct {
ctx func(*testing.T) context.Context
expectedErr error
ctx func(*testing.T) context.Context
expectedErr error
expectedErrCause error
}{
"should return context.DeadlineExceeded when context deadline exceeded without cause": {
"context deadline exceeded without cause": {
ctx: func(t *testing.T) context.Context {
ctx, cancel := context.WithDeadline(context.Background(), time.Now())
t.Cleanup(cancel)

return ctx
},
expectedErr: context.DeadlineExceeded,
expectedErr: context.DeadlineExceeded,
expectedErrCause: context.DeadlineExceeded,
},
"should return cause when context deadline exceeded with cause": {
"context deadline exceeded with cause": {
ctx: func(t *testing.T) context.Context {
ctx, cancel := context.WithDeadlineCause(context.Background(), time.Now(), cause)

Check failure on line 128 in backoff/backoff_test.go

View workflow job for this annotation

GitHub Actions / Test on Go 1.20.x

undefined: context.WithDeadlineCause
t.Cleanup(cancel)

return ctx
},
expectedErr: cause,
expectedErr: context.DeadlineExceeded,
expectedErrCause: cause,
},
"should return context.Canceled when context is canceled without cause": {
"context is canceled without cause": {
ctx: func(_ *testing.T) context.Context {
ctx, cancel := context.WithCancel(context.Background())
cancel()

return ctx
},
expectedErr: context.Canceled,
expectedErr: context.Canceled,
expectedErrCause: context.Canceled,
},
"should return cause when context is canceled with cause": {
"context is canceled with cause": {
ctx: func(_ *testing.T) context.Context {
ctx, cancel := context.WithCancelCause(context.Background())
cancel(cause)

return ctx
},
expectedErr: cause,
expectedErr: context.Canceled,
expectedErrCause: cause,
},
}

Expand All @@ -160,6 +165,7 @@ func TestBackoff_Err(t *testing.T) {
}, time.Second, 10*time.Millisecond)

require.Equal(t, testData.expectedErr, b.Err())
require.Equal(t, testData.expectedErrCause, b.ErrCause())
})
}
}

0 comments on commit 9b0cfc8

Please sign in to comment.