From a34aef4fc5ec97249bdd728fb41e62cc18612074 Mon Sep 17 00:00:00 2001 From: Julian Brost Date: Tue, 28 Sep 2021 11:16:51 +0200 Subject: [PATCH] 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. --- pkg/retry/retry.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/pkg/retry/retry.go b/pkg/retry/retry.go index b8c1c92a..29faf8a7 100644 --- a/pkg/retry/retry.go +++ b/pkg/retry/retry.go @@ -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):