@@ -10,6 +10,7 @@ def setup
1010 def conn ( *retry_args )
1111 Faraday . new do |b |
1212 b . request :retry , *retry_args
13+
1314 b . adapter :test do |stub |
1415 [ 'get' , 'post' ] . each do |method |
1516 stub . send ( method , '/unstable' ) do |env |
@@ -18,6 +19,22 @@ def conn(*retry_args)
1819 env [ :body ] = nil # simulate blanking out response body
1920 @explode . call @times_called
2021 end
22+
23+ stub . send ( method , '/throttled' ) do |env |
24+ @times_called += 1
25+ @envs << env . dup
26+
27+ params = env [ :params ]
28+
29+ status = ( params [ 'status' ] || 429 ) . to_i
30+ headers = { }
31+
32+ retry_after = params [ 'retry_after' ]
33+
34+ headers [ 'Retry-After' ] = retry_after if retry_after
35+
36+ [ status , headers , '' ]
37+ end
2138 end
2239 end
2340 end
@@ -68,7 +85,7 @@ def test_interval
6885 assert_in_delta 0.2 , Time . now - started , 0.04
6986 end
7087
71- def test_calls_sleep_amount
88+ def test_calls_calculate_sleep_amount
7289 explode_app = MiniTest ::Mock . new
7390 explode_app . expect ( :call , nil , [ { :body => nil } ] )
7491 def explode_app . call ( env )
@@ -79,7 +96,7 @@ def explode_app.call(env)
7996 class << retry_middleware
8097 attr_accessor :sleep_amount_retries
8198
82- def sleep_amount ( retries )
99+ def calculate_sleep_amount ( retries , env )
83100 self . sleep_amount_retries . delete ( retries )
84101 0
85102 end
@@ -95,30 +112,30 @@ def sleep_amount(retries)
95112
96113 def test_exponential_backoff
97114 middleware = Faraday ::Request ::Retry . new ( nil , :max => 5 , :interval => 0.1 , :backoff_factor => 2 )
98- assert_equal middleware . sleep_amount ( 5 ) , 0.1
99- assert_equal middleware . sleep_amount ( 4 ) , 0.2
100- assert_equal middleware . sleep_amount ( 3 ) , 0.4
115+ assert_equal middleware . send ( :calculate_retry_interval , 5 ) , 0.1
116+ assert_equal middleware . send ( :calculate_retry_interval , 4 ) , 0.2
117+ assert_equal middleware . send ( :calculate_retry_interval , 3 ) , 0.4
101118 end
102119
103120 def test_exponential_backoff_with_max_interval
104121 middleware = Faraday ::Request ::Retry . new ( nil , :max => 5 , :interval => 1 , :max_interval => 3 , :backoff_factor => 2 )
105- assert_equal middleware . sleep_amount ( 5 ) , 1
106- assert_equal middleware . sleep_amount ( 4 ) , 2
107- assert_equal middleware . sleep_amount ( 3 ) , 3
108- assert_equal middleware . sleep_amount ( 2 ) , 3
122+ assert_equal middleware . send ( :calculate_retry_interval , 5 ) , 1
123+ assert_equal middleware . send ( :calculate_retry_interval , 4 ) , 2
124+ assert_equal middleware . send ( :calculate_retry_interval , 3 ) , 3
125+ assert_equal middleware . send ( :calculate_retry_interval , 2 ) , 3
109126 end
110127
111128 def test_random_additional_interval_amount
112129 middleware = Faraday ::Request ::Retry . new ( nil , :max => 2 , :interval => 0.1 , :interval_randomness => 1.0 )
113- sleep_amount = middleware . sleep_amount ( 2 )
130+ sleep_amount = middleware . send ( :calculate_retry_interval , 2 )
114131 assert_operator sleep_amount , :>= , 0.1
115132 assert_operator sleep_amount , :<= , 0.2
116133 middleware = Faraday ::Request ::Retry . new ( nil , :max => 2 , :interval => 0.1 , :interval_randomness => 0.5 )
117- sleep_amount = middleware . sleep_amount ( 2 )
134+ sleep_amount = middleware . send ( :calculate_retry_interval , 2 )
118135 assert_operator sleep_amount , :>= , 0.1
119136 assert_operator sleep_amount , :<= , 0.15
120137 middleware = Faraday ::Request ::Retry . new ( nil , :max => 2 , :interval => 0.1 , :interval_randomness => 0.25 )
121- sleep_amount = middleware . sleep_amount ( 2 )
138+ sleep_amount = middleware . send ( :calculate_retry_interval , 2 )
122139 assert_operator sleep_amount , :>= , 0.1
123140 assert_operator sleep_amount , :<= , 0.125
124141 end
@@ -212,5 +229,53 @@ def test_should_rewind_files_on_retry
212229 assert_equal 3 , @times_called
213230 assert_equal 2 , rewound
214231 end
232+
233+ def test_should_retry_retriable_response
234+ params = { status : 429 }
235+ conn ( :max => 1 , :retry_statuses => 429 ) . get ( "/throttled" , params )
236+
237+ assert_equal 2 , @times_called
238+ end
239+
240+ def test_should_not_retry_non_retriable_response
241+ params = { status : 503 }
242+ conn ( :max => 1 , :retry_statuses => 429 ) . get ( "/throttled" , params )
243+
244+ assert_equal 1 , @times_called
245+ end
246+
247+ def test_interval_if_retry_after_present
248+ started = Time . now
249+
250+ params = { :retry_after => 0.5 }
251+ conn ( :max => 1 , :interval => 0.1 , :retry_statuses => [ 429 ] ) . get ( "/throttled" , params )
252+
253+ assert Time . now - started > 0.5
254+ end
255+
256+ def test_should_ignore_retry_after_if_less_then_calculated
257+ started = Time . now
258+
259+ params = { :retry_after => 0.1 }
260+ conn ( :max => 1 , :interval => 0.2 , :retry_statuses => [ 429 ] ) . get ( "/throttled" , params )
261+
262+ assert Time . now - started > 0.2
263+ end
264+
265+ def test_interval_when_retry_after_is_timestamp
266+ started = Time . now
267+
268+ params = { :retry_after => ( Time . now . utc + 2 ) . strftime ( '%a, %d %b %Y %H:%M:%S GMT' ) }
269+ conn ( :max => 1 , :interval => 0.1 , :retry_statuses => [ 429 ] ) . get ( "/throttled" , params )
270+
271+ assert Time . now - started > 1
272+ end
273+
274+ def test_should_not_retry_when_retry_after_greater_then_max_interval
275+ params = { :retry_after => ( Time . now . utc + 20 ) . strftime ( '%a, %d %b %Y %H:%M:%S GMT' ) }
276+ conn ( :max => 2 , :interval => 0.1 , :retry_statuses => [ 429 ] , max_interval : 5 ) . get ( "/throttled" , params )
277+
278+ assert_equal 1 , @times_called
279+ end
215280 end
216281end
0 commit comments