in internal/retry/retry.go [97:136]
func RunWithResponse[T any](ctx context.Context, policy Policy, f func() (T, error)) (T, error) {
var (
res T
err error
)
if f == nil {
return res, fmt.Errorf("retry function cannot be nil")
}
for attempt := 0; ; attempt++ {
if res, err = f(); err == nil {
return res, nil
}
if !isRetriable(policy, err) {
return res, fmt.Errorf("giving up, retry policy returned false on error: %w", err)
}
galog.Debugf("Attempt %d failed with error %+v", attempt, err)
// Return early, no need to wait if all retries have exhausted.
if attempt+1 == policy.MaxAttempts {
return res, fmt.Errorf("exhausted all (%d) retries, last error: %w", policy.MaxAttempts, err)
}
select {
case <-ctx.Done():
return res, ctx.Err()
case <-time.After(backoff(attempt, policy)):
// Verify if context is still active. If not, return early.
select {
case <-ctx.Done():
return res, ctx.Err()
default:
// Timeout, continue retrying.
}
}
}
}