Module: Lucerna::HTTP
- Defined in:
- lib/lucerna/http.rb
Defined Under Namespace
Classes: NetHttpTransport, Request, Response
Constant Summary collapse
- RETRY_BASE =
0.25- DEFAULT_SLEEPER =
->(seconds) { sleep(seconds) }
- RETRYABLE_EXCEPTIONS =
Transport failures worth retrying — the request may never have reached the server.
[ SystemCallError, SocketError, IOError, EOFError, Timeout::Error, # covers Net::OpenTimeout / Net::ReadTimeout / Net::WriteTimeout OpenSSL::SSL::SSLError, ].freeze
Class Method Summary collapse
-
.with_retry(attempts: 3, sleeper: DEFAULT_SLEEPER) ⇒ Object
Runs the block (which must return a Response) up to
attemptstimes with jittered exponential backoff.
Class Method Details
.with_retry(attempts: 3, sleeper: DEFAULT_SLEEPER) ⇒ Object
Runs the block (which must return a Response) up to attempts times
with jittered exponential backoff. Only network failures and 5xx are
retried; any 4xx is a stable answer and raises immediately —
AuthError for 401/403. Exhausted attempts raise the last error.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/lucerna/http.rb', line 58 def with_retry(attempts: 3, sleeper: DEFAULT_SLEEPER) attempt = 0 loop do attempt += 1 begin response = yield status = response.status return response if status < 400 error_class = status == 401 || status == 403 ? AuthError : RequestError error = error_class.new("request failed with status #{status}", status: status) raise error if status < 500 || attempt >= attempts rescue *RETRYABLE_EXCEPTIONS => exception raise RequestError, "#{exception.class}: #{exception.}" if attempt >= attempts end sleeper.call((RETRY_BASE * (2**(attempt - 1))) + (rand * 0.1)) end end |