1
0
Fork 0
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:
Mike Perham 2011-05-14 19:42:07 -07:00
parent 27362471c6
commit 5ddef034cf
4 changed files with 36 additions and 28 deletions

View file

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

View file

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

View file

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

View file

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