Skip to content

Commit 393b7b2

Browse files
author
mar
committed
fix for issue #988 --> seemles highly customizable retry setup
1 parent fe9bf99 commit 393b7b2

File tree

1 file changed

+19
-20
lines changed

1 file changed

+19
-20
lines changed

src/clientlayers/RetryRequest.jl

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ module RetryRequest
33
using Sockets, LoggingExtras, MbedTLS, OpenSSL
44
using ..IOExtras, ..Messages, ..Strings, ..ExceptionRequest, ..Exceptions
55

6-
export retrylayer
7-
8-
FALSE(x...) = false
6+
export retrylayer, retry_check, isrecoverable
97

108
"""
119
retrylayer(handler) -> handler
@@ -21,13 +19,12 @@ e.g. `Sockets.DNSError`, `Base.EOFError` and `HTTP.StatusError`
2119
(if status is `5xx`).
2220
"""
2321
function retrylayer(handler)
24-
return function(req::Request; retry::Bool=true, retries::Int=4,
25-
retry_delays::ExponentialBackOff=ExponentialBackOff(n = retries, factor=3.0), retry_check=FALSE,
26-
retry_non_idempotent::Bool=false, kw...)
27-
if !retry || retries == 0
28-
# no retry
29-
return handler(req; kw...)
30-
end
22+
return function(req::Request; retries::Int=4, retry::Bool=retries>0,
23+
retry_delays=ExponentialBackOff(n=retries, factor=3.0), retry_check=retry_check,
24+
retry_non_idempotent::Bool=false, kw...
25+
)
26+
retry || return handler(req; kw...) # no retry
27+
retries = length(retry_delays)
3128
req.context[:allow_retries] = true
3229
req.context[:retryattempt] = 0
3330
if retry_non_idempotent
@@ -39,16 +36,10 @@ function retrylayer(handler)
3936
req_body_is_marked = true
4037
mark(req.body)
4138
end
42-
retryattempt = Ref(0)
43-
retry_request = Base.retry(handler,
44-
delays=retry_delays,
45-
check=(s, ex) -> begin
46-
retryattempt[] += 1
47-
req.context[:retryattempt] = retryattempt[]
48-
retry = retryable(req) || retryablebody(req) && _retry_check(s, ex, req, retry_check)
49-
if retryattempt[] == retries
50-
req.context[:retrylimitreached] = true
51-
end
39+
retry_request = Base.retry(handler, delays=retry_delays,
40+
check = (s, ex) -> begin
41+
req.context[:retrylimitreached] = (req.context[:retryattempt] += 1) > retries
42+
retry = retryable(req) && _retry_check(s, ex, req, retry_check)
5243
if retry
5344
@debugv 1 "🔄 Retry $ex: $(sprintcompact(req))"
5445
reset!(req.response)
@@ -72,6 +63,14 @@ function _retry_check(s, ex, req, check)
7263
resp_body = get(req.context, :response_body, nothing)
7364
return check(s, ex, req, resp_body !== nothing ? resp : nothing, resp_body)
7465
end
66+
retry_check(s, ex, x...) = isrecoverable(ex)
67+
isrecoverable(e) = false
68+
isrecoverable(e::Union{Base.EOFError, Base.IOError, MbedTLS.MbedException, OpenSSL.OpenSSLError}) = true
69+
isrecoverable(e::ArgumentError) = e.msg == "stream is closed or unusable"
70+
isrecoverable(e::Sockets.DNSError) = true
71+
isrecoverable(e::ConnectError) = true
72+
isrecoverable(e::RequestError) = isrecoverable(e.error)
73+
isrecoverable(e::StatusError) = retryable(e.status)
7574

7675
function no_retry_reason(ex, req)
7776
buf = IOBuffer()

0 commit comments

Comments
 (0)