FIX: pool drainer to use Rails 5.2 implementation
old implementation did not reap abandoned connections
This commit is contained in:
parent
8fc08aad09
commit
71aa20bd30
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue