From 9fc7c145b3b8353d692ac4e6773c98c9f1960546 Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 11 Aug 2014 15:13:37 +1000 Subject: [PATCH] FEATURE: added method for draining idle connections --- lib/freedom_patches/pool_drainer.rb | 33 +++++++++++++ .../freedom_patches/pool_drainer_spec.rb | 47 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 lib/freedom_patches/pool_drainer.rb create mode 100644 spec/components/freedom_patches/pool_drainer_spec.rb diff --git a/lib/freedom_patches/pool_drainer.rb b/lib/freedom_patches/pool_drainer.rb new file mode 100644 index 000000000..f953b32a4 --- /dev/null +++ b/lib/freedom_patches/pool_drainer.rb @@ -0,0 +1,33 @@ + +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) + synchronize do + @available.clear + @connections.delete_if do |conn| + try_drain?(conn, idle_time) + end + + @connections.each do |conn| + @available.add conn if !conn.in_use? + end + end + + end + + private + + def try_drain?(conn, idle_time) + if !conn.in_use? + if !idle_time || conn.last_use < idle_time.seconds.ago + conn.disconnect! + return true + end + end + + false + end + +end diff --git a/spec/components/freedom_patches/pool_drainer_spec.rb b/spec/components/freedom_patches/pool_drainer_spec.rb new file mode 100644 index 000000000..9ebfd0e69 --- /dev/null +++ b/spec/components/freedom_patches/pool_drainer_spec.rb @@ -0,0 +1,47 @@ +require 'spec_helper' + +describe 'pool drainer' do + let(:pool) do + ActiveRecord::Base.connection_pool + end + + it 'can correctly drain the connection pool' do + pool.drain + old = pool.connections.length + old.should == 1 + + Thread.new do + conn = pool.checkout + pool.checkin conn + end.join + + pool.connections.length.should == (old+1) + pool.drain + pool.connections.length.should == old + end + + it 'can drain with idle time setting' do + pool.drain + old = pool.connections.length + old.should == 1 + + + Thread.new do + conn = pool.checkout + pool.checkin conn + end.join + + pool.connections.length.should == (old+1) + pool.drain(1.minute) + pool.connections.length.should == (old+1) + + # make sure we don't corrupt internal state + 20.times do + conn = pool.checkout + pool.checkin conn + pool.drain + end + + end + +end