FIX: pool drainer to use Rails 5.2 implementation

old implementation did not reap abandoned connections
This commit is contained in:
Sam 2018-06-14 15:54:48 +10:00
parent 8fc08aad09
commit 71aa20bd30
3 changed files with 23 additions and 23 deletions

View File

@ -500,6 +500,9 @@ module Discourse
ObjectSpace.each_object(ActiveRecord::ConnectionAdapters::ConnectionPool) { |pool| pools << pool } ObjectSpace.each_object(ActiveRecord::ConnectionAdapters::ConnectionPool) { |pool| pools << pool }
pools.each do |pool| pools.each do |pool|
# reap recovers connections that were aborted
# eg a thread died or a dev forgot to check it in
pool.reap
pool.drain(idle.seconds, max_age.seconds) pool.drain(idle.seconds, max_age.seconds)
end end
end end

View File

@ -25,31 +25,23 @@ class ActiveRecord::ConnectionAdapters::ConnectionPool
# drain all idle connections # drain all idle connections
# if idle_time is specified only connections idle for N seconds will be drained # if idle_time is specified only connections idle for N seconds will be drained
def drain(idle_time = nil, max_age = nil) def drain(idle_time = nil, max_age = nil)
synchronize do return if !(@connections && @available)
if @available && @connections
@available.clear
@connections.delete_if do |conn|
try_drain?(conn, idle_time, max_age)
end
@connections.each do |conn| idle_connections = synchronize do
@available.add conn if !conn.in_use? @connections.select do |conn|
end !conn.in_use? && ((idle_time && conn.last_use <= idle_time.seconds.ago) || (max_age && conn.first_use < max_age.seconds.ago))
end.each do |conn|
conn.lease
@available.delete conn
@connections.delete conn
end end
end end
idle_connections.each do |conn|
conn.disconnect!
end
end end
private
def try_drain?(conn, idle_time, max_age)
if !conn.in_use?
if !idle_time || conn.last_use < idle_time.seconds.ago || (max_age && conn.first_use < max_age.seconds.ago)
conn.disconnect!
return true
end
end
false
end
end end

View File

@ -6,7 +6,10 @@ describe 'pool drainer' do
end end
it 'can correctly drain the connection pool' do it 'can correctly drain the connection pool' do
pool.drain
pool.reap
pool.drain(0)
old = pool.connections.length old = pool.connections.length
expect(old).to eq(1) expect(old).to eq(1)
@ -16,7 +19,9 @@ describe 'pool drainer' do
end.join end.join
expect(pool.connections.length).to eq(old + 1) expect(pool.connections.length).to eq(old + 1)
pool.drain
freeze_time 1.second.from_now
pool.drain(0)
expect(pool.connections.length).to eq(old) expect(pool.connections.length).to eq(old)
end end