FIX: correct pool reaper

This removes a freedom patch and replaces with a custom reaper thread
it also captures an issue where reaper would fail when connections where
empty
This commit is contained in:
Sam
2018-06-14 18:22:02 +10:00
parent 1d9fdcd9d3
commit 87fabdc2f3
4 changed files with 13 additions and 105 deletions

View File

@@ -435,7 +435,7 @@ module Discourse
# after fork, otherwise Discourse will be
# in a bad state
def self.after_fork
# note: all this reconnecting may no longer be needed per https://github.com/redis/redis-rb/pull/414
# note: some of this reconnecting may no longer be needed per https://github.com/redis/redis-rb/pull/414
MessageBus.after_fork
SiteSetting.after_fork
$redis._client.reconnect
@@ -487,7 +487,7 @@ module Discourse
while true
begin
sleep GlobalSetting.connection_reaper_interval
reap_connections(GlobalSetting.connection_reaper_age, GlobalSetting.connection_reaper_max_age)
reap_connections(GlobalSetting.connection_reaper_age)
rescue => e
Discourse.warn_exception(e, message: "Error reaping connections")
end
@@ -495,15 +495,22 @@ module Discourse
end
end
def self.reap_connections(idle, max_age)
def self.reap_connections(idle)
pools = []
ObjectSpace.each_object(ActiveRecord::ConnectionAdapters::ConnectionPool) { |pool| pools << pool }
i = 0
pools.each do |pool|
i += 1
# 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)
# flush removes idle connections
# after fork we have "deadpools" so ignore them, they have been discarded
# so @connections is set to nil
if pool.connections
pool.reap
pool.flush(idle.seconds)
end
end
end

View File

@@ -1,47 +0,0 @@
class ActiveRecord::ConnectionAdapters::AbstractAdapter
module LastUseExtension
attr_reader :last_use, :first_use
def initialize(connection, logger = nil, pool = nil)
super
@last_use = false
@first_use = Time.now
end
def lease
@lock.synchronize do
unless in_use?
@last_use = Time.now
super
end
end
end
end
prepend LastUseExtension
end
class ActiveRecord::ConnectionAdapters::ConnectionPool
# drain all idle connections
# if idle_time is specified only connections idle for N seconds will be drained
def drain(idle_time = nil, max_age = nil)
return if !(@connections && @available)
idle_connections = synchronize do
@connections.select do |conn|
!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
idle_connections.each do |conn|
conn.disconnect!
end
end
end