From 27362471c69aa2b0b25cf890579928ae565dcac3 Mon Sep 17 00:00:00 2001 From: Mike Perham Date: Sat, 14 May 2011 15:36:17 -0700 Subject: [PATCH] Add project info, tests --- Gemfile | 2 ++ LICENSE | 20 +++++++++++++ README.md | 32 ++++++++++++++++++++ Rakefile | 9 ++++++ lib/connection_pool.rb | 4 +-- lib/connection_pool/timed_queue.rb | 2 +- test/helper.rb | 16 ++++++++++ test/test_connection_pool.rb | 47 ++++++++++++++++++++++++++++++ 8 files changed, 129 insertions(+), 3 deletions(-) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 test/helper.rb create mode 100644 test/test_connection_pool.rb diff --git a/Gemfile b/Gemfile index f095e7a..b8e4007 100644 --- a/Gemfile +++ b/Gemfile @@ -2,3 +2,5 @@ source "http://rubygems.org" # Specify your gem's dependencies in connection_pool.gemspec gemspec + +gem 'minitest' \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7673cbf --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2011 Mike Perham + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a0ac7da --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +connection_pool +====================== + +Generic connection pooling for Ruby. + +MongoDB has its own connection pool. ActiveRecord has its own connection pool. This is a generic connection pool that can be used with anything, e.g. Redis, Dalli and other Ruby network clients. + +Install +------------ + + gem install connection_pool + +Usage +------------ + +Create a pool of objects to share amongst the fibers or threads in your Ruby application: + + @memcached = ConnectionPool.new(:size => 5, :timeout => 5) { Dalli::Client.new } + +Then use the pool in your application: + + @memcached.with do |dalli| + dalli.fetch('some-count', :expires_in => 1.day) do + SomeModel.query.count + end + end + + +Author +-------------- + +Mike Perham, [@mperham](https://twitter.com/mperham), \ No newline at end of file diff --git a/Rakefile b/Rakefile index 14cfe0b..dbaacee 100644 --- a/Rakefile +++ b/Rakefile @@ -1,2 +1,11 @@ require 'bundler' Bundler::GemHelper.install_tasks + +require 'rake/testtask' +Rake::TestTask.new(:test) do |test| + test.libs << 'test' + test.warning = true + test.pattern = 'test/**/test_*.rb' +end + +task :default => :test diff --git a/lib/connection_pool.rb b/lib/connection_pool.rb index ab0131e..dafbd06 100644 --- a/lib/connection_pool.rb +++ b/lib/connection_pool.rb @@ -8,7 +8,7 @@ require 'connection_pool/timed_queue' # @pool = ConnectionPool.new { Redis.new } # # @pool.with do |redis| -# redis.lpop if redis.llen('my-list') > 0 +# redis.lpop('my-list') if redis.llen('my-list') > 0 # end # # Example usage replacing a global connection (slower): @@ -16,7 +16,7 @@ require 'connection_pool/timed_queue' # REDIS = ConnectionPool.new { Redis.new } # # def do_work -# REDIS.lpop if REDIS.llen('my-list') > 0 +# REDIS.lpop('my-list') if REDIS.llen('my-list') > 0 # end # # Accepts the following options: diff --git a/lib/connection_pool/timed_queue.rb b/lib/connection_pool/timed_queue.rb index 8dc06c6..ba8c787 100644 --- a/lib/connection_pool/timed_queue.rb +++ b/lib/connection_pool/timed_queue.rb @@ -24,7 +24,7 @@ class TimedQueue if @que.empty? @waiting.push Thread.current @resource.wait(@mutex, timeout) - raise TimeoutError if @que.empty? + raise Timeout::Error if @que.empty? else retval = @que.shift @resource.signal diff --git a/test/helper.rb b/test/helper.rb new file mode 100644 index 0000000..3716844 --- /dev/null +++ b/test/helper.rb @@ -0,0 +1,16 @@ +require 'rubygems' +require 'minitest/autorun' + +require 'connection_pool' + +puts RUBY_DESCRIPTION + +class MiniTest::Unit::TestCase + + def async_test(time=0.5) + q = TimedQueue.new + yield Proc.new { q << nil } + q.timed_pop(time) + end + +end diff --git a/test/test_connection_pool.rb b/test/test_connection_pool.rb new file mode 100644 index 0000000..b35d945 --- /dev/null +++ b/test/test_connection_pool.rb @@ -0,0 +1,47 @@ +require 'helper' + +class TestConnectionPool < MiniTest::Unit::TestCase + + class NetworkConnection + def do_something + sleep 0.1 + 'foo' + end + end + + def test_basic_multithreaded_usage + pool = ConnectionPool.new(:size => 5) { NetworkConnection.new } + threads = [] + 10.times do + threads << Thread.new do + pool.with do |net| + net.do_something + end + end + end + + a = Time.now + threads.each(&:join) + b = Time.now + assert((b - a) > 0.2) + end + + def test_timeout + pool = ConnectionPool.new(:timeout => 0.1, :size => 1) { NetworkConnection.new } + Thread.new do + pool.with do |net| + net.do_something + sleep 0.2 + end + end + sleep 0.1 + assert_raises Timeout::Error do + pool.do_something + end + end + + def test_passthru + pool = ConnectionPool.new(:timeout => 0.1, :size => 1) { NetworkConnection.new } + assert_equal 'foo', pool.do_something + end +end \ No newline at end of file