Skip to content

Commit ea3bd55

Browse files
committed
Retry on TimeoutException, as we did in HTTP v1.9
1 parent 352bca2 commit ea3bd55

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

src/clientlayers/RetryRequest.jl

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module RetryRequest
22

3+
import ConcurrentUtilities
34
using Sockets, LoggingExtras, MbedTLS, OpenSSL, ExceptionUnwrapping
45
using ..IOExtras, ..Messages, ..Strings, ..ExceptionRequest, ..Exceptions
56

@@ -79,6 +80,7 @@ end
7980
isrecoverable(ex) = is_wrapped_exception(ex) ? isrecoverable(unwrap_exception(ex)) : false
8081
isrecoverable(::Union{Base.EOFError, Base.IOError, MbedTLS.MbedException, OpenSSL.OpenSSLError}) = true
8182
isrecoverable(ex::ArgumentError) = ex.msg == "stream is closed or unusable"
83+
isrecoverable(ex::ConcurrentUtilities.TimeoutException) = true
8284
isrecoverable(ex::CompositeException) = all(isrecoverable, ex.exceptions)
8385
# Treat all DNS errors except `EAI_AGAIN`` as non-recoverable
8486
# Ref: https://github.com/JuliaLang/julia/blob/ec8df3da3597d0acd503ff85ac84a5f8f73f625b/stdlib/Sockets/src/addrinfo.jl#L108-L112

test/client.jl

+30
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,35 @@ end
692692
end
693693
end
694694

695+
@testset "Connection TimeoutException is retried" begin
696+
# Since our request fails and we don't get to see the response, we
697+
# add this layer just after the retry layer to capture the context
698+
# of the request which we can use to test that we attempted the retries
699+
function test_context_layer(handler)
700+
return function(req; test_context::Dict, kw...)
701+
merge!(test_context, req.context)
702+
return handler(req; kw...)
703+
end
704+
end
705+
706+
test_context = Dict{Symbol,Any}()
707+
try
708+
HTTP.pushlayer!(test_context_layer)
709+
# 10.0.0.0 is non-routeable and will result in a connection timeout
710+
HTTP.get("http://10.0.0.0", connect_timeout=1, retries=3, retry_delays=[0.1, 0.1, 0.1], test_context=test_context)
711+
catch e
712+
@assert e isa HTTP.ConnectError
713+
@test e.error isa ConcurrentUtilities.TimeoutException
714+
finally
715+
HTTP.poplayer!()
716+
end
717+
718+
@test test_context[:retrylimitreached]
719+
@test test_context[:retryattempt] == 3
720+
@test test_context[:connect_errors] == 3
721+
end
722+
723+
695724
@testset "Retry with ConnectError" begin
696725
mktemp() do path, io
697726
redirect_stdout(io) do
@@ -717,6 +746,7 @@ end
717746
# isrecoverable tests
718747
@test !HTTP.RetryRequest.isrecoverable(nothing)
719748

749+
@test HTTP.RetryRequest.isrecoverable(ConcurrentUtilities.TimeoutException(1.0))
720750
@test !HTTP.RetryRequest.isrecoverable(ErrorException(""))
721751
@test !HTTP.RetryRequest.isrecoverable(ArgumentError("yikes"))
722752
@test HTTP.RetryRequest.isrecoverable(ArgumentError("stream is closed or unusable"))

0 commit comments

Comments
 (0)