diff --git a/src/clientlayers/RetryRequest.jl b/src/clientlayers/RetryRequest.jl index 8fa5850ef..d6e1275d0 100644 --- a/src/clientlayers/RetryRequest.jl +++ b/src/clientlayers/RetryRequest.jl @@ -3,9 +3,7 @@ module RetryRequest using Sockets, LoggingExtras, MbedTLS, OpenSSL using ..IOExtras, ..Messages, ..Strings, ..ExceptionRequest, ..Exceptions -export retrylayer - -FALSE(x...) = false +export retrylayer, retry_check, isrecoverable, isstatuserror """ retrylayer(handler) -> handler @@ -21,13 +19,12 @@ e.g. `Sockets.DNSError`, `Base.EOFError` and `HTTP.StatusError` (if status is `5xx`). """ function retrylayer(handler) - return function(req::Request; retry::Bool=true, retries::Int=4, - retry_delays::ExponentialBackOff=ExponentialBackOff(n = retries, factor=3.0), retry_check=FALSE, - retry_non_idempotent::Bool=false, kw...) - if !retry || retries == 0 - # no retry - return handler(req; kw...) - end + return function(req::Request; retries::Int=4, retry::Bool=retries>0, + retry_delays=ExponentialBackOff(n=retries, factor=3.0), retry_check=retry_check, + retry_non_idempotent::Bool=false, kw... + ) + retry || return handler(req; kw...) # no retry + retries = length(retry_delays) req.context[:allow_retries] = true req.context[:retryattempt] = 0 if retry_non_idempotent @@ -39,16 +36,10 @@ function retrylayer(handler) req_body_is_marked = true mark(req.body) end - retryattempt = Ref(0) - retry_request = Base.retry(handler, - delays=retry_delays, - check=(s, ex) -> begin - retryattempt[] += 1 - req.context[:retryattempt] = retryattempt[] - retry = retryable(req) || retryablebody(req) && _retry_check(s, ex, req, retry_check) - if retryattempt[] == retries - req.context[:retrylimitreached] = true - end + retry_request = Base.retry(handler, delays=retry_delays, + check = (s, ex) -> begin + req.context[:retrylimitreached] = (req.context[:retryattempt] += 1) > retries + retry = retryable(req) && _retry_check(s, ex, req, retry_check) if retry @debugv 1 "🔄 Retry $ex: $(sprintcompact(req))" reset!(req.response) @@ -67,6 +58,11 @@ function retrylayer(handler) end end +isstatuserror(e, status) = e isa HTTP.StatusError && e.status in status +isrecoverable(ex) = true +isrecoverable(ex::StatusError) = retryable(ex.status) +retry_check(s, ex, x...) = isrecoverable(ex) + function _retry_check(s, ex, req, check) resp = req.response resp_body = get(req.context, :response_body, nothing)