@@ -11,25 +11,46 @@ module Http
1111 Faraday ::ConnectionFailed , Faraday ::ClientError , Net ::OpenTimeout , Errno ::ECONNREFUSED , EOFError , Faraday ::ServerError
1212 ]
1313
14- def connection ( verify_ssl = true , max_retries = 5 , hmac_client : nil )
14+ def connection ( verify_ssl = true , max_retries = 5 , hmac_client : nil , retry_options : nil )
15+ default_config = {
16+ max : max_retries ,
17+ interval : 0.1 ,
18+ max_interval : 30 ,
19+ backoff_factor : 5 ,
20+ methods : %i[ get post ] ,
21+ exceptions : RETRY_EXCEPTIONS ,
22+ retry_statuses : [ 429 , 500 , 502 , 503 , 504 ] ,
23+ retry_block : method ( :log_retry ) ,
24+ exhausted_retries_block : method ( :log_retries_exhausted )
25+ }
26+
27+ priority_config = nil
28+ if retry_options
29+ # `retry_options` configures a dedicated retry policy for a specific set of
30+ # statuses (e.g. 504). It is applied as a separate, outer retry middleware so
31+ # those statuses get their own max/interval, while every other error keeps the
32+ # default behaviour below. The prioritised statuses are removed from the default
33+ # middleware so they are never retried twice.
34+ priority_statuses = Array ( retry_options [ :retry_statuses ] )
35+ priority_config = default_config . merge ( retry_options ) . merge (
36+ methods : [ ] , # rely solely on retry_if so only the prioritised statuses retry
37+ retry_if : -> ( env , exception ) { priority_statuses . include? ( retry_status ( env , exception ) ) }
38+ )
39+
40+ default_config [ :retry_statuses ] -= priority_statuses
41+ default_config [ :methods ] = [ ]
42+ default_config [ :retry_if ] = -> ( env , exception ) { !priority_statuses . include? ( retry_status ( env , exception ) ) }
43+ end
44+
1545 Faraday . new do |faraday |
1646 faraday . request :multipart
1747 faraday . request :json
1848 faraday . ssl . verify = verify_ssl
1949 if @options && @options [ :debug ] == true
2050 faraday . response :logger # This logs to STDOUT by default
2151 end
22- faraday . request :retry , {
23- max : max_retries ,
24- interval : 0.1 ,
25- max_interval : 30 ,
26- backoff_factor : 5 ,
27- methods : %i[ get post ] ,
28- exceptions : RETRY_EXCEPTIONS ,
29- retry_statuses : [ 429 , 500 , 502 , 503 , 504 ] ,
30- retry_block : method ( :log_retry ) ,
31- exhausted_retries_block : method ( :log_retries_exhausted )
32- }
52+ faraday . request :retry , priority_config if priority_config
53+ faraday . request :retry , default_config
3354 if hmac_client
3455 require_relative './faraday_middlewares/faraday_hmac_middleware'
3556 faraday . use FaradayHmac , hmac_client
@@ -40,20 +61,31 @@ def connection(verify_ssl = true, max_retries = 5, hmac_client: nil)
4061 end
4162 end
4263
43- def http_get ( url , headers , max_retries = 5 , verify_ssl = true , hmac_client : nil )
44- connection ( verify_ssl , max_retries , hmac_client :) . run_request ( :get , url , nil , headers )
64+ # Resolves the HTTP status for a retry decision. `raise_error` runs before the retry
65+ # middleware, so error responses arrive here as exceptions; we read the status from
66+ # the exception when present and fall back to the response env otherwise.
67+ def retry_status ( env , exception )
68+ if exception . respond_to? ( :response_status ) && exception . response_status
69+ exception . response_status
70+ else
71+ env &.status
72+ end
73+ end
74+
75+ def http_get ( url , headers , max_retries = 5 , verify_ssl = true , hmac_client : nil , retry_options : nil )
76+ connection ( verify_ssl , max_retries , hmac_client :, retry_options :) . run_request ( :get , url , nil , headers )
4577 end
4678
47- def http_post ( url , headers , payload , max_retries = 5 , verify_ssl = true , hmac_client : nil )
48- connection ( verify_ssl , max_retries , hmac_client :) . run_request ( :post , url , payload , headers )
79+ def http_post ( url , headers , payload , max_retries = 5 , verify_ssl = true , hmac_client : nil , retry_options : nil )
80+ connection ( verify_ssl , max_retries , hmac_client :, retry_options : ) . run_request ( :post , url , payload , headers )
4981 end
5082
51- def http_put ( url , headers , payload , max_retries = 5 , verify_ssl = true )
52- connection ( verify_ssl , max_retries ) . run_request ( :put , url , payload , headers )
83+ def http_put ( url , headers , payload , max_retries = 5 , verify_ssl = true , retry_options : nil )
84+ connection ( verify_ssl , max_retries , retry_options : ) . run_request ( :put , url , payload , headers )
5385 end
5486
55- def http_delete ( url , headers , max_retries = 5 , verify_ssl = true )
56- connection ( verify_ssl , max_retries ) . run_request ( :delete , url , nil , headers )
87+ def http_delete ( url , headers , max_retries = 5 , verify_ssl = true , retry_options : nil )
88+ connection ( verify_ssl , max_retries , retry_options : ) . run_request ( :delete , url , nil , headers )
5789 end
5890
5991 def log_retry ( retry_count :, exception :, will_retry_in :, **_kwargs )
0 commit comments