Methods
Public Class
Public Instance
Constants
POOL_TIMEOUT | = | 5 |
Public Class methods
new(options)
Sets up the connection pool with the given options
, which can be the following:
:max_connections |
the maximum number of connections held in the pool. |
:max_connections_per_origin |
the maximum number of connections held in the pool pointing to a given origin. |
:pool_timeout |
the number of seconds to wait for a connection to a given origin (before raising |
[show source]
# File lib/httpx/pool.rb 22 def initialize(options) 23 @max_connections = options.fetch(:max_connections, Float::INFINITY) 24 @max_connections_per_origin = options.fetch(:max_connections_per_origin, Float::INFINITY) 25 @pool_timeout = options.fetch(:pool_timeout, POOL_TIMEOUT) 26 @resolvers = Hash.new { |hs, resolver_type| hs[resolver_type] = [] } 27 @resolver_mtx = Thread::Mutex.new 28 @connections = [] 29 @connection_mtx = Thread::Mutex.new 30 @connections_counter = 0 31 @max_connections_cond = ConditionVariable.new 32 @origin_counters = Hash.new(0) 33 @origin_conds = Hash.new { |hs, orig| hs[orig] = ConditionVariable.new } 34 end
Public Instance methods
checkin_connection(connection)
[show source]
# File lib/httpx/pool.rb 90 def checkin_connection(connection) 91 return if connection.options.io 92 93 @connection_mtx.synchronize do 94 @connections << connection 95 96 @max_connections_cond.signal 97 @origin_conds[connection.origin.to_s].signal 98 end 99 end
checkin_resolver(resolver)
[show source]
# File lib/httpx/pool.rb 130 def checkin_resolver(resolver) 131 @resolver_mtx.synchronize do 132 resolvers = @resolvers[resolver.class] 133 134 resolver = resolver.multi 135 136 resolvers << resolver unless resolvers.include?(resolver) 137 end 138 end
checkout_connection(uri, options)
opens a connection to the IP reachable through uri
. Many hostnames are reachable through the same IP, so we try to maximize pipelining by opening as few connections as possible.
[show source]
# File lib/httpx/pool.rb 47 def checkout_connection(uri, options) 48 return checkout_new_connection(uri, options) if options.io 49 50 @connection_mtx.synchronize do 51 acquire_connection(uri, options) || begin 52 if @connections_counter == @max_connections 53 # this takes precedence over per-origin 54 @max_connections_cond.wait(@connection_mtx, @pool_timeout) 55 56 if (conn = acquire_connection(uri, options)) 57 return conn 58 end 59 60 if @connections_counter == @max_connections 61 # if no matching usable connection was found, the pool will make room and drop a closed connection. if none is found, 62 # this means that all of them are persistent or being used, so raise a timeout error. 63 conn = @connections.find { |c| c.state == :closed } 64 65 raise PoolTimeoutError.new(@pool_timeout, 66 "Timed out after #{@pool_timeout} seconds while waiting for a connection") unless conn 67 68 drop_connection(conn) 69 end 70 71 end 72 73 if @origin_counters[uri.origin] == @max_connections_per_origin 74 75 @origin_conds[uri.origin].wait(@connection_mtx, @pool_timeout) 76 77 return acquire_connection(uri, options) || 78 raise(PoolTimeoutError.new(@pool_timeout, 79 "Timed out after #{@pool_timeout} seconds while waiting for a connection to #{uri.origin}")) 80 end 81 82 @connections_counter += 1 83 @origin_counters[uri.origin] += 1 84 85 checkout_new_connection(uri, options) 86 end 87 end 88 end
checkout_mergeable_connection(connection)
[show source]
# File lib/httpx/pool.rb 101 def checkout_mergeable_connection(connection) 102 return if connection.options.io 103 104 @connection_mtx.synchronize do 105 idx = @connections.find_index do |ch| 106 ch != connection && ch.mergeable?(connection) 107 end 108 @connections.delete_at(idx) if idx 109 end 110 end
checkout_resolver(options)
[show source]
# File lib/httpx/pool.rb 116 def checkout_resolver(options) 117 resolver_type = options.resolver_class 118 resolver_type = Resolver.resolver_for(resolver_type, options) 119 120 @resolver_mtx.synchronize do 121 resolvers = @resolvers[resolver_type] 122 123 idx = resolvers.find_index do |res| 124 res.options == options 125 end 126 resolvers.delete_at(idx) if idx 127 end || checkout_new_resolver(resolver_type, options) 128 end
inspect()
:nocov:
[show source]
# File lib/httpx/pool.rb 141 def inspect 142 "#<#{self.class}:#{object_id} " \ 143 "@max_connections_per_origin=#{@max_connections_per_origin} " \ 144 "@pool_timeout=#{@pool_timeout} " \ 145 "@connections=#{@connections.size}>" 146 end
pop_connection()
connections returned by this function are not expected to return to the connection pool.
[show source]
# File lib/httpx/pool.rb 37 def pop_connection 38 @connection_mtx.synchronize do 39 drop_connection 40 end 41 end
reset_resolvers()
[show source]
# File lib/httpx/pool.rb 112 def reset_resolvers 113 @resolver_mtx.synchronize { @resolvers.clear } 114 end