connection_pool 1.0.0 → 1.1.0

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,12 @@
1
+ 1.1.0
2
+ -----
3
+
4
+ - New `#shutdown` method (simao)
5
+
6
+ This method accepts a block and calls the block for each
7
+ connection in the pool. After calling this method, trying to get a
8
+ connection from the pool raises `PoolShuttingDownError`.
9
+
1
10
  1.0.0
2
11
  -----
3
12
 
@@ -14,4 +14,6 @@ Gem::Specification.new do |s|
14
14
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
15
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
16
  s.require_paths = ["lib"]
17
+ s.license = "MIT"
18
+ s.add_development_dependency 'minitest', '>= 5.0.0'
17
19
  end
@@ -1,4 +1,5 @@
1
- require_relative 'connection_pool/version'
1
+ require 'connection_pool/version'
2
+ require 'connection_pool/timed_stack'
2
3
 
3
4
  # Generic connection pool class for e.g. sharing a limited number of network connections
4
5
  # among many threads. Note: Connections are eager created.
@@ -73,6 +74,10 @@ class ConnectionPool
73
74
  nil
74
75
  end
75
76
 
77
+ def shutdown(&block)
78
+ @available.shutdown(&block)
79
+ end
80
+
76
81
  class Wrapper < ::BasicObject
77
82
  METHODS = [:with]
78
83
 
@@ -1,16 +1,24 @@
1
1
  require 'thread'
2
2
  require 'timeout'
3
3
 
4
+ class ConnectionPool::PoolShuttingDownError < RuntimeError; end
5
+
4
6
  class ConnectionPool::TimedStack
5
7
  def initialize(size = 0)
6
8
  @que = Array.new(size) { yield }
7
9
  @mutex = Mutex.new
8
10
  @resource = ConditionVariable.new
11
+ @shutdown_block = nil
9
12
  end
10
13
 
11
14
  def push(obj)
12
15
  @mutex.synchronize do
13
- @que.push obj
16
+ if @shutdown_block
17
+ @shutdown_block.call(obj)
18
+ else
19
+ @que.push obj
20
+ end
21
+
14
22
  @resource.broadcast
15
23
  end
16
24
  end
@@ -20,6 +28,7 @@ class ConnectionPool::TimedStack
20
28
  deadline = Time.now + timeout
21
29
  @mutex.synchronize do
22
30
  loop do
31
+ raise ConnectionPool::PoolShuttingDownError if @shutdown_block
23
32
  return @que.pop unless @que.empty?
24
33
  to_wait = deadline - Time.now
25
34
  raise Timeout::Error, "Waited #{timeout} sec" if to_wait <= 0
@@ -28,6 +37,20 @@ class ConnectionPool::TimedStack
28
37
  end
29
38
  end
30
39
 
40
+ def shutdown(&block)
41
+ raise ArgumentError, "shutdown must receive a block" unless block_given?
42
+
43
+ @mutex.synchronize do
44
+ @shutdown_block = block
45
+ @resource.broadcast
46
+
47
+ @que.size.times do
48
+ conn = @que.pop
49
+ block.call(conn)
50
+ end
51
+ end
52
+ end
53
+
31
54
  def empty?
32
55
  @que.empty?
33
56
  end
@@ -1,3 +1,3 @@
1
1
  class ConnectionPool
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -2,9 +2,9 @@ require 'rubygems'
2
2
  require 'minitest/pride'
3
3
  require 'minitest/autorun'
4
4
 
5
- puts RUBY_DESCRIPTION
5
+ require 'connection_pool'
6
6
 
7
- class MiniTest::Unit::TestCase
7
+ class Minitest::Unit::TestCase
8
8
 
9
9
  def async_test(time=0.5)
10
10
  q = TimedQueue.new
@@ -13,7 +13,3 @@ class MiniTest::Unit::TestCase
13
13
  end
14
14
 
15
15
  end
16
-
17
- $VERBOSE = 1
18
-
19
- require_relative '../lib/connection_pool'
@@ -1,7 +1,7 @@
1
1
  Thread.abort_on_exception = true
2
2
  require 'helper'
3
3
 
4
- class TestConnectionPool < MiniTest::Unit::TestCase
4
+ class TestConnectionPool < Minitest::Test
5
5
 
6
6
  class NetworkConnection
7
7
  def initialize
@@ -29,6 +29,18 @@ class TestConnectionPool < MiniTest::Unit::TestCase
29
29
  end
30
30
  end
31
31
 
32
+ class Recorder
33
+ def initialize
34
+ @calls = []
35
+ end
36
+
37
+ attr_reader :calls
38
+
39
+ def do_work(label)
40
+ @calls << label
41
+ end
42
+ end
43
+
32
44
  def test_basic_multithreaded_usage
33
45
  pool = ConnectionPool.new(:size => 5) { NetworkConnection.new }
34
46
  threads = []
@@ -112,18 +124,6 @@ class TestConnectionPool < MiniTest::Unit::TestCase
112
124
  assert_equal 1, ids.uniq.size
113
125
  end
114
126
 
115
- class Recorder
116
- def initialize
117
- @calls = []
118
- end
119
-
120
- attr_reader :calls
121
-
122
- def do_work(label)
123
- @calls << label
124
- end
125
- end
126
-
127
127
  def test_nested_checkout
128
128
  recorder = Recorder.new
129
129
  pool = ConnectionPool.new(:size => 1) { recorder }
@@ -147,4 +147,56 @@ class TestConnectionPool < MiniTest::Unit::TestCase
147
147
 
148
148
  assert_equal ['inner', 'outer', 'other'], recorder.calls
149
149
  end
150
+
151
+ def test_shutdown_is_executed_for_all_connections
152
+ recorders = []
153
+
154
+ pool = ConnectionPool.new(:size => 3) do
155
+ Recorder.new.tap { |r| recorders << r }
156
+ end
157
+
158
+ pool.shutdown do |recorder|
159
+ recorder.do_work("shutdown")
160
+ end
161
+
162
+ assert_equal [["shutdown"]] * 3, recorders.map { |r| r.calls }
163
+ end
164
+
165
+ def test_raises_error_after_shutting_down
166
+ pool = ConnectionPool.new(:size => 1) { true }
167
+
168
+ pool.shutdown { }
169
+
170
+ assert_raises ConnectionPool::PoolShuttingDownError do
171
+ pool.checkout
172
+ end
173
+ end
174
+
175
+ def test_runs_shutdown_block_asynchronously_if_connection_was_in_use
176
+ recorders = []
177
+
178
+ pool = ConnectionPool.new(:size => 3) do
179
+ Recorder.new.tap { |r| recorders << r }
180
+ end
181
+
182
+ pool.checkout
183
+
184
+ pool.shutdown do |recorder|
185
+ recorder.do_work("shutdown")
186
+ end
187
+
188
+ assert_equal [["shutdown"], ["shutdown"], []], recorders.map { |r| r.calls }
189
+
190
+ pool.checkin
191
+
192
+ assert_equal [["shutdown"], ["shutdown"], ["shutdown"]], recorders.map { |r| r.calls }
193
+ end
194
+
195
+ def test_raises_an_error_if_shutdown_is_called_without_a_block
196
+ pool = ConnectionPool.new(:size => 1) { }
197
+
198
+ assert_raises ArgumentError do
199
+ pool.shutdown
200
+ end
201
+ end
150
202
  end
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: 1.0.0
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-19 00:00:00.000000000 Z
13
- dependencies: []
12
+ date: 2013-06-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: minitest
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 5.0.0
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 5.0.0
14
30
  description: Generic connection pool for Ruby
15
31
  email:
16
32
  - mperham@gmail.com
@@ -31,7 +47,8 @@ files:
31
47
  - test/helper.rb
32
48
  - test/test_connection_pool.rb
33
49
  homepage: https://github.com/mperham/connection_pool
34
- licenses: []
50
+ licenses:
51
+ - MIT
35
52
  post_install_message:
36
53
  rdoc_options: []
37
54
  require_paths:
@@ -50,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
50
67
  version: '0'
51
68
  requirements: []
52
69
  rubyforge_project:
53
- rubygems_version: 1.8.24
70
+ rubygems_version: 1.8.23
54
71
  signing_key:
55
72
  specification_version: 3
56
73
  summary: Generic connection pool for Ruby