[ruby/rubygems] Update vendored version of connection_pool to 2.5.4

https://github.com/ruby/rubygems/commit/3f5330c9fc
This commit is contained in:
Hiroshi SHIBATA 2025-11-14 11:57:27 +09:00 committed by git
parent e68c0fc75b
commit 917fd39982
3 changed files with 77 additions and 30 deletions

View File

@ -39,7 +39,7 @@ end
# - :auto_reload_after_fork - automatically drop all connections after fork, defaults to true
#
class Bundler::ConnectionPool
DEFAULTS = {size: 5, timeout: 5, auto_reload_after_fork: true}
DEFAULTS = {size: 5, timeout: 5, auto_reload_after_fork: true}.freeze
def self.wrap(options, &block)
Wrapper.new(options, &block)
@ -99,7 +99,8 @@ class Bundler::ConnectionPool
@available = TimedStack.new(@size, &block)
@key = :"pool-#{@available.object_id}"
@key_count = :"pool-#{@available.object_id}-count"
INSTANCES[self] = self if INSTANCES
@discard_key = :"pool-#{@available.object_id}-discard"
INSTANCES[self] = self if @auto_reload_after_fork && INSTANCES
end
def with(options = {})
@ -116,20 +117,65 @@ class Bundler::ConnectionPool
end
alias_method :then, :with
##
# Marks the current thread's checked-out connection for discard.
#
# When a connection is marked for discard, it will not be returned to the pool
# when checked in. Instead, the connection will be discarded.
# This is useful when a connection has become invalid or corrupted
# and should not be reused.
#
# Takes an optional block that will be called with the connection to be discarded.
# The block should perform any necessary clean-up on the connection.
#
# @yield [conn]
# @yieldparam conn [Object] The connection to be discarded.
# @yieldreturn [void]
#
#
# Note: This only affects the connection currently checked out by the calling thread.
# The connection will be discarded when +checkin+ is called.
#
# @return [void]
#
# @example
# pool.with do |conn|
# begin
# conn.execute("SELECT 1")
# rescue SomeConnectionError
# pool.discard_current_connection # Mark connection as bad
# raise
# end
# end
def discard_current_connection(&block)
::Thread.current[@discard_key] = block || proc { |conn| conn }
end
def checkout(options = {})
if ::Thread.current[@key]
::Thread.current[@key_count] += 1
::Thread.current[@key]
else
::Thread.current[@key_count] = 1
::Thread.current[@key] = @available.pop(options[:timeout] || @timeout)
::Thread.current[@key] = @available.pop(options[:timeout] || @timeout, options)
end
end
def checkin(force: false)
if ::Thread.current[@key]
if ::Thread.current[@key_count] == 1 || force
@available.push(::Thread.current[@key])
if ::Thread.current[@discard_key]
begin
@available.decrement_created
::Thread.current[@discard_key].call(::Thread.current[@key])
rescue
nil
ensure
::Thread.current[@discard_key] = nil
end
else
@available.push(::Thread.current[@key])
end
::Thread.current[@key] = nil
::Thread.current[@key_count] = nil
else
@ -146,7 +192,6 @@ class Bundler::ConnectionPool
# Shuts down the Bundler::ConnectionPool by passing each connection to +block+ and
# then removing it from the pool. Attempting to checkout a connection after
# shutdown will raise +Bundler::ConnectionPool::PoolShuttingDownError+.
def shutdown(&block)
@available.shutdown(&block)
end
@ -155,7 +200,6 @@ class Bundler::ConnectionPool
# Reloads the Bundler::ConnectionPool by passing each connection to +block+ and then
# removing it the pool. Subsequent checkouts will create new connections as
# needed.
def reload(&block)
@available.shutdown(reload: true, &block)
end

View File

@ -1,8 +1,8 @@
##
# The TimedStack manages a pool of homogeneous connections (or any resource
# you wish to manage). Connections are created lazily up to a given maximum
# you wish to manage). Connections are created lazily up to a given maximum
# number.
#
# Examples:
#
# ts = TimedStack.new(1) { MyConnection.new }
@ -16,14 +16,12 @@
# conn = ts.pop
# ts.pop timeout: 5
# #=> raises Bundler::ConnectionPool::TimeoutError after 5 seconds
class Bundler::ConnectionPool::TimedStack
attr_reader :max
##
# Creates a new pool with +size+ connections that are created from the given
# +block+.
def initialize(size = 0, &block)
@create_block = block
@created = 0
@ -35,9 +33,8 @@ class Bundler::ConnectionPool::TimedStack
end
##
# Returns +obj+ to the stack. +options+ is ignored in TimedStack but may be
# Returns +obj+ to the stack. +options+ is ignored in TimedStack but may be
# used by subclasses that extend TimedStack.
def push(obj, options = {})
@mutex.synchronize do
if @shutdown_block
@ -53,14 +50,13 @@ class Bundler::ConnectionPool::TimedStack
alias_method :<<, :push
##
# Retrieves a connection from the stack. If a connection is available it is
# immediately returned. If no connection is available within the given
# Retrieves a connection from the stack. If a connection is available it is
# immediately returned. If no connection is available within the given
# timeout a Bundler::ConnectionPool::TimeoutError is raised.
#
# +:timeout+ is the only checked entry in +options+ and is preferred over
# the +timeout+ argument (which will be removed in a future release). Other
# the +timeout+ argument (which will be removed in a future release). Other
# options may be used by subclasses that extend TimedStack.
def pop(timeout = 0.5, options = {})
options, timeout = timeout, 0.5 if Hash === timeout
timeout = options.fetch :timeout, timeout
@ -69,7 +65,9 @@ class Bundler::ConnectionPool::TimedStack
@mutex.synchronize do
loop do
raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block
return fetch_connection(options) if connection_stored?(options)
if (conn = try_fetch_connection(options))
return conn
end
connection = try_create(options)
return connection if connection
@ -86,7 +84,6 @@ class Bundler::ConnectionPool::TimedStack
# removing it from the pool. Attempting to checkout a connection after
# shutdown will raise +Bundler::ConnectionPool::PoolShuttingDownError+ unless
# +:reload+ is +true+.
def shutdown(reload: false, &block)
raise ArgumentError, "shutdown must receive a block" unless block
@ -121,14 +118,12 @@ class Bundler::ConnectionPool::TimedStack
##
# Returns +true+ if there are no available connections.
def empty?
(@created - @que.length) >= @max
end
##
# The number of connections available on the stack.
def length
@max - @created + @que.length
end
@ -139,6 +134,12 @@ class Bundler::ConnectionPool::TimedStack
@que.length
end
##
# Reduce the created count
def decrement_created
@created -= 1 unless @created == 0
end
private
def current_time
@ -148,8 +149,17 @@ class Bundler::ConnectionPool::TimedStack
##
# This is an extension point for TimedStack and is called with a mutex.
#
# This method must returns true if a connection is available on the stack.
# This method must returns a connection from the stack if one exists. Allows
# subclasses with expensive match/search algorithms to avoid double-handling
# their stack.
def try_fetch_connection(options = nil)
connection_stored?(options) && fetch_connection(options)
end
##
# This is an extension point for TimedStack and is called with a mutex.
#
# This method must returns true if a connection is available on the stack.
def connection_stored?(options = nil)
!@que.empty?
end
@ -158,7 +168,6 @@ class Bundler::ConnectionPool::TimedStack
# This is an extension point for TimedStack and is called with a mutex.
#
# This method must return a connection from the stack.
def fetch_connection(options = nil)
@que.pop&.first
end
@ -167,10 +176,8 @@ class Bundler::ConnectionPool::TimedStack
# This is an extension point for TimedStack and is called with a mutex.
#
# This method must shut down all connections on the stack.
def shutdown_connections(options = nil)
while connection_stored?(options)
conn = fetch_connection(options)
while (conn = try_fetch_connection(options))
@created -= 1 unless @created == 0
@shutdown_block.call(conn)
end
@ -181,7 +188,6 @@ class Bundler::ConnectionPool::TimedStack
#
# This method returns the oldest idle connection if it has been idle for more than idle_seconds.
# This requires that the stack is kept in order of checked in time (oldest first).
def reserve_idle_connection(idle_seconds)
return unless idle_connections?(idle_seconds)
@ -194,7 +200,6 @@ class Bundler::ConnectionPool::TimedStack
# This is an extension point for TimedStack and is called with a mutex.
#
# Returns true if the first connection in the stack has been idle for more than idle_seconds
def idle_connections?(idle_seconds)
connection_stored? && (current_time - @que.first.last > idle_seconds)
end
@ -203,7 +208,6 @@ class Bundler::ConnectionPool::TimedStack
# This is an extension point for TimedStack and is called with a mutex.
#
# This method must return +obj+ to the stack.
def store_connection(obj, options = nil)
@que.push [obj, current_time]
end
@ -213,7 +217,6 @@ class Bundler::ConnectionPool::TimedStack
#
# This method must create a connection if and only if the total number of
# connections allowed has not been met.
def try_create(options = nil)
unless @created == @max
object = @create_block.call

View File

@ -1,3 +1,3 @@
class Bundler::ConnectionPool
VERSION = "2.5.0"
VERSION = "2.5.4"
end