Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
ExternalResource
module ExternalResource
# Adds ability to use view helpers, like number_to_currency.
# e.g. @@view_context.number_to_currency( 2.48 )
@@view_context = ActionController::Base.new.view_context
# # Handles timeout and other issues for blocks requesting external resources.
# For example, when using nokogiri to scrape a site.
# Requires a block with the HTTPClient.get call or what-have-you
#
# @param [Hash] options Options for the timeout.
# @option options [Integer] timeout (20) Number of seconds to wait before it times out.
# @option options [String] attempts (10) Number of attempts before the resource is unreachable.
#
# @return [SystemTimer, False] SystemTimer if all goes well. Otherwise, returns false if it hits
# the retry limit.
#
# @todo This might be better in a more generally accessible place. I could see Controllers taking
# advantage of this.
#
def load_with_timeout( options = {} )
options = { :timeout => 20, :attempts => 10 }.merge!(options)
@attempts_remaining ||= options[:attempts]
begin
@attempts_remaining -= 1
output = SystemTimer.timeout_after( options[:timeout] ) do
yield
end
rescue Timeout::Error
tell "Timed out."
rescue => e
tell e
ensure
unless output
tell "#{@@view_context.pluralize( @attempts_remaining, "attempt" )} remaining."
if @attempts_remaining <= 0
total_attempts = @@view_context.pluralize( options[:attempts], "attempt" )
raise "Unable to load after #{total_attempts}."
else
sleep 0.5 and retry
end
end
end
end
end
@chuckbergeron
Copy link

You have a todo: "put this in a more accessible place, possibly for controllers".

Couldn't a controller access it if it's module ExternalResource;end; ?

@joshuapinter
Copy link
Author

joshuapinter commented Jan 19, 2012 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment