DataHub Docs
DataHubLearnCommunity
  • ๐Ÿ‘‹Welcome to Figment Docs
  • ๐ŸšฉIntroduction
    • ๐Ÿš€Why Build on Web 3?
    • ๐Ÿ’ปWhat is DataHub?
  • ๐Ÿ“–DataHub Guides
    • ๐Ÿ“DataHub Products
      • Transaction Search API
      • Staking API
    • ๐ŸญDataHub Infrastructure
    • ๐ŸGet Started With DataHub
    • ๐ŸšจQuotas & Rate Limits
    • ๐Ÿ’กDashboard how-tos
      • Configuring CORS whitelist
  • ๐Ÿ“šNetwork Documentation
    • ๐Ÿ”ญNetwork Guide
    • ๐Ÿ…ฐ๏ธArbitrum
      • ๐ŸŽฎRPC & REST API
    • ๐Ÿ”๏ธAvalanche
      • ๐ŸŽฎRPC & REST API
        • Avalanche Indexer API
    • ๐Ÿ’ Binance Smart Chain
      • ๐ŸŽฎRPC & REST API
    • ๐Ÿ’ฐCelo
      • ๐Ÿ’ผCELO Wallet
      • ๐ŸŽฎRPC & REST API
    • โžฐCentrifuge
      • ๐ŸŽฎRPC & REST API
    • ๐ŸŒŒCosmos
      • ๐ŸŽฎRPC & REST API
      • ๐ŸŽŠEnriched APIs
        • Transaction Search
        • Rewards API
    • ๐Ÿ’ŽEthereum
      • ๐ŸŽฎRPC & REST API
    • ๐ŸงŠFantom
      • ๐ŸŽฎRPC & REST API
    • ๐ŸฆKusama
      • ๐ŸŽฎRPC & REST API
    • ๐Ÿ“ฑMina
      • ๐ŸŽฎRPC & REST API
        • Indexer API Documentation
        • Query Mina GraphQL API
    • ๐ŸŒˆNEAR
      • ๐ŸŽฎRPC & REST API
      • ๐ŸŽŠEnriched APIs
        • Indexer API
      • ๐Ÿ’ผNEAR Wallet
    • ๐Ÿ๏ธOasis
      • ๐ŸŽฎRPC & REST API
        • Oasis REST API
    • ๐ŸงชOsmosis
      • ๐ŸŽฎRPC & REST API
    • ๐ŸกPolkadot
      • ๐ŸŽฎRPC & REST API
      • ๐ŸŽŠEnriched APIs
        • Indexer API
        • Transaction Search
    • โ›ฝPolygon (Matic)
      • ๐ŸŽฎRPC & REST API
    • ๐Ÿ”‹Solana
      • ๐ŸŽฎRPC & REST API
    • ๐Ÿ“šExtra Guides
      • Blockchain Fundamentals
      • Docker Setup for Windows
      • Troubleshooting CORS Errors on DataHub
      • 5XX Retry Logic Best Practices
        • 5XX Retry Logic Best Practices - NodeJS
        • 5XX Retry Logic Best Practices - Python
        • 5XX Retry Logic Best Practices - Ruby
        • 5XX Retry Logic Best Practices - Go
      • Setting up a fresh JavaScript Project with dotenv
      • Getting started with dotenv and .env files
      • Rust Learning Resources
      • Setup Solana BPF Toolchain on Windows
      • Figment Learn Pathway Troubleshooting
  • ๐Ÿค”Other
    • ๐ŸงพGlossary
    • ๐Ÿ—ณ๏ธSupport
  • ๐Ÿ”—Terms & Conditions
    • Terms of Use
    • Terms & Conditions DataHub
    • Privacy Policy
    • Contributor Terms
Powered by GitBook
On this page
  • Method 1 ensure
  • Method 2

Was this helpful?

  1. Network Documentation
  2. Extra Guides
  3. 5XX Retry Logic Best Practices

5XX Retry Logic Best Practices - Ruby

Review best practices to deal with 5XX errors in Ruby

Method 1 ensure

The ensure keyword is used for ensuring that a block of code runs, even when an exception happens.

Weโ€™d like to ensure the TCP connection opened by Net::HTTP.start is closed, even if the request fails because it times out, for example. To do this, weโ€™ll first wrap our request in a begin/ensure/end block. The code in the ensure part will always run, even if an exception is raised in the preceding begin block.

require "net/http"

begin
  puts "Opening TCP connection..."
  http = Net::HTTP.start(uri.host, uri.port)
  puts "Sending HTTP request..."
  puts http.request_get(uri.path).body
ensure
  if http
    puts "Closing the TCP connection..."
    http.finish
  end
end

The retry keyword allows to retry a piece of code in a block. Combined with a rescue block, we can use it to try again if we fail to open the connection, or if the API takes too long to respond.

To do that, weโ€™ll add a read_timeout to the Net::HTTP.start call which sets the timeout to 10 seconds. If a response to our request hasnโ€™t come in by then, itโ€™ll raise a Net::ReadTimeout.

Weโ€™ll also match on Errno::ECONNREFUSED to handle the API being down completely, which would prevent us from opening the TCP connection. In that case, the http variable is nil.

The exception is rescued and retry is called to start the begin block again, which results in the code doing the same request until no timeout occurs. Weโ€™ll reuse the http object which holds the connection if it already exists.

require "net/http"

http = nil
uri = URI("http://localhost:4567/")

begin
  unless http
    puts "Opening TCP connection..."
    http = Net::HTTP.start(uri.host, uri.port, read_timeout: 10)
  end
  puts "Executing HTTP request..."
  puts http.request_get(uri.path).body
rescue Errno::ECONNREFUSED, Net::ReadTimeout => e
  puts "Timeout (#{e}), retrying in 1 second..."
  sleep(1)
  retry
ensure
  if http
    puts "Closing the TCP connection..."
    http.finish
  end
end

Now, our request will retry every second until no Net::ReadTimeout is raised.

Giving up: reraising exceptions using raise

Whenever a timeout happens, weโ€™ll increment the number and check if itโ€™s less than or equal to three, because weโ€™d like to retry three retries at most. If so, weโ€™ll retry. If not, weโ€™ll raise to reraise the last exception.

require "net/http"

http = nil
uri = URI("http://localhost:4567/")
retries = 0

begin
  unless http
    puts "Opening TCP connection..."
    http = Net::HTTP.start(uri.host, uri.port, read_timeout: 1)
  end
  puts "Executing HTTP request..."
  puts http.request_get(uri.path).body
rescue Errno::ECONNREFUSED, Net::ReadTimeout => e
  if (retries += 1) <= 3
    puts "Timeout (#{e}), retrying in #{retries} second(s)..."
    sleep(retries)
    retry
  else
    raise
  end
ensure
  if http
    puts 'Closing the TCP connection...'
    http.finish
  end
end

Method 2

When we are sending an HTTP request and would like to have 3 retries if it fails due to connection errors. We can do this by following the steps below:

require 'http'

def send_request(params)
  with_connection_retry { HTTP.post("http://example.com/resource", params: 
    params) }
end

def with_connection_retry
  retries = 0

  loop do
    yield
  rescue HTTP::ConnectionError => e
    retries += 1

    raise e if retries >= 3
  end
end

Another way to perform the same action is by using Ruby's native API instead of using loops:

def send_request(params)
  with_connection_retry { HTTP.post("http://example.com/resource", params: 
    params) }
end

def with_connection_retry
  retries ||= 0

  begin
    yield
  rescue HTTP::ConnectionError => e
    retries += 1
    raise e if retries >= 3
    retry
  end
end
Previous5XX Retry Logic Best Practices - PythonNext5XX Retry Logic Best Practices - Go

Last updated 3 years ago

Was this helpful?

By using the retries variable in the call to sleep, we can increase the wait time for every new attempt. Check out the source .

๐Ÿ“š
๐Ÿ“š
HERE