diff --git a/pkg/http/client.go b/pkg/http/client.go index 0f4db5b..18c8046 100644 --- a/pkg/http/client.go +++ b/pkg/http/client.go @@ -181,13 +181,11 @@ func (r *HTTPClient) Do(req *http.Request) (*http.Response, error) { } } - incr := r.shouldRetry(req, resp, err, attempt, r.rateLimitSleepSecs) - if incr == -1 { + if !r.shouldRetry(req, resp, err, attempt, r.rateLimitSleepSecs) { break - } else if incr == 0 { - continue } - attempt += incr + attempt++ + continue } return resp, err } @@ -240,53 +238,56 @@ func (r *HTTPClient) proxyDialer(proxyURL *url.URL) (proxy.Dialer, error) { return nil, fmt.Errorf("unsupported proxy scheme: %s", proxyURL.Scheme) } -// shouldRetry returns a number indicating whether the request should be retried -// -1: don't retry -// 0: retry indefinitely -// 1: retry until maxRetries -func (r *HTTPClient) shouldRetry(req *http.Request, resp *http.Response, err error, attempts, rateLimitSleep int) int { - if attempts >= r.maxRetries { - return -1 - } - +// shouldRetry returns true if the request should be retried +func (r *HTTPClient) shouldRetry(req *http.Request, resp *http.Response, err error, attempts, rateLimitSleep int) bool { // assume that all addMagnet requests are always successful; // don't retry to prevent duplicate torrents if req.Host == "api.real-debrid.com" && strings.HasSuffix(req.URL.Path, "torrents/addMagnet") { - return -1 + return false } if apiErr, ok := err.(*ApiErrorResponse); ok { switch apiErr.Code { case 5: // Slow down (retry infinitely) secs := r.backoff(attempts, rateLimitSleep) - r.log.Debugf("API rate limit reached, retrying in %d seconds", secs/time.Second) + r.log.Debugf("API rate limit reached, attempt #%d, retrying in %d seconds", attempts+1, secs/time.Second) time.Sleep(secs) - return 0 + return true case 34: // Too many requests (retry infinitely) secs := r.backoff(attempts, rateLimitSleep) - r.log.Debugf("API rate limit reached, retrying in %d seconds", secs/time.Second) + r.log.Debugf("API rate limit reached, attempt #%d, retrying in %d seconds", attempts+1, secs/time.Second) time.Sleep(secs) - return 0 + return true case 36: // Fair Usage Limit secs := r.backoff(attempts, rateLimitSleep) - r.log.Debugf("Fair usage limit reached, retrying in %d seconds", secs/time.Second) + r.log.Debugf("Fair usage limit reached, attempt #%d, retrying in %d seconds", attempts+1, secs/time.Second) time.Sleep(secs) - return 0 + return true case -1: // Internal error - r.log.Debugf("RD Internal error, attempt #%d, retrying", attempts+1) - return 1 + if attempts >= r.maxRetries { + r.log.Debugf("RD Internal error, attempt #%d", attempts+1) + return false + } + secs := r.backoff(attempts, 1) + r.log.Debugf("RD Internal error, attempt #%d, retrying in %d seconds", attempts+1, secs/time.Second) + time.Sleep(secs) + return true default: - return -1 + return false } } else if downloadErr, ok := err.(*DownloadErrorResponse); ok { switch downloadErr.Message { case "invalid_download_code": // 404 + if attempts >= r.maxRetries { + r.log.Debugf("Invalid download code, attempt #%d", attempts+1) + return false + } secs := r.backoff(attempts, rateLimitSleep) r.log.Debugf("Invalid download code, attempt #%d, retrying in %d seconds", attempts+1, secs/time.Second) - time.Sleep(r.backoff(attempts, rateLimitSleep)) - return 1 + time.Sleep(secs) + return true default: - return -1 + return false } } @@ -296,13 +297,19 @@ func (r *HTTPClient) shouldRetry(req *http.Request, resp *http.Response, err err // if the request has a Range header but the server doesn't respond with a Content-Range header hasRangeHeader := req.Header.Get("Range") != "" && !strings.HasPrefix(req.Header.Get("Range"), "bytes=0-") if okResponseCode && hasRangeHeader && resp.Header.Get("Content-Range") == "" { - return 0 + return true } - return -1 + return false } - r.log.Debugf("Request failed, attempt #%d, retrying (error=%v)", attempts+1, err) - return 1 + if attempts >= r.maxRetries { + r.log.Debugf("Request failed, attempt #%d (error=%v)", attempts+1, err) + return false + } + secs := r.backoff(attempts, 1) + r.log.Debugf("Request failed, attempt #%d, retrying in %d seconds (error=%v)", attempts+1, secs/time.Second, err) + time.Sleep(secs) + return true } func backoffFunc(attempt, base int) time.Duration {