Ruby
HTTP client is not sophisticated enough to handle errors gracefully. I came across a well-designed client for a web service at [AppSignal].
(https://blog.appsignal.com/2018/05/16/ensure-retry-and-reraise-exceptions-in-ruby.html)
The code for the client is as following:
require 'uri' | |
require 'net/http' | |
def get_server_connection(arg1, arg2) | |
http = nil | |
retries = 0 | |
uri = URI("http://localhost:8089/") | |
begin | |
unless http | |
puts "Opening TCP connection..." | |
http = Net::HTTP.start(uri.host, uri.port, read_timeout: 5) | |
end | |
puts "Executing HTTP request..." | |
res = http.request_get(uri.path) | |
puts res.code, res.body | |
return res | |
rescue Errno::ECONNREFUSED, Net::ReadTimeout => e | |
# timeout would throw ReadTimeout exception | |
if (retries+=1) <= 3 | |
puts "Timeout (#{e}), retrying in 1 second..." | |
sleep(retries) # Sleep more with each failure | |
retry # re-run the code!! | |
else | |
raise # All retries failed, raise the `last` seen exception | |
end | |
ensure | |
if http | |
puts "Closing the TCP connection..." | |
http.finish | |
end | |
end | |
end | |
def handle_backend_response(arg1, arg2) | |
res = get_server_connection(arg1, arg2) | |
unless res.nil? # did we get a response? | |
puts res.code, res.body | |
if res.code == "200" | |
return get_body_from_response(res.body) | |
end | |
if res.code == "404" | |
# handle 404 as you wish | |
return nil | |
else | |
puts "service unavailable" | |
return nil | |
end | |
end | |
end |
The code has the following logic:
- Try to establish a connection with the server.
- The request has a timeout and connection refused exceptions.
- If retries fail, code raise the last seen exception.
- Each retry has increased timeout.
Written with StackEdit.