1
0
Fork 0
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:
Matthew Draper 2016-11-19 22:07:40 +10:30
parent f9230a2d42
commit d314646c96
2 changed files with 17 additions and 25 deletions

View file

@ -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

View file

@ -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