Skip to content

Commit

Permalink
Merge pull request #131 from Shopify/handle-timeout-due-to-starvation
Browse files Browse the repository at this point in the history
Handle timeout due to pool exhaustion
  • Loading branch information
tenderlove authored Dec 5, 2024
2 parents 431c024 + 6665d26 commit 234f3b2
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 36 deletions.
6 changes: 6 additions & 0 deletions History.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
=== 4.0.6 / 2024-12-04

Bug fixes:

* Allow ConnectionPool exceptions from checkout to bubble up to caller.

=== 4.0.5 / 2024-12-04

Bug fixes:
Expand Down
74 changes: 38 additions & 36 deletions lib/net/http/persistent.rb
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ class Net::HTTP::Persistent
##
# The version of Net::HTTP::Persistent you are using

VERSION = '4.0.5'
VERSION = '4.0.6'

##
# Error class for errors raised by Net::HTTP::Persistent. Various
Expand Down Expand Up @@ -630,47 +630,49 @@ def connection_for uri

connection = @pool.checkout net_http_args

http = connection.http
begin
http = connection.http

connection.ressl @ssl_generation if
connection.ssl_generation != @ssl_generation
connection.ressl @ssl_generation if
connection.ssl_generation != @ssl_generation

if not http.started? then
ssl http if use_ssl
start http
elsif expired? connection then
reset connection
end
if not http.started? then
ssl http if use_ssl
start http
elsif expired? connection then
reset connection
end

http.keep_alive_timeout = @idle_timeout if @idle_timeout
http.max_retries = @max_retries if http.respond_to?(:max_retries=)
http.read_timeout = @read_timeout if @read_timeout
http.write_timeout = @write_timeout if
@write_timeout && http.respond_to?(:write_timeout=)
http.keep_alive_timeout = @idle_timeout if @idle_timeout
http.max_retries = @max_retries if http.respond_to?(:max_retries=)
http.read_timeout = @read_timeout if @read_timeout
http.write_timeout = @write_timeout if
@write_timeout && http.respond_to?(:write_timeout=)

return yield connection
rescue Errno::ECONNREFUSED
if http.proxy?
address = http.proxy_address
port = http.proxy_port
else
address = http.address
port = http.port
end

return yield connection
rescue Errno::ECONNREFUSED
if http.proxy?
address = http.proxy_address
port = http.proxy_port
else
address = http.address
port = http.port
end
raise Error, "connection refused: #{address}:#{port}"
rescue Errno::EHOSTDOWN
if http.proxy?
address = http.proxy_address
port = http.proxy_port
else
address = http.address
port = http.port
end

raise Error, "connection refused: #{address}:#{port}"
rescue Errno::EHOSTDOWN
if http.proxy?
address = http.proxy_address
port = http.proxy_port
else
address = http.address
port = http.port
raise Error, "host down: #{address}:#{port}"
ensure
@pool.checkin net_http_args
end

raise Error, "host down: #{address}:#{port}"
ensure
@pool.checkin net_http_args
end

##
Expand Down
10 changes: 10 additions & 0 deletions test/test_net_http_persistent.rb
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,16 @@ def test_connection_for
assert_same used, stored
end

def test_connection_for_exhaustion
@http = Net::HTTP::Persistent.new pool_size: 0

assert_raises Timeout::Error do
@http.connection_for @uri do |c|
assert_same nil, c
end
end
end

def test_connection_for_cached
cached = basic_connection
cached.http.start
Expand Down

0 comments on commit 234f3b2

Please sign in to comment.