Refactor should retry
This commit is contained in:
@@ -181,13 +181,11 @@ func (r *HTTPClient) Do(req *http.Request) (*http.Response, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
incr := r.shouldRetry(req, resp, err, attempt, r.rateLimitSleepSecs)
|
if !r.shouldRetry(req, resp, err, attempt, r.rateLimitSleepSecs) {
|
||||||
if incr == -1 {
|
|
||||||
break
|
break
|
||||||
} else if incr == 0 {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
attempt += incr
|
attempt++
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
return resp, err
|
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)
|
return nil, fmt.Errorf("unsupported proxy scheme: %s", proxyURL.Scheme)
|
||||||
}
|
}
|
||||||
|
|
||||||
// shouldRetry returns a number indicating whether the request should be retried
|
// shouldRetry returns true if the request should be retried
|
||||||
// -1: don't retry
|
func (r *HTTPClient) shouldRetry(req *http.Request, resp *http.Response, err error, attempts, rateLimitSleep int) bool {
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// assume that all addMagnet requests are always successful;
|
// assume that all addMagnet requests are always successful;
|
||||||
// don't retry to prevent duplicate torrents
|
// don't retry to prevent duplicate torrents
|
||||||
if req.Host == "api.real-debrid.com" && strings.HasSuffix(req.URL.Path, "torrents/addMagnet") {
|
if req.Host == "api.real-debrid.com" && strings.HasSuffix(req.URL.Path, "torrents/addMagnet") {
|
||||||
return -1
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if apiErr, ok := err.(*ApiErrorResponse); ok {
|
if apiErr, ok := err.(*ApiErrorResponse); ok {
|
||||||
switch apiErr.Code {
|
switch apiErr.Code {
|
||||||
case 5: // Slow down (retry infinitely)
|
case 5: // Slow down (retry infinitely)
|
||||||
secs := r.backoff(attempts, rateLimitSleep)
|
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)
|
time.Sleep(secs)
|
||||||
return 0
|
return true
|
||||||
case 34: // Too many requests (retry infinitely)
|
case 34: // Too many requests (retry infinitely)
|
||||||
secs := r.backoff(attempts, rateLimitSleep)
|
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)
|
time.Sleep(secs)
|
||||||
return 0
|
return true
|
||||||
case 36: // Fair Usage Limit
|
case 36: // Fair Usage Limit
|
||||||
secs := r.backoff(attempts, rateLimitSleep)
|
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)
|
time.Sleep(secs)
|
||||||
return 0
|
return true
|
||||||
case -1: // Internal error
|
case -1: // Internal error
|
||||||
r.log.Debugf("RD Internal error, attempt #%d, retrying", attempts+1)
|
if attempts >= r.maxRetries {
|
||||||
return 1
|
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:
|
default:
|
||||||
return -1
|
return false
|
||||||
}
|
}
|
||||||
} else if downloadErr, ok := err.(*DownloadErrorResponse); ok {
|
} else if downloadErr, ok := err.(*DownloadErrorResponse); ok {
|
||||||
switch downloadErr.Message {
|
switch downloadErr.Message {
|
||||||
case "invalid_download_code": // 404
|
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)
|
secs := r.backoff(attempts, rateLimitSleep)
|
||||||
r.log.Debugf("Invalid download code, attempt #%d, retrying in %d seconds", attempts+1, secs/time.Second)
|
r.log.Debugf("Invalid download code, attempt #%d, retrying in %d seconds", attempts+1, secs/time.Second)
|
||||||
time.Sleep(r.backoff(attempts, rateLimitSleep))
|
time.Sleep(secs)
|
||||||
return 1
|
return true
|
||||||
default:
|
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
|
// 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-")
|
hasRangeHeader := req.Header.Get("Range") != "" && !strings.HasPrefix(req.Header.Get("Range"), "bytes=0-")
|
||||||
if okResponseCode && hasRangeHeader && resp.Header.Get("Content-Range") == "" {
|
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)
|
if attempts >= r.maxRetries {
|
||||||
return 1
|
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 {
|
func backoffFunc(attempt, base int) time.Duration {
|
||||||
|
|||||||
Reference in New Issue
Block a user