in internal/requesthelper/retry.go [33:95]
func WithRetries(ctx *log.Context, rm *RequestManager, sf SleepFunc, eTag string) (*http.Response, error) {
var lastErr error
for n := 0; n < expRetryN; n++ {
resp, err := rm.MakeRequest(ctx, eTag)
// If there was no error, return the response
if err == nil {
return resp, nil
}
lastErr = err
ctx.Log("warning", fmt.Sprintf("error on attempt %v: %v", n+1, err))
status := -1
if resp != nil {
if resp.Body != nil { // we are not going to read this response body
resp.Body.Close()
}
status = resp.StatusCode
}
// status == -1 means that there wasn't any http request
if status == -1 {
te, haste := lastErr.(interface {
Temporary() bool
})
to, hasto := lastErr.(interface {
Timeout() bool
})
if haste || hasto {
if haste && te.Temporary() {
ctx.Log("message", fmt.Sprintf("temporary error occurred. Retrying: %v", lastErr))
} else if hasto && to.Timeout() {
ctx.Log("message", fmt.Sprintf("timeout error occurred. Retrying: %v", lastErr))
} else {
ctx.Log("message", fmt.Sprintf("non-timeout, non-temporary error occurred, skipping retries: %v", lastErr))
break
}
} else {
ctx.Log("message", "no response returned and unexpected error, skipping retries.")
break
}
} else if responseNotModified(status) {
return resp, nil
} else if noImmediateGoalStatesToProcess(status) {
return resp, nil
} else if !isTransientHTTPStatusCode(status) {
ctx.Log("message", fmt.Sprintf("RequestManager returned %v, skipping retries", status))
break
}
if n < expRetryN-1 {
// have more retries to go, sleep before retrying
slp := expRetryK * time.Duration(int(math.Pow(float64(expRetryM), float64(n))))
sf(slp)
}
}
return nil, lastErr
}