From 105910429d5873dce677ef32eef5f705e0625d86 Mon Sep 17 00:00:00 2001 From: Cheah Chu Yeow Date: Sun, 13 Apr 2008 14:40:30 +0800 Subject: Introduce ActiveResource::Base.timeout. This allows a timeout to be set on the internal Net::HTTP instance ARes uses (default is 60 seconds). Setting a low timeout allows ARes clients to fail-fast in the event of a unresponsive/crashed server, rather than cause cascading failures in your application. Signed-off-by: Michael Koziarski --- activeresource/lib/active_resource/base.rb | 38 +++++++++++++++++++++++- activeresource/lib/active_resource/connection.rb | 12 ++++++-- 2 files changed, 46 insertions(+), 4 deletions(-) (limited to 'activeresource/lib') diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb index cd53c5d771..4072b9494d 100644 --- a/activeresource/lib/active_resource/base.rb +++ b/activeresource/lib/active_resource/base.rb @@ -166,6 +166,26 @@ module ActiveResource # # Learn more about Active Resource's validation features in the ActiveResource::Validations documentation. # + # === Timeouts + # + # Active Resource relies on HTTP to access RESTful APIs and as such is inherently susceptible to slow or + # unresponsive servers. In such cases, your Active Resource method calls could timeout. You can control the + # amount of time before Active Resource times out with the +timeout+ variable. + # + # class Person < ActiveResource::Base + # self.site = "http://api.people.com:3000/" + # self.timeout = 5 + # end + # + # This sets the +timeout+ to 5 seconds. You can adjust the timeout to a value suitable for the RESTful API + # you are accessing. It is recommended to set this to a reasonably low value to allow your Active Resource + # clients (especially if you are using Active Resource in a Rails application) to fail-fast (see + # http://en.wikipedia.org/wiki/Fail-fast) rather than cause cascading failures that could incapacitate your + # server. + # + # Internally, Active Resource relies on Ruby's Net::HTTP library to make HTTP requests. Setting +timeout+ + # sets the read_timeout of the internal Net::HTTP instance to the same value. The default + # read_timeout is 60 seconds on most Ruby implementations. class Base # The logger for diagnosing and tracing Active Resource calls. cattr_accessor :logger @@ -257,12 +277,27 @@ module ActiveResource write_inheritable_attribute("format", format) connection.format = format if site end - + # Returns the current format, default is ActiveResource::Formats::XmlFormat def format # :nodoc: read_inheritable_attribute("format") || ActiveResource::Formats[:xml] end + # Sets the number of seconds after which requests to the REST API should time out. + def timeout=(timeout) + @connection = nil + @timeout = timeout + end + + # Gets tthe number of seconds after which requests to the REST API should time out. + def timeout + if defined?(@timeout) + @timeout + elsif superclass != Object && superclass.timeout + superclass.timeout + end + end + # An instance of ActiveResource::Connection that is the base connection to the remote service. # The +refresh+ parameter toggles whether or not the connection is refreshed at every request # or not (defaults to false). @@ -271,6 +306,7 @@ module ActiveResource @connection = Connection.new(site, format) if refresh || @connection.nil? @connection.user = user if user @connection.password = password if password + @connection.timeout = timeout if timeout @connection else superclass.connection diff --git a/activeresource/lib/active_resource/connection.rb b/activeresource/lib/active_resource/connection.rb index c8cee7aaa3..3b61009f43 100644 --- a/activeresource/lib/active_resource/connection.rb +++ b/activeresource/lib/active_resource/connection.rb @@ -55,7 +55,7 @@ module ActiveResource # This class is used by ActiveResource::Base to interface with REST # services. class Connection - attr_reader :site, :user, :password + attr_reader :site, :user, :password, :timeout attr_accessor :format class << self @@ -90,6 +90,11 @@ module ActiveResource @password = password end + # Set the number of seconds after which HTTP requests to the remote service should time out. + def timeout=(timeout) + @timeout = timeout + end + # Execute a GET request. # Used to get (find) resources. def get(path, headers = {}) @@ -167,18 +172,19 @@ module ActiveResource http = Net::HTTP.new(@site.host, @site.port) http.use_ssl = @site.is_a?(URI::HTTPS) http.verify_mode = OpenSSL::SSL::VERIFY_NONE if http.use_ssl + http.read_timeout = @timeout if @timeout # If timeout is not set, the default Net::HTTP timeout (60s) is used. http end def default_header @default_header ||= { 'Content-Type' => format.mime_type } end - + # Builds headers for request to remote service. def build_request_headers(headers) authorization_header.update(default_header).update(headers) end - + # Sets authorization header def authorization_header (@user || @password ? { 'Authorization' => 'Basic ' + ["#{@user}:#{ @password}"].pack('m').delete("\r\n") } : {}) -- cgit v1.2.3