diff options
author | Terence Lee <hone02@gmail.com> | 2012-09-14 22:29:50 +0900 |
---|---|---|
committer | Terence Lee <hone02@gmail.com> | 2012-09-15 00:46:25 +0900 |
commit | 337d20df3037807f2f76983ff7927cc70706a05c (patch) | |
tree | 813e47e0ab09c00cd6c9a94e2338b6fb069ad517 | |
parent | 9afd8849f50957a06f10498caa556d076a55f680 (diff) | |
download | bundler-337d20df3037807f2f76983ff7927cc70706a05c.tar.gz |
have a timeout around the gemcutter API endpoint
The API endpoint can sometimes hang and not return a response but open a
connection. Bundler before would just hang for a long time. This adds a
reasonable timeout, since the point of the API is to speed up the
install process. If the API takes too long, we should fall back on
cloudfront and the modern index, since that will likely be faster.
-rw-r--r-- | lib/bundler/fetcher.rb | 5 | ||||
-rw-r--r-- | spec/install/gems/dependency_api_spec.rb | 11 | ||||
-rw-r--r-- | spec/support/artifice/endpoint_timeout.rb | 13 |
3 files changed, 28 insertions, 1 deletions
diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb index 7bc8bf76cb..6f9cce8fb1 100644 --- a/lib/bundler/fetcher.rb +++ b/lib/bundler/fetcher.rb @@ -5,6 +5,8 @@ module Bundler # Handles all the fetching with the rubygems server class Fetcher REDIRECT_LIMIT = 5 + # how long to wait for each gemcutter API call + API_TIMEOUT = 10 attr_reader :has_api @@ -142,7 +144,8 @@ module Bundler begin Bundler.ui.debug "Fetching from: #{uri}" - response = @@connection.request(uri) + response = nil + Timeout.timeout(API_TIMEOUT) { response = @@connection.request(uri) } rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, SocketError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::HTTP::Persistent::Error, Net::ProtocolError => e diff --git a/spec/install/gems/dependency_api_spec.rb b/spec/install/gems/dependency_api_spec.rb index 1a94917f45..867674abf5 100644 --- a/spec/install/gems/dependency_api_spec.rb +++ b/spec/install/gems/dependency_api_spec.rb @@ -158,6 +158,17 @@ describe "gemcutter's dependency API" do out.should match(/Too many redirects/) end + it "timeouts when Gemcutter API takes too long to respond" do + gemfile <<-G + source "#{source_uri}" + gem "rack" + G + + bundle :install, :artifice => "endpoint_timeout" + out.should include("\nFetching full source index from #{source_uri}") + should_be_installed "rack 1.0.0" + end + context "when --full-index is specified" do it "should use the modern index for install" do gemfile <<-G diff --git a/spec/support/artifice/endpoint_timeout.rb b/spec/support/artifice/endpoint_timeout.rb new file mode 100644 index 0000000000..da682204c4 --- /dev/null +++ b/spec/support/artifice/endpoint_timeout.rb @@ -0,0 +1,13 @@ +require File.expand_path("../endpoint_fallback", __FILE__) + +Artifice.deactivate + +class EndpointTimeout < EndpointFallback + SLEEP_TIMEOUT = 15 + + get "/api/v1/dependencies" do + sleep(SLEEP_TIMEOUT) + end +end + +Artifice.activate_with(EndpointTimeout) |