retry: if stopped due to outer context, return that error

If there is an outer context that is canceled or exceeds its deadline before
the internal timeout is reached, its error should be passed on as the failure
didn't happen due to retry giving up.
This commit is contained in:
Julian Brost 2021-09-28 11:16:51 +02:00
parent 217ab03e59
commit a34aef4fc5

View file

@ -28,6 +28,8 @@ type Settings struct {
func WithBackoff(
ctx context.Context, retryableFunc RetryableFunc, retryable IsRetryable, b backoff.Backoff, settings Settings,
) (err error) {
parentCtx := ctx
if settings.Timeout > 0 {
var cancelCtx context.CancelFunc
ctx, cancelCtx = context.WithTimeout(ctx, settings.Timeout)
@ -65,10 +67,14 @@ func WithBackoff(
sleep := b(attempt)
select {
case <-ctx.Done():
if err == nil {
err = ctx.Err()
if outerErr := parentCtx.Err(); outerErr != nil {
err = errors.Wrap(outerErr, "outer context canceled")
} else {
if err == nil {
err = ctx.Err()
}
err = errors.Wrap(err, "can't retry")
}
err = errors.Wrap(err, "can't retry")
return
case <-time.After(sleep):