connection_pool 1.0.0 → 1.1.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,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