connection_pool 0.9.2 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Changes.md CHANGED
@@ -1,3 +1,20 @@
1
+ 0.9.3
2
+ --------
3
+
4
+ - `#with_connection` is now deprecated in favor of `#with`.
5
+
6
+ A warning will be issued in the 0.9 series and the method will be
7
+ removed in 1.0.
8
+
9
+ - We now reuse objects when possible.
10
+
11
+ This means that under no contention, the same object will be checked
12
+ out from the pool after subsequent calls to `ConnectionPool#with`.
13
+
14
+ This change should have no impact on end user performance. If
15
+ anything, it should be an improvement, depending on what objects you
16
+ are pooling.
17
+
1
18
  0.9.2
2
19
  --------
3
20
 
data/README.md CHANGED
@@ -11,35 +11,57 @@ Install
11
11
 
12
12
  gem install connection_pool
13
13
 
14
+
15
+ Notes
16
+ ------------
17
+
18
+ - Connections are eager created when the pool is created.
19
+ - There is no provision for repairing or checking the health of a
20
+ connection; connections should be self-repairing. This is
21
+ true of the dalli and redis clients.
22
+
23
+
14
24
  Usage
15
25
  ------------
16
26
 
17
27
  Create a pool of objects to share amongst the fibers or threads in your Ruby application:
18
28
 
19
- @memcached = ConnectionPool.new(:size => 5, :timeout => 5) { Dalli::Client.new }
29
+ ``` ruby
30
+ @memcached = ConnectionPool.new(:size => 5, :timeout => 5) { Dalli::Client.new }
31
+ ```
20
32
 
21
33
  Then use the pool in your application:
22
34
 
23
- @memcached.with_connection do |dalli|
24
- dalli.get('some-count')
25
- end
35
+ ``` ruby
36
+ @memcached.with do |dalli|
37
+ dalli.get('some-count')
38
+ end
39
+ ```
40
+
41
+ If all the objects in the connection pool are in use, `with` will block
42
+ until one becomes available. If no object is available within `:timeout` seconds,
43
+ `with` will raise a `Timeout::Error`.
26
44
 
27
45
  You can use `ConnectionPool::Wrapper` to wrap a single global connection, making
28
46
  it easier to port your connection code over time:
29
47
 
30
- $redis = ConnectionPool::Wrapper.new(:size => 5, :timeout => 3) { Redis.connect }
31
- $redis.sadd('foo', 1)
32
- $redis.smembers('foo')
48
+ ``` ruby
49
+ $redis = ConnectionPool::Wrapper.new(:size => 5, :timeout => 3) { Redis.connect }
50
+ $redis.sadd('foo', 1)
51
+ $redis.smembers('foo')
52
+ ```
33
53
 
34
54
  The Wrapper uses `method_missing` to checkout a connection, run the
35
55
  requested method and then immediately check the connection back into the
36
56
  pool. It's **not** high-performance so you'll want to port your
37
- performance sensitive code to use `with_connection` as soon as possible.
38
-
39
- $redis.with_connection do |conn|
40
- conn.sadd('foo', 1)
41
- conn.smembers('foo')
42
- end
57
+ performance sensitive code to use `with` as soon as possible.
58
+
59
+ ``` ruby
60
+ $redis.with do |conn|
61
+ conn.sadd('foo', 1)
62
+ conn.smembers('foo')
63
+ end
64
+ ```
43
65
 
44
66
  Once you've ported your entire system to use `with`, you can simply
45
67
  remove ::Wrapper and use a simple, fast ConnectionPool.
data/Rakefile CHANGED
@@ -1,5 +1,8 @@
1
- require 'bundler'
2
- Bundler::GemHelper.install_tasks
1
+ begin
2
+ require 'bundler'
3
+ Bundler::GemHelper.install_tasks
4
+ rescue LoadError
5
+ end
3
6
 
4
7
  require 'rake/testtask'
5
8
  Rake::TestTask.new(:test) do |test|
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
7
7
  s.platform = Gem::Platform::RUBY
8
8
  s.authors = ["Mike Perham"]
9
9
  s.email = ["mperham@gmail.com"]
10
- s.homepage = ""
10
+ s.homepage = "https://github.com/mperham/connection_pool"
11
11
  s.description = s.summary = %q{Generic connection pool for Ruby}
12
12
 
13
13
  s.files = `git ls-files`.split("\n")
@@ -1,5 +1,5 @@
1
- require 'connection_pool/version'
2
- require 'timed_queue'
1
+ require_relative 'connection_pool/version'
2
+ require_relative 'timed_queue'
3
3
 
4
4
  # Generic connection pool class for e.g. sharing a limited number of network connections
5
5
  # among many threads. Note: Connections are eager created.
@@ -25,19 +25,19 @@ require 'timed_queue'
25
25
  # - :timeout - amount of time to wait for a connection if none currently available, defaults to 5 seconds
26
26
  #
27
27
  class ConnectionPool
28
- DEFAULTS = { :size => 5, :timeout => 5 }
28
+ DEFAULTS = {size: 5, timeout: 5}
29
29
 
30
30
  def self.wrap(options, &block)
31
31
  Wrapper.new(options, &block)
32
32
  end
33
33
 
34
- def initialize(options={}, &block)
34
+ def initialize(options = {}, &block)
35
35
  raise ArgumentError, 'Connection pool requires a block' unless block
36
36
 
37
37
  options = DEFAULTS.merge(options)
38
38
 
39
- @size = options[:size]
40
- @timeout = options[:timeout]
39
+ @size = options.fetch(:size)
40
+ @timeout = options.fetch(:timeout)
41
41
 
42
42
  @available = ::TimedQueue.new(@size, &block)
43
43
  @key = :"current-#{@available.object_id}"
@@ -51,7 +51,11 @@ class ConnectionPool
51
51
  checkin
52
52
  end
53
53
  end
54
- alias_method :with_connection, :with
54
+
55
+ def with_connection(&block)
56
+ warn("ConnectionPool#with_connection is deprecated and will be removed in version 1.0. Upgrade your code to use ConnectionPool#with instead. (in #{caller[0]})")
57
+ with(&block)
58
+ end
55
59
 
56
60
  def checkout
57
61
  stack = ::Thread.current[@key] ||= []
@@ -75,7 +79,9 @@ class ConnectionPool
75
79
  nil
76
80
  end
77
81
 
78
- class Wrapper
82
+ class Wrapper < ::BasicObject
83
+ METHODS = [:with]
84
+
79
85
  def initialize(options = {}, &block)
80
86
  @pool = ::ConnectionPool.new(options, &block)
81
87
  end
@@ -85,7 +91,15 @@ class ConnectionPool
85
91
  ensure
86
92
  @pool.checkin
87
93
  end
88
- alias_method :with_connection, :with
94
+
95
+ def with_connection(&block)
96
+ warn("ConnectionPool::Wrapper#with_connection is deprecated and will be removed in version 1.0. Upgrade your code to use ConnectionPool::Wrapper#with instead. (in #{caller[0]})")
97
+ with(&block)
98
+ end
99
+
100
+ def respond_to?(id, *args)
101
+ METHODS.include?(id) || @pool.with { |c| c.respond_to?(id, *args) }
102
+ end
89
103
 
90
104
  def method_missing(name, *args, &block)
91
105
  @pool.with do |connection|
@@ -1,3 +1,3 @@
1
1
  class ConnectionPool
2
- VERSION = "0.9.2"
2
+ VERSION = "0.9.3"
3
3
  end
data/lib/timed_queue.rb CHANGED
@@ -20,7 +20,7 @@ class TimedQueue
20
20
  deadline = Time.now + timeout
21
21
  @mutex.synchronize do
22
22
  loop do
23
- return @que.shift unless @que.empty?
23
+ return @que.pop unless @que.empty?
24
24
  to_wait = deadline - Time.now
25
25
  raise Timeout::Error, "Waited #{timeout} sec" if to_wait <= 0
26
26
  @resource.wait(@mutex, to_wait)
data/test/helper.rb CHANGED
@@ -2,8 +2,6 @@ require 'rubygems'
2
2
  require 'minitest/pride'
3
3
  require 'minitest/autorun'
4
4
 
5
- require 'connection_pool'
6
-
7
5
  puts RUBY_DESCRIPTION
8
6
 
9
7
  class MiniTest::Unit::TestCase
@@ -15,3 +13,7 @@ class MiniTest::Unit::TestCase
15
13
  end
16
14
 
17
15
  end
16
+
17
+ $VERBOSE = 1
18
+
19
+ require_relative '../lib/connection_pool'
@@ -7,19 +7,26 @@ class TestConnectionPool < MiniTest::Unit::TestCase
7
7
  def initialize
8
8
  @x = 0
9
9
  end
10
+
10
11
  def do_something
11
12
  @x += 1
12
13
  sleep 0.05
13
14
  @x
14
15
  end
16
+
15
17
  def fast
16
18
  @x += 1
17
19
  end
20
+
18
21
  def do_something_with_block
19
22
  @x += yield
20
23
  sleep 0.05
21
24
  @x
22
25
  end
26
+
27
+ def respond_to?(method_id, *args)
28
+ method_id == :do_magic || super(method_id, *args)
29
+ end
23
30
  end
24
31
 
25
32
  def test_basic_multithreaded_usage
@@ -27,7 +34,7 @@ class TestConnectionPool < MiniTest::Unit::TestCase
27
34
  threads = []
28
35
  15.times do
29
36
  threads << Thread.new do
30
- pool.with_connection do |net|
37
+ pool.with do |net|
31
38
  net.do_something
32
39
  end
33
40
  end
@@ -67,9 +74,17 @@ class TestConnectionPool < MiniTest::Unit::TestCase
67
74
  assert_equal 6, pool.with { |net| net.fast }
68
75
  end
69
76
 
77
+ def test_passthru_respond_to
78
+ pool = ConnectionPool.wrap(:timeout => 0.1, :size => 1) { NetworkConnection.new }
79
+ assert pool.respond_to?(:with)
80
+ assert pool.respond_to?(:do_something)
81
+ assert pool.respond_to?(:do_magic)
82
+ refute pool.respond_to?(:do_lots_of_magic)
83
+ end
84
+
70
85
  def test_return_value
71
86
  pool = ConnectionPool.new(:timeout => 0.1, :size => 1) { NetworkConnection.new }
72
- result = pool.with_connection do |net|
87
+ result = pool.with do |net|
73
88
  net.fast
74
89
  end
75
90
  assert_equal 1, result
@@ -87,6 +102,16 @@ class TestConnectionPool < MiniTest::Unit::TestCase
87
102
  sleep 0.5
88
103
  end
89
104
 
105
+ def test_reuses_objects_when_pool_not_saturated
106
+ pool = ConnectionPool.new(:size => 5) { NetworkConnection.new }
107
+
108
+ ids = 10.times.map do
109
+ pool.with { |c| c.object_id }
110
+ end
111
+
112
+ assert_equal 1, ids.uniq.size
113
+ end
114
+
90
115
  class Recorder
91
116
  def initialize
92
117
  @calls = []
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: connection_pool
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.2
4
+ version: 0.9.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-30 00:00:00.000000000 Z
12
+ date: 2012-12-19 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Generic connection pool for Ruby
15
15
  email:
@@ -30,7 +30,7 @@ files:
30
30
  - lib/timed_queue.rb
31
31
  - test/helper.rb
32
32
  - test/test_connection_pool.rb
33
- homepage: ''
33
+ homepage: https://github.com/mperham/connection_pool
34
34
  licenses: []
35
35
  post_install_message:
36
36
  rdoc_options: []
@@ -50,7 +50,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
50
50
  version: '0'
51
51
  requirements: []
52
52
  rubyforge_project:
53
- rubygems_version: 1.8.15
53
+ rubygems_version: 1.8.24
54
54
  signing_key:
55
55
  specification_version: 3
56
56
  summary: Generic connection pool for Ruby