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

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.message}" if attempt >= attempts
    end
    sleeper.call((RETRY_BASE * (2**(attempt - 1))) + (rand * 0.1))
  end
end