summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTerence Lee <hone02@gmail.com>2012-09-14 22:29:50 +0900
committerTerence Lee <hone02@gmail.com>2012-09-15 00:46:25 +0900
commit337d20df3037807f2f76983ff7927cc70706a05c (patch)
tree813e47e0ab09c00cd6c9a94e2338b6fb069ad517
parent9afd8849f50957a06f10498caa556d076a55f680 (diff)
downloadbundler-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.rb5
-rw-r--r--spec/install/gems/dependency_api_spec.rb11
-rw-r--r--spec/support/artifice/endpoint_timeout.rb13
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)