diff --git a/client.go b/client.go index bd75ad16cd..0d0b0ebdb8 100644 --- a/client.go +++ b/client.go @@ -661,7 +661,7 @@ type RetryIfFunc func(request *Request) bool // RetryIfErrFunc defines the signature of the retry if error function. // request and error passed to RetryIfErrFunc, if there are any request errors. -type RetryIfErrFunc func(request *Request, err error) bool +type RetryIfErrFunc func(request *Request, retryCount int, err error) (sleepDuration time.Duration, retry bool) // RoundTripper wraps every request/response. type RoundTripper interface { @@ -721,6 +721,8 @@ type HostClient struct { // RetryIfErr controls whether a retry should be attempted after an error. // By default, it uses the isIdempotent function. RetryIfErr RetryIfErrFunc + // Whether the timeout resets before retrying. + RetryResetTimeout bool connsWait *wantConnQueue @@ -1308,6 +1310,11 @@ func (c *HostClient) Do(req *Request, resp *Response) error { if timeout > 0 { deadline = time.Now().Add(timeout) } + retryFunc := c.RetryIf + sleepDuration := time.Duration(0) + if retryFunc == nil { + retryFunc = isIdempotent + } atomic.AddInt32(&c.pendingRequests, 1) for { @@ -1329,16 +1336,17 @@ func (c *HostClient) Do(req *Request, resp *Response) error { if hasBodyStream { break } + // Path prioritization based on ease of computation + attempts++ - switch { - case c.RetryIf != nil: + if attempts >= maxAttempts { + break + } + if c.RetryIfErr != nil { + sleepDuration, retry = c.RetryIfErr(req, attempts, err) + } else { retry = c.RetryIf(req) - case c.RetryIfErr != nil: - retry = c.RetryIfErr(req, err) - default: - retry = isIdempotent(req) } - if !retry { // Retry non-idempotent requests if the server closes // the connection before sending the response. @@ -1351,10 +1359,6 @@ func (c *HostClient) Do(req *Request, resp *Response) error { break } } - attempts++ - if attempts >= maxAttempts { - break - } } atomic.AddInt32(&c.pendingRequests, -1)