mirror of
https://github.com/mperham/connection_pool
synced 2023-03-27 23:22:21 -04:00
More testing, threading fixes
This commit is contained in:
parent
27362471c6
commit
5ddef034cf
4 changed files with 36 additions and 28 deletions
|
@ -19,10 +19,8 @@ Create a pool of objects to share amongst the fibers or threads in your Ruby app
|
||||||
|
|
||||||
Then use the pool in your application:
|
Then use the pool in your application:
|
||||||
|
|
||||||
@memcached.with do |dalli|
|
@memcached.with_connection do |dalli|
|
||||||
dalli.fetch('some-count', :expires_in => 1.day) do
|
dalli.get('some-count')
|
||||||
SomeModel.query.count
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ class ConnectionPool
|
||||||
ensure
|
ensure
|
||||||
checkin
|
checkin
|
||||||
end
|
end
|
||||||
|
alias_method :with_connection, :with
|
||||||
|
|
||||||
def method_missing(name, *args)
|
def method_missing(name, *args)
|
||||||
checkout.send(name, *args)
|
checkout.send(name, *args)
|
||||||
|
|
|
@ -4,7 +4,6 @@ require 'timeout'
|
||||||
class TimedQueue
|
class TimedQueue
|
||||||
def initialize
|
def initialize
|
||||||
@que = []
|
@que = []
|
||||||
@waiting = []
|
|
||||||
@mutex = Mutex.new
|
@mutex = Mutex.new
|
||||||
@resource = ConditionVariable.new
|
@resource = ConditionVariable.new
|
||||||
end
|
end
|
||||||
|
@ -15,22 +14,15 @@ class TimedQueue
|
||||||
@resource.signal
|
@resource.signal
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
alias << push
|
alias_method :<<, :push
|
||||||
|
|
||||||
def timed_pop(timeout=0.5)
|
def timed_pop(timeout=0.5)
|
||||||
while true
|
|
||||||
@mutex.synchronize do
|
@mutex.synchronize do
|
||||||
@waiting.delete(Thread.current)
|
|
||||||
if @que.empty?
|
if @que.empty?
|
||||||
@waiting.push Thread.current
|
|
||||||
@resource.wait(@mutex, timeout)
|
@resource.wait(@mutex, timeout)
|
||||||
raise Timeout::Error if @que.empty?
|
raise Timeout::Error if @que.empty?
|
||||||
else
|
|
||||||
retval = @que.shift
|
|
||||||
@resource.signal
|
|
||||||
return retval
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
return @que.shift
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -3,38 +3,46 @@ require 'helper'
|
||||||
class TestConnectionPool < MiniTest::Unit::TestCase
|
class TestConnectionPool < MiniTest::Unit::TestCase
|
||||||
|
|
||||||
class NetworkConnection
|
class NetworkConnection
|
||||||
|
def initialize
|
||||||
|
@x = 0
|
||||||
|
end
|
||||||
def do_something
|
def do_something
|
||||||
sleep 0.1
|
@x += 1
|
||||||
'foo'
|
sleep 0.05
|
||||||
|
@x
|
||||||
|
end
|
||||||
|
def fast
|
||||||
|
@x += 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_basic_multithreaded_usage
|
def test_basic_multithreaded_usage
|
||||||
pool = ConnectionPool.new(:size => 5) { NetworkConnection.new }
|
pool = ConnectionPool.new(:size => 5) { NetworkConnection.new }
|
||||||
threads = []
|
threads = []
|
||||||
10.times do
|
15.times do
|
||||||
threads << Thread.new do
|
threads << Thread.new do
|
||||||
pool.with do |net|
|
pool.with_connection do |net|
|
||||||
net.do_something
|
net.do_something
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
a = Time.now
|
a = Time.now
|
||||||
threads.each(&:join)
|
result = threads.map(&:value)
|
||||||
b = Time.now
|
b = Time.now
|
||||||
assert((b - a) > 0.2)
|
assert_operator((b - a), :>, 0.125)
|
||||||
|
assert_equal(result, [1,2,3].cycle(5).sort)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_timeout
|
def test_timeout
|
||||||
pool = ConnectionPool.new(:timeout => 0.1, :size => 1) { NetworkConnection.new }
|
pool = ConnectionPool.new(:timeout => 0.05, :size => 1) { NetworkConnection.new }
|
||||||
Thread.new do
|
Thread.new do
|
||||||
pool.with do |net|
|
pool.with do |net|
|
||||||
net.do_something
|
net.do_something
|
||||||
sleep 0.2
|
|
||||||
end
|
|
||||||
end
|
|
||||||
sleep 0.1
|
sleep 0.1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sleep 0.05
|
||||||
assert_raises Timeout::Error do
|
assert_raises Timeout::Error do
|
||||||
pool.do_something
|
pool.do_something
|
||||||
end
|
end
|
||||||
|
@ -42,6 +50,15 @@ class TestConnectionPool < MiniTest::Unit::TestCase
|
||||||
|
|
||||||
def test_passthru
|
def test_passthru
|
||||||
pool = ConnectionPool.new(:timeout => 0.1, :size => 1) { NetworkConnection.new }
|
pool = ConnectionPool.new(:timeout => 0.1, :size => 1) { NetworkConnection.new }
|
||||||
assert_equal 'foo', pool.do_something
|
assert_equal 1, pool.do_something
|
||||||
|
assert_equal 2, pool.do_something
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_return_value
|
||||||
|
pool = ConnectionPool.new(:timeout => 0.1, :size => 1) { NetworkConnection.new }
|
||||||
|
result = pool.with_connection do |net|
|
||||||
|
net.fast
|
||||||
|
end
|
||||||
|
assert_equal 1, result
|
||||||
end
|
end
|
||||||
end
|
end
|
Loading…
Reference in a new issue