An unresponsive service can be worse than a down one. It can tie up your entire system if not handled properly. All network requests should have a timeout.
Here’s how to add timeouts for popular Ruby gems. All have been tested. You should avoid Ruby’s Timeout
module. The default is no timeout, unless otherwise specified. Enjoy!
- connect (or open) - time to open the connection
- read (or receive) - time to receive data after connected
- write (or send) - time to send data after connected
- checkout - time to checkout a connection from the pool
- statement - time to execute a database statement
For many apps, the single most important thing to do (if you use a relational database)
Data Stores
- activerecord
- bunny
- cassandra-driver
- connection_pool
- couchrest
- dalli
- drill-sergeant
- elasticsearch
- hiredis
- influxdb
- mongo
- mongoid
- mysql2
- neo4j
- pg
- presto-client
- redis
- riddle
- rsolr
- ruby-druid
- ruby-kafka
- searchkick
- sequel
HTTP Clients
- curb
- em-http-client
- excon
- faraday
- http
- httparty
- httpclient
- httpi
- net/http
- open-uri
- patron
- rest-client
- typhoeus
- unirest
Web Servers
Rack Middleware
3rd Party Services
- airrecord
- airtable
- algoliasearch
- aws-sdk
- azure
- bitly
- boxr
- checkr-official
- clearbit
- coinbase
- dogapi
- dropbox-sdk
- droplet_kit
- fastly
- firebase
- flickraw
- gibbon
- github_api
- google-api-client
- google-cloud
- hipchat
- intercom
- koala
- octokit
- pinterest-api
- pwned
- restforce
- rspotify
- shopify_api
- sift
- slack-notifier
- slack-ruby-client
- smartystreets_ruby_sdk
- soda-ruby
- soundcloud
- stripe
- tamber
- twilio-ruby
- yt
- zendesk_api
Other
- acme-client
- actionmailer
- activemerchant
- activeresource
- active_shipping
- carrot2
- docker-api
- fastimage
- geocoder
- graphql-client
- grpc
- kubeclient
- mechanize
- nats-pure
- nestful
- net-dns
- net/ftp
- net-ldap
- net-ntp
- net-scp
- net-sftp
- net/smtp
- net-ssh
- net-telnet
- omniauth-oauth2
- reversed
- savon
- socket
- spidr
- spyke
- stomp
- vault
- whois
- zk
- zookeeper
Prevent single queries from taking up all of your database’s resources.
If you use Rails, add to your config/database.yml
production:
variables:
statement_timeout: 5s # or ms, min, etc
or set it on your database role
ALTER ROLE myuser SET statement_timeout = '5s';
Test with
SELECT pg_sleep(6);
To set for a single transaction, use
BEGIN;
SET LOCAL statement_timeout = '5s';
...
COMMIT;
For migrations, you likely want to set a longer statement timeout. You can do this with
production:
variables:
statement_timeout: <%= ENV["STATEMENT_TIMEOUT"] || "5s" %>
And use
STATEMENT_TIMEOUT=90s rails db:migrate
Note: Requires MySQL 5.7.8 or higher
If you use Rails, add to your config/database.yml
production:
variables:
max_execution_time: 5000 # ms
or set it directly on each connection
SET SESSION max_execution_time = 5000;
Test with
SELECT 1 FROM information_schema.tables WHERE sleep(6);
To set for a single statement, use an optimizer hint
SELECT /*+ MAX_EXECUTION_TIME(5000) */ ...
For migrations, you likely want to set a longer statement timeout. You can do this with
production:
variables:
max_execution_time: <%= ENV["MAX_EXECUTION_TIME"] || 5000 %>
And use
MAX_EXECUTION_TIME=90000 rails db:migrate
Note: Requires MariaDB 10.1.1 or higher
If you use Rails, add to your config/database.yml
production:
variables:
max_statement_time: 5 # sec
or set it directly on each connection
SET SESSION max_statement_time = 5;
Test with
SELECT 1 FROM information_schema.tables WHERE sleep(6);
As of MariaDB 10.1.2, you can set single statement timeouts with
SET STATEMENT max_statement_time=5 FOR
SELECT ...
For migrations, you likely want to set a longer statement timeout. You can do this with
production:
variables:
max_statement_time: <%= ENV['MAX_STATEMENT_TIME'] || 5 %>
And use
MAX_STATEMENT_TIME=90 rails db:migrate
-
ActiveRecord::Base.establish_connection(connect_timeout: 1, checkout_timeout: 1, ...)
or in
config/database.yml
production: connect_timeout: 1 checkout_timeout: 1
Raises
PG::ConnectionBad
on connect and read timeoutsActiveRecord::ConnectionTimeoutError
on checkout timeout
See also PostgreSQL statement timeouts
-
ActiveRecord::Base.establish_connection(connect_timeout: 1, read_timeout: 1, write_timeout: 1, checkout_timeout: 1, ...)
or in
config/database.yml
production: connect_timeout: 1 read_timeout: 1 write_timeout: 1 checkout_timeout: 1
Raises
Mysql2::Error
on connect and read timeoutsActiveRecord::ConnectionTimeoutError
on checkout timeout
See also MySQL statement timeouts
Bunny.new(connection_timeout: 1, read_timeout: 1, ...)
Raises
Bunny::TCPConnectionFailedForAllHosts
on connect timeoutBunny::NetworkFailure
on read timeout
Cassandra.cluster(connect_timeout: 1, timeout: 1)
Default: 10s connect timeout, 12s read timeout
Raises
Cassandra::Errors::NoHostsAvailable
on connect timeoutCassandra::Errors::TimeoutError
on read timeout
ConnectionPool.new(timeout: 1) { ... }
Raises Timeout::Error
CouchRest.new(url, open_timeout: 1, read_timeout: 1, timeout: 1)
Raises
HTTPClient::ConnectTimeoutError
on connect timeoutHTTPClient::ReceiveTimeoutError
on read timeout
Dalli::Client.new(host, socket_timeout: 1, ...)
Default: 0.5s
Raises Dalli::RingError
Drill.new(url: url, open_timeout: 1, read_timeout: 1)
Default: 3s connect timeout, no read timeout
Raises
Net::OpenTimeout
on connect timeoutNet::ReadTimeout
on read timeout
Elasticsearch::Client.new(transport_options: {request: {timeout: 1}}, ...)
Raises
Faraday::ConnectionFailed
on connect timeoutFaraday::TimeoutError
on read timeout
conn = Hiredis::Connection.new
conn.timeout = 1_000_000 # microseconds
Raises
Errno::ETIMEDOUT
on connect timeoutErrno::EAGAIN
on read timeout
InfluxDB::Client.new(open_timeout: 1, read_timeout: 1)
Raises InfluxDB::ConnectionError
Mongo::Client.new([host], connect_timeout: 1, socket_timeout: 1, server_selection_timeout: 1, ...)
Raises Mongo::Error::NoServerAvailable
production:
clients:
default:
options:
connect_timeout: 1
socket_timeout: 1
server_selection_timeout: 1
Raises Mongo::Error::NoServerAvailable
Mysql2::Client.new(connect_timeout: 1, read_timeout: 1, write_timeout: 1, ...)
Raises Mysql2::Error
config.neo4j.session.options = {
faraday_configurator: lambda do |faraday|
faraday.adapter :typhoeus
faraday.options[:open_timeout] = 5
faraday.options[:timeout] = 65
end
}
Raises Faraday::TimeoutError
PG.connect(connect_timeout: 1, ...)
Raises PG::ConnectionBad
Presto::Client.new(http_open_timeout: 1, http_timeout: 1)
Raises
Faraday::ConnectionFailed
on connect timeoutFaraday::TimeoutError
on read timeout
Redis.new(connect_timeout: 1, timeout: 1, ...)
Default: 5s
Raises
Redis::CannotConnectError
on connect timeoutRedis::TimeoutError
on read timeout
client = Riddle::Client.new
client.timeout = 1
Raises Riddle::ResponseError
RSolr.connect(open_timeout: 1, read_timeout: 1)
Raises
RSolr::Error::ConnectionRefused
on connect timeoutRSolr::Error::Http
on read timeout
Not configurable at the moment
Default: 10s connect timeout, no read timeout
Kafka.new(connect_timeout: 1, socket_timeout: 1)
Raises Kafka::ConnectionError
Searchkick.timeout = 1
Searchkick.search_timeout = 1
Default: 10s
Raises same exceptions as elasticsearch
-
Sequel.connect(connect_timeout: 1, pool_timeout: 1, ...)
Sequel::DatabaseConnectionError
on connect and read timeoutsSequel::PoolTimeout
on checkout timeout
-
Sequel.connect(timeout: 1, read_timeout: 1, connect_timeout: 1, pool_timeout: 1, ...)
Raises
Sequel::DatabaseConnectionError
on connect and read timeoutsSequel::PoolTimeout
on checkout timeout
curl = Curl::Easy.new(url)
curl.connect_timeout = 1
curl.timeout = 1
curl.perform
Raises Curl::Err::TimeoutError
EventMachine.run do
http = EventMachine::HttpRequest.new(url, connect_timeout: 1, inactivity_timeout: 1).get
http.errback { http.error }
end
No exception is raised, but http.error
is set to Errno::ETIMEDOUT
in http.errback
.
Excon.get(url, connect_timeout: 1, read_timeout: 1, write_timeout: 1)
Raises Excon::Errors::Timeout
Faraday.get(url) do |req|
req.options.open_timeout = 1
req.options.timeout = 1
end
or
Faraday.new(url, request: {open_timeout: 1, timeout: 1}) do |faraday|
# ...
end
Raises
Faraday::ConnectionFailed
on connect timeoutFaraday::TimeoutError
on read timeout
HTTP.timeout(connect: 1, read: 1, write: 1).get(url)
Raises HTTP::TimeoutError
HTTParty.get(url, timeout: 1)
or
class Resource
include HTTParty
default_timeout 1
# or
open_timeout 1
read_timeout 1
write_timeout 1
end
Raises
Net::OpenTimeout
on connect timeoutNet::ReadTimeout
on read timeout
client = HTTPClient.new
client.connect_timeout = 1
client.receive_timeout = 1
client.send_timeout = 1
client.get(url)
Raises
HTTPClient::ConnectTimeoutError
on connect timeoutHTTPClient::ReceiveTimeoutError
on read timeout
HTTPI::Request.new(url: url, open_timeout: 1)
Raises same errors as underlying client
Net::HTTP.start(host, port, open_timeout: 1, read_timeout: 1, write_timeout: 1) do
# ...
end
or
http = Net::HTTP.new(host, port)
http.open_timeout = 1
http.read_timeout = 1
http.write_timeout = 1
Raises
Net::OpenTimeout
on connect timeoutNet::ReadTimeout
on read timeoutNet::WriteTimeout
on write timeout
Default: 60s connect timeout, 60s read timeout, 60s write timeout
Write timeout can be set in Ruby 2.6+. Read timeouts are retried once automatically for idempotent methods like GET
. In Ruby 2.5+, you can set the number of retries with http.max_retries = 1
.
open(url, open_timeout: 1, read_timeout: 1)
Raises
Net::OpenTimeout
on connect timeoutNet::ReadTimeout
on read timeout
sess = Patron::Session.new
sess.connect_timeout = 1
sess.timeout = 1
Raises Patron::TimeoutError
RestClient::Request.execute(method: :get, url: url, open_timeout: 1, read_timeout: 1)
# shorthand to set open_timeout = read_timeout = 1
RestClient::Request.execute(method: :get, url: url, timeout: 1)
Same options also work with RestClient::Resource
.
Raises
RestClient::Exceptions::OpenTimeout
on connect timeoutRestClient::Exceptions::ReadTimeout
on read timeout
Default: 60s connect timeout, 60s read timeout
response = Typhoeus.get(url, connecttimeout: 1, timeout: 1)
No exception is raised. Check for a timeout with
response.timed_out?
Unirest.timeout(1)
Connect timeout is not configurable
Default: 10s read timeout, no connect timeout
Raises RuntimeError
# config/puma.rb
worker_timeout 15
Default: 30s
This kills and respawns the worker process. Note that this is for the worker and not threads. This isn’t a request timeout either. Use Rack middleware for request timeouts.
# config/puma.rb
worker_shutdown_timeout 8
Default: 60s
This causes Puma to send a SIGKILL signal to a worker if it hasn’t shutdown within the specified time period after having received a SIGTERM signal.
# config/unicorn.rb
timeout 15
Default: 60s
This kills and respawns the worker process.
It’s recommended to use this in addition to Rack middleware.
use Rack::Timeout,
service_timeout: 15, # ENV["RACK_TIMEOUT_SERVICE_TIMEOUT"]
wait_timeout: 30, # ENV["RACK_TIMEOUT_WAIT_TIMEOUT"]
wait_overtime: 60, # ENV["RACK_TIMEOUT_WAIT_OVERTIME"]
service_past_wait: false # ENV["RACK_TIMEOUT_SERVICE_PAST_WAIT"]
Default: 15s service timeout, 30s wait timeout
Raises Rack::Timeout::RequestTimeoutError
or Rack::Timeout::RequestExpiryError
Note: The approach used by Rack::Timeout can leave your application in an inconsistent state, as described here
Slowpoke.timeout = 5
Default: 15s
Raises same exceptions as rack-timeout
Not configurable at the moment, and no timeout by default
Airtable::Resource.default_timeout 1
Raises
Net::OpenTimeout
on connect timeoutNet::ReadTimeout
on read timeout
Algolia.init(
connect_timeout: 1,
send_timeout: 1,
receive_timeout: 1,
batch_timeout: 1,
search_timeout: 1
)
Raises Algolia::AlgoliaProtocolError
Aws.config = {
http_open_timeout: 1,
http_read_timeout: 1
}
Or with a client
Aws::S3::Client.new(
http_open_timeout: 1,
http_read_timeout: 1
)
Raises Seahorse::Client::NetworkingError
Not configurable at the moment, and no timeout by default
Bitly.new(username, api_key, timeout)
Raises BitlyTimeout
Not configurable at the moment, and no timeout by default
Default: 30s connect timeout, 60s read timeout
Not configurable at the moment
Clearbit::Resource.options = {timeout: 1}
Raises Nestful::TimeoutError
Not configurable at the moment
timeout = 1
Dogapi::Client.new(api_key, nil, nil, nil, false, timeout)
Raises
Net::OpenTimeout
on connect timeoutNet::ReadTimeout
on read timeout
Not configurable at the moment
Default: No connect timeout, 600s read timeout
DropletKit::Client.new(open_timeout: 1, timeout: 1)
Raises
Faraday::ConnectionFailed
on connect timeoutFaraday::TimeoutError
on read timeout
Not configurable at the moment, and no timeout by default
firebase = Firebase::Client.new(url)
firebase.request.connect_timeout = 1
firebase.request.receive_timeout = 1
firebase.request.send_timeout = 1
Raises
HTTPClient::ConnectTimeoutError
on connect timeoutHTTPClient::ReceiveTimeoutError
on read timeout
Not configurable at the moment
Gibbon::Request.new(open_timeout: 1, timeout: 1, ...)
Raises Gibbon::MailChimpError
Github.new(connection_options: {request: {open_timeout: 1, timeout: 1}})
Raises
Faraday::ConnectionFailed
on connect timeoutFaraday::TimeoutError
on read timeout
client = Google::Apis::DriveV2::DriveService.new
client.client_options.open_timeout_sec = 1
client.client_options.read_timeout_sec = 1
Raise Google::Apis::TransmissionError
Google::Cloud::Storage.new(timeout: 1)
Raises Google::Cloud::Error
[HipChat::Client, HipChat::Room, HipChat::User].each { |c| c.default_timeout(1) }
Raises
Net::OpenTimeout
on connect timeoutNet::ReadTimeout
on read timeout
client = Intercom::Client.new(token: token)
client.options(Intercom::Client.set_timeouts(open_timeout: 1, read_timeout: 1))
Raises
Intercom::ServiceConnectionError
on connect timeout (inherits fromIntercom::IntercomError
)Intercom::ServiceUnavailableError
on read timeout (inherits fromIntercom::IntercomError
)
Koala.http_service.http_options = {request: {open_timeout: 1, timeout: 1}}
Raises
Faraday::ConnectionFailed
on connect timeoutFaraday::TimeoutError
on read timeout
Not configurable at the moment, and no timeout by default.
Octokit::Client.new(connection_options: {request: {open_timeout: 1, timeout: 1}})
Raises
Faraday::ConnectionFailed
on connect timeoutFaraday::TimeoutError
on read timeout
Pinterest::Client.new(access_token, request: {open_timeout: 1, timeout: 1})
Raises
Faraday::ConnectionFailed
on connect timeoutFaraday::TimeoutError
on read timeout
Pwned::Password.new("password", open_timeout: 1, read_timeout: 1)
Raises Pwned::TimeoutError
Restforce.new(timeout: 1)
Raises
Faraday::ConnectionFailed
on connect timeoutFaraday::TimeoutError
on read timeout
Not configurable at the moment, and no timeout by default
ShopifyAPI::Base.timeout = 1
Raises ActiveResource::TimeoutError
Sift::Client.new(timeout: 1)
Default: 2s
Raises
Net::OpenTimeout
on connect timeoutNet::ReadTimeout
on read timeout
Slack::Notifier.new(webhook_url, http_options: {open_timeout: 1, read_timeout: 1})
Raises
Net::OpenTimeout
on connect timeoutNet::ReadTimeout
on read timeout
Slack::Web::Client.new(open_timeout: 1, timeout: 1)
Raises
Faraday::ConnectionFailed
on connect timeoutFaraday::TimeoutError
on read timeout
SmartyStreets::ClientBuilder.new(credentials).with_max_timeout(1)
Connect timeout is not configurable at the moment
Raises Net::ReadTimeout
on read timeout
SODA::Client.new(timeout: 1)
Connect timeout is not configurable at the moment
Raises Net::ReadTimeout
on read timeout
Not configurable at the moment, and no timeout by default
Stripe.open_timeout = 1
Stripe.read_timeout = 1
Default: 30s connect timeout, 80s read timeout
Raises Stripe::APIConnectionError
Tamber.open_timeout = 1
Tamber.read_timeout = 1
Raises Tamber::NetworkError
http_client = Twilio::HTTP::Client.new(timeout: 1)
Twilio::REST::Client.new(account_sid, auth_token, nil, nil, http_client)
Default: 30s
Raises
Faraday::ConnectionFailed
on connect timeoutFaraday::TimeoutError
on read timeout
Twitter::REST::Client.new do |config|
config.timeouts = {connect: 1, read: 1, write: 1}
end
Raises HTTP::TimeoutError
Not configurable at the moment, and no timeout by default
ZendeskAPI::Client.new do |config|
config.client_options = {request: {open_timeout: 1, timeout: 1}}
end
Default: 10s connect timeout, no read timeout
Raises ZendeskAPI::Error::NetworkError
Acme::Client.new(connection_options: {request: {open_timeout: 1, timeout: 1}})
Raises
Faraday::ConnectionFailed
on connect timeoutFaraday::TimeoutError
on read timeout
ActionMailer::Base.smtp_settings = {
open_timeout: 1,
read_timeout: 1
}
Raises
Net::OpenTimeout
on connect timeoutNet::ReadTimeout
on read timeout
ActiveMerchant::Billing::Gateway.open_timeout = 1
ActiveMerchant::Billing::Gateway.read_timeout = 1
Default: 60s
Raises ActiveMerchant::ConnectionError
class Person < ActiveResource::Base
self.open_timeout = 1
self.read_timeout = 1
end
Raises ActiveResource::TimeoutError
client = ActiveShipping::USPS.new(login: "developer-key")
client.open_timeout = 1
client.read_timeout = 1
Default: 2s connect timeout, 10s read timeout
Raises ActiveUtils::ConnectionError
Carrot2.new(open_timeout: 1, read_timeout: 1)
Raises
Net::OpenTimeout
on connect timeoutNet::ReadTimeout
on read timeout
Docker.options = {
read_timeout: 1
}
Connect timeout not configurable
Raises Docker::Error::TimeoutError
FastImage.size(url, timeout: 1)
Returns nil
on timeouts
If you pass raise_on_failure: true
, raises FastImage::ImageFetchFailure
Geocoder.configure(timeout: 1, ...)
No exception is raised by default. To raise exceptions, use
Geocoder.configure(timeout: 1, always_raise: :all, ...)
Raises Geocoder::LookupTimeout
GraphQL::Client::HTTP.new(url) do
def connection
conn = super
conn.open_timeout = 1
conn.read_timeout = 1
conn
end
end
Raises
Net::OpenTimeout
on connect timeoutNet::ReadTimeout
on read timeout
RouteGuide::Stub.new(addr, :this_channel_is_insecure, timeout: 1)
Raises GRPC::DeadlineExceeded
Kubeclient::Client.new(url, timeouts: {open: 1, read: 1})
Raises KubeException
Default: 60s connect timeout, 60s read timeout
Mail.defaults do
delivery_method :smtp, open_timeout: 1, read_timeout: 1
end
Raises
Net::OpenTimeout
on connect timeoutNet::ReadTimeout
on read timeout
agent = Mechanize.new
agent.open_timeout = 1
agent.read_timeout = 1
Raises
Net::OpenTimeout
on connect timeoutNet::HTTP::Persistent::Error
on read timeout
nats = NATS::IO::Client.new
nats.connect(connect_timeout: 1)
Raises NATS::IO::SocketTimeoutError
Nestful::Request.new(url, timeout: 1)
or
class Resource < Nestful::Resource
options timeout: 1
end
Raises Nestful::TimeoutError
Net::DNS::Resolver.new(udp_timeout: 1)
Default: 5s
Raises Net::DNS::Resolver::NoResponseError
Net::FTP.new(host, open_timeout: 1, read_timeout: 1)
Raises
Net::OpenTimeout
on connect timeoutNet::ReadTimeout
on read timeout
Net::LDAP.new(host: host, connect_timeout: 1)
Read timeout not configurable at the moment
Default: 5s connect timeout, no read timeout
Raises Net::LDAP::Error
timeout = 1
Net::NTP.get(host, port, timeout)
Raises Timeout::Error
Net::SCP.start(host, user, timeout: 1)
Raises Net::SSH::ConnectionTimeout
Net::SFTP.start(host, user, timeout: 1)
Raises Net::SSH::ConnectionTimeout
smtp = Net::SMTP.new(host, 25)
smtp.open_timeout = 1
smtp.read_timeout = 1
Raises
Net::OpenTimeout
on connect timeoutNet::ReadTimeout
on read timeout
Net::SSH.start(host, user, timeout: 1)
Raises Net::SSH::ConnectionTimeout
Net::Telnet::new("Host" => host, "Timeout" => 1)
Raises
Net::OpenTimeout
on connect timeoutNet::ReadTimeout
on read timeout
Not configurable at the moment, and no timeout by default
Reversed.lookup("8.8.8.8", timeout: 1)
Returns nil
on timeouts
Savon.client(wsdl: url, open_timeout: 1, read_timeout: 1)
Raises
HTTPClient::ConnectTimeoutError
on connect timeoutHTTPClient::ReceiveTimeoutError
on read timeout
Socket.tcp(host, 80, connect_timeout: 1) do |sock|
# ...
end
Raises Errno::ETIMEDOUT
Spidr.open_timeout = 1
Spidr.read_timeout = 1
No exception is raised. Check for failures with
agent = Spidr.site(url)
agent.failures
Spyke::Base.connection = Faraday.new(url: url) do |c|
c.adapter Faraday.default_adapter
c.options[:open_timeout] = 1
c.options[:timeout] = 1
end
Raises Spyke::ConnectionError
Stomp::Client.new(start_timeout: 1, connect_timeout: 1, connread_timeout: 1, parse_timeout: 1)
Raises
Stomp::Error::StartTimeoutException
on connect timeoutStomp::Error::ReceiveTimeout
on read timeout
Vault.configure do |config|
config.timeout = 1
# or more granular
config.ssl_timeout = 1
config.open_timeout = 1
config.read_timeout = 1
end
Raises Vault::HTTPConnectionError
Whois::Client.new(timeout: 1)
Default: 10s
Raises Timeout::Error
Not configurable at the moment
Default: 30s
Raises Zookeeper::Exceptions::ContinuationTimeoutError
Not configurable at the moment
Default: 30s
Raises Zookeeper::Exceptions::ContinuationTimeoutError
Let us know. Even better, create a pull request for it.
Take advantage of inheritance. Instead of
rescue Net::OpenTimeout, Net::ReadTimeout
you can do
rescue Timeout::Error
Use
Timeout::Error
for bothNet::OpenTimeout
andNet::ReadTimeout
Faraday::ClientError
for bothFaraday::ConnectionFailed
andFaraday::TimeoutError
HTTPClient::TimeoutError
for bothHTTPClient::ConnectTimeoutError
andHTTPClient::ReceiveTimeoutError
Redis::BaseConnectionError
for bothRedis::CannotConnectError
andRedis::TimeoutError
Rack::Timeout::Error
for bothRack::Timeout::RequestTimeoutError
andRack::Timeout::RequestExpiryError
RestClient::Exceptions::Timeout
for bothRestClient::Exceptions::OpenTimeout
andRestClient::Exceptions::ReadTimeout
Adding timeouts to existing services can be a daunting task, but there’s a low risk way to do it.
- Select a timeout - say 5 seconds
- Log instances exceeding the proposed timeout
- Fix them
- Add the timeout
- Repeat this process with a lower timeout, until your target timeout is achieved
git clone https://github.com/ankane/the-ultimate-guide-to-ruby-timeouts.git
cd the-ultimate-guide-to-ruby-timeouts
bundle install
node test/server.js
To run all tests, use:
bundle exec appraisal rake test
To run individual tests, use:
bundle exec appraisal faraday rake test
Because time is not going to go backwards, I think I better stop now. - Stephen Hawking
🕓