connection_pool 0.1.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/Changes.md CHANGED
@@ -1,3 +1,9 @@
1
+ 0.9.0
2
+ --------
3
+
4
+ - Move method\_missing magic into ConnectionPool::Wrapper (djanowski)
5
+ - Remove BasicObject superclass (djanowski)
6
+
1
7
  0.1.0
2
8
  --------
3
9
 
data/Gemfile CHANGED
@@ -3,4 +3,5 @@ source "http://rubygems.org"
3
3
  # Specify your gem's dependencies in connection_pool.gemspec
4
4
  gemspec
5
5
 
6
- gem 'minitest'
6
+ gem 'rake'
7
+ gem 'minitest'
@@ -1,3 +1,4 @@
1
+ require 'connection_pool/version'
1
2
  require 'timed_queue'
2
3
 
3
4
  # Generic connection pool class for e.g. sharing a limited number of network connections
@@ -11,59 +12,72 @@ require 'timed_queue'
11
12
  # redis.lpop('my-list') if redis.llen('my-list') > 0
12
13
  # end
13
14
  #
14
- # Example usage replacing a global connection (slower):
15
+ # Example usage replacing an existing connection (slower):
15
16
  #
16
- # REDIS = ConnectionPool.new { Redis.new }
17
+ # $redis = ConnectionPool.wrap { Redis.new }
17
18
  #
18
19
  # def do_work
19
- # REDIS.lpop('my-list') if REDIS.llen('my-list') > 0
20
+ # $redis.lpop('my-list') if $redis.llen('my-list') > 0
20
21
  # end
21
22
  #
22
23
  # Accepts the following options:
23
24
  # - :size - number of connections to pool, defaults to 5
24
25
  # - :timeout - amount of time to wait for a connection if none currently available, defaults to 5 seconds
25
26
  #
26
- class ConnectionPool < BasicObject
27
+ class ConnectionPool
27
28
  DEFAULTS = { :size => 5, :timeout => 5 }
28
29
 
30
+ def self.wrap(options, &block)
31
+ Wrapper.new(options, &block)
32
+ end
33
+
29
34
  def initialize(options={}, &block)
30
- ::Kernel.raise ::ArgumentError, 'Connection pool requires a block' unless block
35
+ raise ArgumentError, 'Connection pool requires a block' unless block
31
36
 
32
- @available = ::TimedQueue.new
33
- @oid = @available.object_id
34
- @options = DEFAULTS.merge(options)
35
- @options[:size].times do
36
- @available << block.call
37
- end
37
+ options = DEFAULTS.merge(options)
38
+
39
+ @size = options[:size]
40
+ @timeout = options[:timeout]
41
+
42
+ @available = ::TimedQueue.new(@size, &block)
43
+ @key = :"current-#{@available.object_id}"
38
44
  end
39
45
 
40
- def with(&block)
46
+ def with
41
47
  yield checkout
42
48
  ensure
43
49
  checkin
44
50
  end
45
51
  alias_method :with_connection, :with
46
52
 
47
- def method_missing(name, *args)
48
- checkout.send(name, *args)
49
- ensure
50
- checkin
51
- end
52
-
53
- private
54
-
55
53
  def checkout
56
- ::Thread.current[:"current-#{@oid}"] ||= begin
57
- @available.timed_pop(@options[:timeout])
58
- end
54
+ ::Thread.current[@key] ||= @available.timed_pop(@timeout)
59
55
  end
60
56
 
61
57
  def checkin
62
- conn = ::Thread.current[:"current-#{@oid}"]
63
- ::Thread.current[:"current-#{@oid}"] = nil
58
+ conn = ::Thread.current[@key]
59
+ ::Thread.current[@key] = nil
64
60
  return unless conn
65
61
  @available << conn
66
62
  nil
67
63
  end
68
64
 
65
+ class Wrapper
66
+ def initialize(options = {}, &block)
67
+ @pool = ::ConnectionPool.new(options, &block)
68
+ end
69
+
70
+ def with
71
+ yield @pool.checkout
72
+ ensure
73
+ @pool.checkin
74
+ end
75
+ alias_method :with_connection, :with
76
+
77
+ def method_missing(name, *args, &block)
78
+ @pool.with do |connection|
79
+ connection.send(name, *args, &block)
80
+ end
81
+ end
82
+ end
69
83
  end
@@ -1,3 +1,3 @@
1
- class ConnectionPool
2
- VERSION = "0.1.0"
1
+ class ConnectionPool < BasicObject
2
+ VERSION = "0.9.0"
3
3
  end
data/lib/timed_queue.rb CHANGED
@@ -2,8 +2,8 @@ require 'thread'
2
2
  require 'timeout'
3
3
 
4
4
  class TimedQueue
5
- def initialize
6
- @que = []
5
+ def initialize(size = 0)
6
+ @que = Array.new(size) { yield }
7
7
  @mutex = Mutex.new
8
8
  @resource = ConditionVariable.new
9
9
  end
data/test/helper.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'rubygems'
2
+ require 'minitest/pride'
2
3
  require 'minitest/autorun'
3
4
 
4
5
  require 'connection_pool'
@@ -15,6 +15,11 @@ class TestConnectionPool < MiniTest::Unit::TestCase
15
15
  def fast
16
16
  @x += 1
17
17
  end
18
+ def do_something_with_block
19
+ @x += yield
20
+ sleep 0.05
21
+ @x
22
+ end
18
23
  end
19
24
 
20
25
  def test_basic_multithreaded_usage
@@ -27,12 +32,12 @@ class TestConnectionPool < MiniTest::Unit::TestCase
27
32
  end
28
33
  end
29
34
  end
30
-
35
+
31
36
  a = Time.now
32
37
  result = threads.map(&:value)
33
38
  b = Time.now
34
39
  assert_operator((b - a), :>, 0.125)
35
- assert_equal(result, [1,2,3].cycle(5).sort)
40
+ assert_equal([1,2,3].cycle(5).sort, result.sort)
36
41
  end
37
42
 
38
43
  def test_timeout
@@ -45,7 +50,7 @@ class TestConnectionPool < MiniTest::Unit::TestCase
45
50
  end
46
51
  sleep 0.05
47
52
  assert_raises Timeout::Error do
48
- pool.do_something
53
+ pool.with { |net| net.do_something }
49
54
  end
50
55
 
51
56
  sleep 0.05
@@ -55,9 +60,11 @@ class TestConnectionPool < MiniTest::Unit::TestCase
55
60
  end
56
61
 
57
62
  def test_passthru
58
- pool = ConnectionPool.new(:timeout => 0.1, :size => 1) { NetworkConnection.new }
63
+ pool = ConnectionPool.wrap(:timeout => 0.1, :size => 1) { NetworkConnection.new }
59
64
  assert_equal 1, pool.do_something
60
65
  assert_equal 2, pool.do_something
66
+ assert_equal 5, pool.do_something_with_block { 3 }
67
+ assert_equal 6, pool.with { |net| net.fast }
61
68
  end
62
69
 
63
70
  def test_return_value
metadata CHANGED
@@ -1,28 +1,23 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: connection_pool
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
4
5
  prerelease:
5
- version: 0.1.0
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Mike Perham
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
-
13
- date: 2011-09-19 00:00:00 Z
12
+ date: 2012-03-14 00:00:00.000000000 Z
14
13
  dependencies: []
15
-
16
14
  description: Generic connection pool for Ruby
17
- email:
15
+ email:
18
16
  - mperham@gmail.com
19
17
  executables: []
20
-
21
18
  extensions: []
22
-
23
19
  extra_rdoc_files: []
24
-
25
- files:
20
+ files:
26
21
  - .gitignore
27
22
  - Changes.md
28
23
  - Gemfile
@@ -35,33 +30,30 @@ files:
35
30
  - lib/timed_queue.rb
36
31
  - test/helper.rb
37
32
  - test/test_connection_pool.rb
38
- homepage: ""
33
+ homepage: ''
39
34
  licenses: []
40
-
41
35
  post_install_message:
42
36
  rdoc_options: []
43
-
44
- require_paths:
37
+ require_paths:
45
38
  - lib
46
- required_ruby_version: !ruby/object:Gem::Requirement
39
+ required_ruby_version: !ruby/object:Gem::Requirement
47
40
  none: false
48
- requirements:
49
- - - ">="
50
- - !ruby/object:Gem::Version
51
- version: "0"
52
- required_rubygems_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
46
  none: false
54
- requirements:
55
- - - ">="
56
- - !ruby/object:Gem::Version
57
- version: "0"
47
+ requirements:
48
+ - - ! '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
58
51
  requirements: []
59
-
60
52
  rubyforge_project:
61
- rubygems_version: 1.8.10
53
+ rubygems_version: 1.8.15
62
54
  signing_key:
63
55
  specification_version: 3
64
56
  summary: Generic connection pool for Ruby
65
- test_files:
57
+ test_files:
66
58
  - test/helper.rb
67
59
  - test/test_connection_pool.rb