FEATURE: add connnection reaping based on maximum age

This feature ensures connections to the db are always attempted to be closed
after 600 seconds of idle time.
This commit is contained in:
Sam 2015-10-17 11:29:16 +11:00
parent 5bea933370
commit 805120fc95
3 changed files with 11 additions and 8 deletions

View File

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

View File

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

View File

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