diff --git a/config/discourse_defaults.conf b/config/discourse_defaults.conf index 3b2ae347d9d..4d7bbfa76fa 100644 --- a/config/discourse_defaults.conf +++ b/config/discourse_defaults.conf @@ -123,6 +123,8 @@ new_version_emails = true connection_reaper_age = 30 # run reap check every 30 seconds connection_reaper_interval = 30 +# also reap any connections older than this +connection_reaper_max_age = 600 # set to relative URL (for subdirectory hosting) # IMPORTANT: path must not include a trailing / diff --git a/lib/discourse.rb b/lib/discourse.rb index a087120ee72..890aa9aa932 100644 --- a/lib/discourse.rb +++ b/lib/discourse.rb @@ -340,7 +340,7 @@ module Discourse while true begin sleep GlobalSetting.connection_reaper_interval - reap_connections(GlobalSetting.connection_reaper_age) + reap_connections(GlobalSetting.connection_reaper_age, GlobalSetting.connection_reaper_max_age) rescue => e Discourse.handle_exception(e, {message: "Error reaping connections"}) end @@ -348,12 +348,12 @@ module Discourse end end - def self.reap_connections(age) + def self.reap_connections(idle, max_age) pools = [] ObjectSpace.each_object(ActiveRecord::ConnectionAdapters::ConnectionPool){|pool| pools << pool} pools.each do |pool| - pool.drain(age.seconds) + pool.drain(idle.seconds, max_age.seconds) end end diff --git a/lib/freedom_patches/pool_drainer.rb b/lib/freedom_patches/pool_drainer.rb index ff58a288d4e..6ded19de97d 100644 --- a/lib/freedom_patches/pool_drainer.rb +++ b/lib/freedom_patches/pool_drainer.rb @@ -2,11 +2,12 @@ if Rails.version >= "4.2.0" class ActiveRecord::ConnectionAdapters::AbstractAdapter module LastUseExtension - attr_reader :last_use + attr_reader :last_use, :first_use def initialize(connection, logger = nil, pool = nil) super @last_use = false + @first_use = Time.now end def lease @@ -26,11 +27,11 @@ 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) + def drain(idle_time=nil, max_age=nil) synchronize do @available.clear @connections.delete_if do |conn| - try_drain?(conn, idle_time) + try_drain?(conn, idle_time, max_age) end @connections.each do |conn| @@ -42,9 +43,9 @@ class ActiveRecord::ConnectionAdapters::ConnectionPool private - def try_drain?(conn, idle_time) + def try_drain?(conn, idle_time, max_age) if !conn.in_use? - if !idle_time || conn.last_use < idle_time.seconds.ago + if !idle_time || conn.last_use < idle_time.seconds.ago || (max_age && conn.first_use < max_age.seconds.ago) conn.disconnect! return true end