mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Distribute connections to previously blocked threads when we're done
Two methods block new connections; we were already doing the right thing for clear_reloadable_connections, but it's better placed in with_new_connections_blocked, where it can work for disconnect too.
This commit is contained in:
parent
f9230a2d42
commit
d314646c96
2 changed files with 17 additions and 25 deletions
|
@ -422,7 +422,6 @@ module ActiveRecord
|
||||||
conn.disconnect!
|
conn.disconnect!
|
||||||
end
|
end
|
||||||
@connections = []
|
@connections = []
|
||||||
@available.clear
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -445,8 +444,6 @@ module ActiveRecord
|
||||||
# connections in the pool within a timeout interval (default duration is
|
# connections in the pool within a timeout interval (default duration is
|
||||||
# <tt>spec.config[:checkout_timeout] * 2</tt> seconds).
|
# <tt>spec.config[:checkout_timeout] * 2</tt> seconds).
|
||||||
def clear_reloadable_connections(raise_on_acquisition_timeout = true)
|
def clear_reloadable_connections(raise_on_acquisition_timeout = true)
|
||||||
num_new_conns_required = 0
|
|
||||||
|
|
||||||
with_exclusively_acquired_all_connections(raise_on_acquisition_timeout) do
|
with_exclusively_acquired_all_connections(raise_on_acquisition_timeout) do
|
||||||
synchronize do
|
synchronize do
|
||||||
@connections.each do |conn|
|
@connections.each do |conn|
|
||||||
|
@ -457,26 +454,10 @@ module ActiveRecord
|
||||||
conn.disconnect! if conn.requires_reloading?
|
conn.disconnect! if conn.requires_reloading?
|
||||||
end
|
end
|
||||||
@connections.delete_if(&:requires_reloading?)
|
@connections.delete_if(&:requires_reloading?)
|
||||||
|
|
||||||
@available.clear
|
|
||||||
|
|
||||||
if @connections.size < @size
|
|
||||||
# because of the pruning done by this method, we might be running
|
|
||||||
# low on connections, while threads stuck in queue are helpless
|
|
||||||
# (not being able to establish new connections for themselves),
|
|
||||||
# see also more detailed explanation in +remove+
|
|
||||||
num_new_conns_required = num_waiting_in_queue - @connections.size
|
|
||||||
end
|
|
||||||
|
|
||||||
@connections.each do |conn|
|
|
||||||
@available.add conn
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
bulk_make_new_connections(num_new_conns_required) if num_new_conns_required > 0
|
|
||||||
end
|
|
||||||
|
|
||||||
# Clears the cache which maps classes and re-connects connections that
|
# Clears the cache which maps classes and re-connects connections that
|
||||||
# require reloading.
|
# require reloading.
|
||||||
#
|
#
|
||||||
|
@ -705,10 +686,27 @@ module ActiveRecord
|
||||||
|
|
||||||
yield
|
yield
|
||||||
ensure
|
ensure
|
||||||
|
num_new_conns_required = 0
|
||||||
|
|
||||||
synchronize do
|
synchronize do
|
||||||
@threads_blocking_new_connections -= 1
|
@threads_blocking_new_connections -= 1
|
||||||
|
|
||||||
|
if @threads_blocking_new_connections.zero?
|
||||||
|
@available.clear
|
||||||
|
|
||||||
|
num_new_conns_required = num_waiting_in_queue
|
||||||
|
|
||||||
|
@connections.each do |conn|
|
||||||
|
next if conn.in_use?
|
||||||
|
|
||||||
|
@available.add conn
|
||||||
|
num_new_conns_required -= 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
bulk_make_new_connections(num_new_conns_required) if num_new_conns_required > 0
|
||||||
|
end
|
||||||
|
|
||||||
# Acquire a connection by one of 1) immediately removing one
|
# Acquire a connection by one of 1) immediately removing one
|
||||||
# from the queue of available connections, 2) creating a new
|
# from the queue of available connections, 2) creating a new
|
||||||
|
|
|
@ -487,12 +487,6 @@ module ActiveRecord
|
||||||
#--- post test clean up start
|
#--- post test clean up start
|
||||||
second_thread_done.count_down if failed
|
second_thread_done.count_down if failed
|
||||||
|
|
||||||
# after `pool.disconnect()` the first thread will be left stuck in queue, no need to wait for
|
|
||||||
# it to timeout with ConnectionTimeoutError
|
|
||||||
if (group_action_method == :disconnect || group_action_method == :disconnect!) && pool.num_waiting_in_queue > 0
|
|
||||||
pool.with_connection {} # create a new connection in case there are threads still stuck in a queue
|
|
||||||
end
|
|
||||||
|
|
||||||
first_thread.join
|
first_thread.join
|
||||||
second_thread.join
|
second_thread.join
|
||||||
#--- post test clean up end
|
#--- post test clean up end
|
||||||
|
|
Loading…
Reference in a new issue