connection_pool 2.2.2 → 2.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: cf8177bf07f6c8e68b13f28416f6ccc0c64803af
4
- data.tar.gz: ff9c836ce5576d4d0cb1edf8d858a761f982e437
2
+ SHA256:
3
+ metadata.gz: e9fefa40cd9db0f5add54482a9f980d808b5bb578e83a5a8bf287c636c41704d
4
+ data.tar.gz: ec25d36c42cfb863e768bf49b18316d955397edaa8862f92d27687ab2a089bf0
5
5
  SHA512:
6
- metadata.gz: 73bda4d8d0b3cc9daef5c93bb98b7649d811bd5c8f467e25c3aaf7d3353541225e7b30e1efd481a14e45f5c56b5fc846d49dabdd9a167702a71c4a9631a9b6a2
7
- data.tar.gz: a331275f67b3635e09792e646113e32bdc74254a2cdff032e972c6f2ebedd6391a1e508c36be7c4e33b40e2a07efe029a2ad0267c3ba4dc20b22813df86427bb
6
+ metadata.gz: d8653437078b6334be998d16f4851e12a21e8caca8338a07559c9bfbe646dc6023a7370aad6e33be905b05d6eaab8f249387eaa72b16a478f57c9c497adbbf30
7
+ data.tar.gz: 2a437d085a3f11376338ee32debe5e7ff38fc28fdc8d0d318287c2890bc90ce2d282468981dde43c8391798d113e1391d7998a5f5e571f1021ae99dfff6893e2
@@ -1,10 +1,12 @@
1
1
  ---
2
- sudo: false
3
2
  cache: bundler
4
3
  language: ruby
5
4
  rvm:
6
- - 2.2.9
7
- - 2.3.6
8
- - 2.4.3
9
- - 2.5.0
5
+ - 2.3
6
+ - 2.4
7
+ - 2.5
8
+ - 2.6
9
+ - 2.7
10
10
  - jruby
11
+ jdk:
12
+ - openjdk11
data/Changes.md CHANGED
@@ -1,5 +1,12 @@
1
- connection\_pool changelog
2
- ---------------------------
1
+ # connection_pool Changelog
2
+
3
+ 2.2.3
4
+ ------
5
+
6
+ - Pool now throws `ConnectionPool::TimeoutError` on timeout. [#130]
7
+ - Use monotonic clock present in all modern Rubies [Tero Tasanen, #109]
8
+ - Remove code hacks necessary for JRuby 1.7
9
+ - Expose wrapped pool from ConnectionPool::Wrapper [Thomas Lecavelier, #113]
3
10
 
4
11
  2.2.2
5
12
  ------
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gemspec(development_group: :runtime)
4
+
5
+ gem "standard"
data/README.md CHANGED
@@ -51,7 +51,7 @@ You can use `ConnectionPool::Wrapper` to wrap a single global connection,
51
51
  making it easier to migrate existing connection code over time:
52
52
 
53
53
  ``` ruby
54
- $redis = ConnectionPool::Wrapper.new(size: 5, timeout: 3) { Redis.connect }
54
+ $redis = ConnectionPool::Wrapper.new(size: 5, timeout: 3) { Redis.new }
55
55
  $redis.sadd('foo', 1)
56
56
  $redis.smembers('foo')
57
57
  ```
@@ -87,6 +87,20 @@ Shutting down a connection pool will block until all connections are checked in
87
87
  **Note that shutting down is completely optional**; Ruby's garbage collector will reclaim
88
88
  unreferenced pools under normal circumstances.
89
89
 
90
+ ## Current State
91
+
92
+ There are several methods that return information about a pool.
93
+
94
+ ```ruby
95
+ cp = ConnectionPool.new(size: 10) { Redis.new }
96
+ cp.size # => 10
97
+ cp.available # => 10
98
+
99
+ cp.with do |conn|
100
+ cp.size # => 10
101
+ cp.available # => 9
102
+ end
103
+ ```
90
104
 
91
105
  Notes
92
106
  -----
data/Rakefile CHANGED
@@ -1,6 +1,7 @@
1
- require 'bundler/gem_tasks'
1
+ require "bundler/gem_tasks"
2
2
 
3
- require 'rake/testtask'
3
+ require "rake/testtask"
4
+ require "standard/rake"
4
5
  Rake::TestTask.new
5
6
 
6
- task :default => :test
7
+ task default: :test
@@ -1,21 +1,20 @@
1
- # -*- encoding: utf-8 -*-
2
1
  require "./lib/connection_pool/version"
3
2
 
4
3
  Gem::Specification.new do |s|
5
- s.name = "connection_pool"
6
- s.version = ConnectionPool::VERSION
7
- s.platform = Gem::Platform::RUBY
8
- s.authors = ["Mike Perham", "Damian Janowski"]
9
- s.email = ["mperham@gmail.com", "damian@educabilia.com"]
10
- s.homepage = "https://github.com/mperham/connection_pool"
11
- s.description = s.summary = %q{Generic connection pool for Ruby}
4
+ s.name = "connection_pool"
5
+ s.version = ConnectionPool::VERSION
6
+ s.platform = Gem::Platform::RUBY
7
+ s.authors = ["Mike Perham", "Damian Janowski"]
8
+ s.email = ["mperham@gmail.com", "damian@educabilia.com"]
9
+ s.homepage = "https://github.com/mperham/connection_pool"
10
+ s.description = s.summary = "Generic connection pool for Ruby"
12
11
 
13
- s.files = `git ls-files`.split("\n")
14
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ s.files = `git ls-files`.split("\n")
13
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
16
15
  s.require_paths = ["lib"]
17
16
  s.license = "MIT"
18
- s.add_development_dependency 'bundler'
19
- s.add_development_dependency 'minitest', '>= 5.0.0'
20
- s.add_development_dependency 'rake'
17
+ s.add_development_dependency "bundler"
18
+ s.add_development_dependency "minitest", ">= 5.0.0"
19
+ s.add_development_dependency "rake"
21
20
  end
@@ -1,14 +1,18 @@
1
- require_relative 'connection_pool/version'
2
- require_relative 'connection_pool/timed_stack'
1
+ require "timeout"
2
+ require "connection_pool/version"
3
3
 
4
+ class ConnectionPool
5
+ class Error < ::RuntimeError; end
6
+ class PoolShuttingDownError < ::ConnectionPool::Error; end
7
+ class TimeoutError < ::Timeout::Error; end
8
+ end
4
9
 
5
- # Generic connection pool class for e.g. sharing a limited number of network connections
6
- # among many threads. Note: Connections are lazily created.
10
+ # Generic connection pool class for sharing a limited number of objects or network connections
11
+ # among many threads. Note: pool elements are lazily created.
7
12
  #
8
13
  # Example usage with block (faster):
9
14
  #
10
15
  # @pool = ConnectionPool.new { Redis.new }
11
- #
12
16
  # @pool.with do |redis|
13
17
  # redis.lpop('my-list') if redis.llen('my-list') > 0
14
18
  # end
@@ -34,29 +38,23 @@ require_relative 'connection_pool/timed_stack'
34
38
  class ConnectionPool
35
39
  DEFAULTS = {size: 5, timeout: 5}
36
40
 
37
- class Error < RuntimeError
38
- end
39
-
40
41
  def self.wrap(options, &block)
41
42
  Wrapper.new(options, &block)
42
43
  end
43
44
 
44
45
  def initialize(options = {}, &block)
45
- raise ArgumentError, 'Connection pool requires a block' unless block
46
+ raise ArgumentError, "Connection pool requires a block" unless block
46
47
 
47
48
  options = DEFAULTS.merge(options)
48
49
 
49
- @size = options.fetch(:size)
50
+ @size = Integer(options.fetch(:size))
50
51
  @timeout = options.fetch(:timeout)
51
52
 
52
53
  @available = TimedStack.new(@size, &block)
53
- @key = :"current-#{@available.object_id}"
54
- @key_count = :"current-#{@available.object_id}-count"
54
+ @key = :"pool-#{@available.object_id}"
55
+ @key_count = :"pool-#{@available.object_id}-count"
55
56
  end
56
57
 
57
- if Thread.respond_to?(:handle_interrupt)
58
-
59
- # MRI
60
58
  def with(options = {})
61
59
  Thread.handle_interrupt(Exception => :never) do
62
60
  conn = checkout(options)
@@ -70,27 +68,13 @@ if Thread.respond_to?(:handle_interrupt)
70
68
  end
71
69
  end
72
70
 
73
- else
74
-
75
- # jruby 1.7.x
76
- def with(options = {})
77
- conn = checkout(options)
78
- begin
79
- yield conn
80
- ensure
81
- checkin
82
- end
83
- end
84
-
85
- end
86
-
87
71
  def checkout(options = {})
88
72
  if ::Thread.current[@key]
89
- ::Thread.current[@key_count]+= 1
73
+ ::Thread.current[@key_count] += 1
90
74
  ::Thread.current[@key]
91
75
  else
92
- ::Thread.current[@key_count]= 1
93
- ::Thread.current[@key]= @available.pop(options[:timeout] || @timeout)
76
+ ::Thread.current[@key_count] = 1
77
+ ::Thread.current[@key] = @available.pop(options[:timeout] || @timeout)
94
78
  end
95
79
  end
96
80
 
@@ -98,12 +82,12 @@ end
98
82
  if ::Thread.current[@key]
99
83
  if ::Thread.current[@key_count] == 1
100
84
  @available.push(::Thread.current[@key])
101
- ::Thread.current[@key]= nil
85
+ ::Thread.current[@key] = nil
102
86
  else
103
- ::Thread.current[@key_count]-= 1
87
+ ::Thread.current[@key_count] -= 1
104
88
  end
105
89
  else
106
- raise ConnectionPool::Error, 'no connections are checked out'
90
+ raise ConnectionPool::Error, "no connections are checked out"
107
91
  end
108
92
 
109
93
  nil
@@ -114,48 +98,13 @@ end
114
98
  end
115
99
 
116
100
  # Size of this connection pool
117
- def size
118
- @size
119
- end
101
+ attr_reader :size
120
102
 
121
103
  # Number of pool entries available for checkout at this instant.
122
104
  def available
123
105
  @available.length
124
106
  end
125
-
126
- private
127
-
128
- class Wrapper < ::BasicObject
129
- METHODS = [:with, :pool_shutdown]
130
-
131
- def initialize(options = {}, &block)
132
- @pool = options.fetch(:pool) { ::ConnectionPool.new(options, &block) }
133
- end
134
-
135
- def with(&block)
136
- @pool.with(&block)
137
- end
138
-
139
- def pool_shutdown(&block)
140
- @pool.shutdown(&block)
141
- end
142
-
143
- def pool_size
144
- @pool.size
145
- end
146
-
147
- def pool_available
148
- @pool.available
149
- end
150
-
151
- def respond_to?(id, *args)
152
- METHODS.include?(id) || with { |c| c.respond_to?(id, *args) }
153
- end
154
-
155
- def method_missing(name, *args, &block)
156
- with do |connection|
157
- connection.send(name, *args, &block)
158
- end
159
- end
160
- end
161
107
  end
108
+
109
+ require "connection_pool/timed_stack"
110
+ require "connection_pool/wrapper"
@@ -1,13 +1,3 @@
1
- require 'thread'
2
- require 'timeout'
3
- require_relative 'monotonic_time'
4
-
5
- ##
6
- # Raised when you attempt to retrieve a connection from a pool that has been
7
- # shut down.
8
-
9
- class ConnectionPool::PoolShuttingDownError < RuntimeError; end
10
-
11
1
  ##
12
2
  # The TimedStack manages a pool of homogeneous connections (or any resource
13
3
  # you wish to manage). Connections are created lazily up to a given maximum
@@ -59,7 +49,7 @@ class ConnectionPool::TimedStack
59
49
  @resource.broadcast
60
50
  end
61
51
  end
62
- alias_method :<<, :push
52
+ alias << push
63
53
 
64
54
  ##
65
55
  # Retrieves a connection from the stack. If a connection is available it is
@@ -74,7 +64,7 @@ class ConnectionPool::TimedStack
74
64
  options, timeout = timeout, 0.5 if Hash === timeout
75
65
  timeout = options.fetch :timeout, timeout
76
66
 
77
- deadline = ConnectionPool.monotonic_time + timeout
67
+ deadline = current_time + timeout
78
68
  @mutex.synchronize do
79
69
  loop do
80
70
  raise ConnectionPool::PoolShuttingDownError if @shutdown_block
@@ -83,8 +73,8 @@ class ConnectionPool::TimedStack
83
73
  connection = try_create(options)
84
74
  return connection if connection
85
75
 
86
- to_wait = deadline - ConnectionPool.monotonic_time
87
- raise Timeout::Error, "Waited #{timeout} sec" if to_wait <= 0
76
+ to_wait = deadline - current_time
77
+ raise ConnectionPool::TimeoutError, "Waited #{timeout} sec" if to_wait <= 0
88
78
  @resource.wait(@mutex, to_wait)
89
79
  end
90
80
  end
@@ -121,6 +111,10 @@ class ConnectionPool::TimedStack
121
111
 
122
112
  private
123
113
 
114
+ def current_time
115
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
116
+ end
117
+
124
118
  ##
125
119
  # This is an extension point for TimedStack and is called with a mutex.
126
120
  #
@@ -1,3 +1,3 @@
1
1
  class ConnectionPool
2
- VERSION = "2.2.2"
2
+ VERSION = "2.2.3"
3
3
  end
@@ -0,0 +1,43 @@
1
+ class ConnectionPool
2
+ class Wrapper < ::BasicObject
3
+ METHODS = [:with, :pool_shutdown, :wrapped_pool]
4
+
5
+ def initialize(options = {}, &block)
6
+ @pool = options.fetch(:pool) { ::ConnectionPool.new(options, &block) }
7
+ end
8
+
9
+ def wrapped_pool
10
+ @pool
11
+ end
12
+
13
+ def with(&block)
14
+ @pool.with(&block)
15
+ end
16
+
17
+ def pool_shutdown(&block)
18
+ @pool.shutdown(&block)
19
+ end
20
+
21
+ def pool_size
22
+ @pool.size
23
+ end
24
+
25
+ def pool_available
26
+ @pool.available
27
+ end
28
+
29
+ def respond_to?(id, *args)
30
+ METHODS.include?(id) || with { |c| c.respond_to?(id, *args) }
31
+ end
32
+
33
+ # rubocop:disable Style/MethodMissingSuper
34
+ # rubocop:disable Style/MissingRespondToMissing
35
+ def method_missing(name, *args, &block)
36
+ with do |connection|
37
+ connection.send(name, *args, &block)
38
+ end
39
+ end
40
+ # rubocop:enable Style/MethodMissingSuper
41
+ # rubocop:enable Style/MissingRespondToMissing
42
+ end
43
+ end
@@ -1,8 +1,8 @@
1
- gem 'minitest'
1
+ gem "minitest"
2
2
 
3
- require 'minitest/pride'
4
- require 'minitest/autorun'
3
+ require "minitest/pride"
4
+ require "minitest/autorun"
5
5
 
6
6
  $VERBOSE = 1
7
7
 
8
- require_relative '../lib/connection_pool'
8
+ require_relative "../lib/connection_pool"
@@ -1,7 +1,6 @@
1
- require_relative 'helper'
1
+ require_relative "helper"
2
2
 
3
3
  class TestConnectionPool < Minitest::Test
4
-
5
4
  class NetworkConnection
6
5
  SLEEP_TIME = 0.1
7
6
 
@@ -43,12 +42,12 @@ class TestConnectionPool < Minitest::Test
43
42
  end
44
43
 
45
44
  def use_pool(pool, size)
46
- Array.new(size) do
45
+ Array.new(size) {
47
46
  Thread.new do
48
- pool.with do sleep end
47
+ pool.with { sleep }
49
48
  end
50
- end.each do |thread|
51
- Thread.pass until thread.status == 'sleep'
49
+ }.each do |thread|
50
+ Thread.pass until thread.status == "sleep"
52
51
  end
53
52
  end
54
53
 
@@ -67,13 +66,13 @@ class TestConnectionPool < Minitest::Test
67
66
 
68
67
  generations = 3
69
68
 
70
- result = Array.new(pool_size * generations) do
69
+ result = Array.new(pool_size * generations) {
71
70
  Thread.new do
72
71
  pool.with do |net|
73
72
  net.do_something
74
73
  end
75
74
  end
76
- end.map(&:value)
75
+ }.map(&:value)
77
76
 
78
77
  finish = Time.new
79
78
 
@@ -84,14 +83,14 @@ class TestConnectionPool < Minitest::Test
84
83
 
85
84
  def test_timeout
86
85
  pool = ConnectionPool.new(timeout: 0, size: 1) { NetworkConnection.new }
87
- thread = Thread.new do
86
+ thread = Thread.new {
88
87
  pool.with do |net|
89
88
  net.do_something
90
89
  sleep 0.01
91
90
  end
92
- end
91
+ }
93
92
 
94
- Thread.pass while thread.status == 'run'
93
+ Thread.pass while thread.status == "run"
95
94
 
96
95
  assert_raises Timeout::Error do
97
96
  pool.with { |net| net.do_something }
@@ -108,9 +107,11 @@ class TestConnectionPool < Minitest::Test
108
107
  pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
109
108
 
110
109
  pool.with do
111
- assert_raises Timeout::Error do
112
- Thread.new { pool.checkout }.join
113
- end
110
+ Thread.new {
111
+ assert_raises Timeout::Error do
112
+ pool.checkout
113
+ end
114
+ }.join
114
115
  end
115
116
 
116
117
  assert Thread.new { pool.checkout }.join
@@ -122,17 +123,24 @@ class TestConnectionPool < Minitest::Test
122
123
  assert_raises Timeout::Error do
123
124
  Timeout.timeout(0.01) do
124
125
  pool.with do |obj|
125
- assert_equal 0, pool.instance_variable_get(:@available).instance_variable_get(:@que).size
126
+ assert_equal 0, pool.available
126
127
  sleep 0.015
127
128
  end
128
129
  end
129
130
  end
130
- assert_equal 1, pool.instance_variable_get(:@available).instance_variable_get(:@que).size
131
+ assert_equal 1, pool.available
131
132
  end
132
133
 
133
- def test_checkout_ignores_timeout
134
- skip("Thread.handle_interrupt not available") unless Thread.respond_to?(:handle_interrupt)
134
+ def test_invalid_size
135
+ assert_raises ArgumentError, TypeError do
136
+ ConnectionPool.new(timeout: 0, size: nil) { Object.new }
137
+ end
138
+ assert_raises ArgumentError, TypeError do
139
+ ConnectionPool.new(timeout: 0, size: "") { Object.new }
140
+ end
141
+ end
135
142
 
143
+ def test_handle_interrupt_ensures_checkin
136
144
  pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
137
145
  def pool.checkout(options)
138
146
  sleep 0.015
@@ -140,7 +148,8 @@ class TestConnectionPool < Minitest::Test
140
148
  end
141
149
 
142
150
  did_something = false
143
- assert_raises Timeout::Error do
151
+
152
+ action = lambda do
144
153
  Timeout.timeout(0.01) do
145
154
  pool.with do |obj|
146
155
  did_something = true
@@ -152,18 +161,33 @@ class TestConnectionPool < Minitest::Test
152
161
  end
153
162
  end
154
163
  end
155
- assert did_something
156
- assert_equal 1, pool.instance_variable_get(:@available).instance_variable_get(:@que).size
164
+
165
+ if RUBY_ENGINE == "ruby"
166
+ # These asserts rely on the Ruby implementation reaching `did_something =
167
+ # true` before the interrupt is detected by the thread. Interrupt
168
+ # detection timing is implementation-specific in practice, with JRuby,
169
+ # Rubinius, and TruffleRuby all having different interrupt timings to MRI.
170
+ # In fact they generally detect interrupts more quickly than MRI, so they
171
+ # may not reach `did_something = true` before detecting the interrupt.
172
+
173
+ assert_raises Timeout::Error, &action
174
+
175
+ assert did_something
176
+ else
177
+ action.call
178
+ end
179
+
180
+ assert_equal 1, pool.available
157
181
  end
158
182
 
159
183
  def test_explicit_return
160
- pool = ConnectionPool.new(timeout: 0, size: 1) do
184
+ pool = ConnectionPool.new(timeout: 0, size: 1) {
161
185
  mock = Minitest::Mock.new
162
186
  def mock.disconnect!
163
187
  raise "should not disconnect upon explicit return"
164
188
  end
165
189
  mock
166
- end
190
+ }
167
191
 
168
192
  pool.with do |conn|
169
193
  return true
@@ -173,14 +197,14 @@ class TestConnectionPool < Minitest::Test
173
197
  def test_with_timeout_override
174
198
  pool = ConnectionPool.new(timeout: 0, size: 1) { NetworkConnection.new }
175
199
 
176
- t = Thread.new do
200
+ t = Thread.new {
177
201
  pool.with do |net|
178
202
  net.do_something
179
203
  sleep 0.01
180
204
  end
181
- end
205
+ }
182
206
 
183
- Thread.pass while t.status == 'run'
207
+ Thread.pass while t.status == "run"
184
208
 
185
209
  assert_raises Timeout::Error do
186
210
  pool.with { |net| net.do_something }
@@ -195,9 +219,11 @@ class TestConnectionPool < Minitest::Test
195
219
  pool = ConnectionPool.new(timeout: 0, size: 1) { NetworkConnection.new }
196
220
  conn = pool.checkout
197
221
 
198
- assert_raises Timeout::Error do
199
- Thread.new { pool.checkout }.join
200
- end
222
+ Thread.new {
223
+ assert_raises Timeout::Error do
224
+ pool.checkout
225
+ end
226
+ }.join
201
227
 
202
228
  pool.checkin
203
229
 
@@ -206,17 +232,14 @@ class TestConnectionPool < Minitest::Test
206
232
 
207
233
  def test_returns_value
208
234
  pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
209
- assert_equal 1, pool.with {|o| 1 }
235
+ assert_equal 1, pool.with { |o| 1 }
210
236
  end
211
237
 
212
238
  def test_checkin_never_checkout
213
239
  pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
214
240
 
215
- e = assert_raises ConnectionPool::Error do
216
- pool.checkin
217
- end
218
-
219
- assert_equal 'no connections are checked out', e.message
241
+ e = assert_raises(ConnectionPool::Error) { pool.checkin }
242
+ assert_equal "no connections are checked out", e.message
220
243
  end
221
244
 
222
245
  def test_checkin_no_current_checkout
@@ -238,11 +261,11 @@ class TestConnectionPool < Minitest::Test
238
261
 
239
262
  pool.checkin
240
263
 
241
- assert_raises Timeout::Error do
242
- Thread.new do
264
+ Thread.new {
265
+ assert_raises Timeout::Error do
243
266
  pool.checkout
244
- end.join
245
- end
267
+ end
268
+ }.join
246
269
 
247
270
  pool.checkin
248
271
 
@@ -263,9 +286,9 @@ class TestConnectionPool < Minitest::Test
263
286
  pool = ConnectionPool.new(size: 2) { NetworkConnection.new }
264
287
  conn = pool.checkout
265
288
 
266
- t = Thread.new do
289
+ t = Thread.new {
267
290
  pool.checkout
268
- end
291
+ }
269
292
 
270
293
  refute_same conn, t.value
271
294
  end
@@ -281,14 +304,14 @@ class TestConnectionPool < Minitest::Test
281
304
  def test_checkout_timeout_override
282
305
  pool = ConnectionPool.new(timeout: 0, size: 1) { NetworkConnection.new }
283
306
 
284
- thread = Thread.new do
307
+ thread = Thread.new {
285
308
  pool.with do |net|
286
309
  net.do_something
287
310
  sleep 0.01
288
311
  end
289
- end
312
+ }
290
313
 
291
- Thread.pass while thread.status == 'run'
314
+ Thread.pass while thread.status == "run"
292
315
 
293
316
  assert_raises Timeout::Error do
294
317
  pool.checkout
@@ -315,22 +338,22 @@ class TestConnectionPool < Minitest::Test
315
338
 
316
339
  def test_return_value
317
340
  pool = ConnectionPool.new(timeout: 2 * NetworkConnection::SLEEP_TIME, size: 1) { NetworkConnection.new }
318
- result = pool.with do |net|
341
+ result = pool.with { |net|
319
342
  net.fast
320
- end
343
+ }
321
344
  assert_equal 1, result
322
345
  end
323
346
 
324
347
  def test_heavy_threading
325
348
  pool = ConnectionPool.new(timeout: 0.5, size: 3) { NetworkConnection.new }
326
349
 
327
- threads = Array.new(20) do
350
+ threads = Array.new(20) {
328
351
  Thread.new do
329
352
  pool.with do |net|
330
353
  sleep 0.01
331
354
  end
332
355
  end
333
- end
356
+ }
334
357
 
335
358
  threads.map { |thread| thread.join }
336
359
  end
@@ -338,9 +361,9 @@ class TestConnectionPool < Minitest::Test
338
361
  def test_reuses_objects_when_pool_not_saturated
339
362
  pool = ConnectionPool.new(size: 5) { NetworkConnection.new }
340
363
 
341
- ids = 10.times.map do
364
+ ids = 10.times.map {
342
365
  pool.with { |c| c.object_id }
343
- end
366
+ }
344
367
 
345
368
  assert_equal 1, ids.uniq.size
346
369
  end
@@ -349,32 +372,32 @@ class TestConnectionPool < Minitest::Test
349
372
  recorder = Recorder.new
350
373
  pool = ConnectionPool.new(size: 1) { recorder }
351
374
  pool.with do |r_outer|
352
- @other = Thread.new do |t|
375
+ @other = Thread.new { |t|
353
376
  pool.with do |r_other|
354
- r_other.do_work('other')
377
+ r_other.do_work("other")
355
378
  end
356
- end
379
+ }
357
380
 
358
381
  pool.with do |r_inner|
359
- r_inner.do_work('inner')
382
+ r_inner.do_work("inner")
360
383
  end
361
384
 
362
385
  Thread.pass
363
386
 
364
- r_outer.do_work('outer')
387
+ r_outer.do_work("outer")
365
388
  end
366
389
 
367
390
  @other.join
368
391
 
369
- assert_equal ['inner', 'outer', 'other'], recorder.calls
392
+ assert_equal ["inner", "outer", "other"], recorder.calls
370
393
  end
371
394
 
372
395
  def test_shutdown_is_executed_for_all_connections
373
396
  recorders = []
374
397
 
375
- pool = ConnectionPool.new(size: 3) do
398
+ pool = ConnectionPool.new(size: 3) {
376
399
  Recorder.new.tap { |r| recorders << r }
377
- end
400
+ }
378
401
 
379
402
  threads = use_pool pool, 3
380
403
 
@@ -390,7 +413,7 @@ class TestConnectionPool < Minitest::Test
390
413
  def test_raises_error_after_shutting_down
391
414
  pool = ConnectionPool.new(size: 1) { true }
392
415
 
393
- pool.shutdown { }
416
+ pool.shutdown {}
394
417
 
395
418
  assert_raises ConnectionPool::PoolShuttingDownError do
396
419
  pool.checkout
@@ -400,9 +423,9 @@ class TestConnectionPool < Minitest::Test
400
423
  def test_runs_shutdown_block_asynchronously_if_connection_was_in_use
401
424
  recorders = []
402
425
 
403
- pool = ConnectionPool.new(size: 3) do
426
+ pool = ConnectionPool.new(size: 3) {
404
427
  Recorder.new.tap { |r| recorders << r }
405
- end
428
+ }
406
429
 
407
430
  threads = use_pool pool, 2
408
431
 
@@ -422,7 +445,7 @@ class TestConnectionPool < Minitest::Test
422
445
  end
423
446
 
424
447
  def test_raises_an_error_if_shutdown_is_called_without_a_block
425
- pool = ConnectionPool.new(size: 1) { }
448
+ pool = ConnectionPool.new(size: 1) {}
426
449
 
427
450
  assert_raises ArgumentError do
428
451
  pool.shutdown
@@ -432,9 +455,9 @@ class TestConnectionPool < Minitest::Test
432
455
  def test_shutdown_is_executed_for_all_connections_in_wrapped_pool
433
456
  recorders = []
434
457
 
435
- wrapper = ConnectionPool::Wrapper.new(size: 3) do
458
+ wrapper = ConnectionPool::Wrapper.new(size: 3) {
436
459
  Recorder.new.tap { |r| recorders << r }
437
- end
460
+ }
438
461
 
439
462
  threads = use_pool wrapper, 3
440
463
 
@@ -447,6 +470,11 @@ class TestConnectionPool < Minitest::Test
447
470
  assert_equal [["shutdown"]] * 3, recorders.map { |r| r.calls }
448
471
  end
449
472
 
473
+ def test_wrapper_wrapped_pool
474
+ wrapper = ConnectionPool::Wrapper.new { NetworkConnection.new }
475
+ assert_equal ConnectionPool, wrapper.wrapped_pool.class
476
+ end
477
+
450
478
  def test_wrapper_method_missing
451
479
  wrapper = ConnectionPool::Wrapper.new { NetworkConnection.new }
452
480
 
@@ -466,14 +494,14 @@ class TestConnectionPool < Minitest::Test
466
494
  wrapper = ConnectionPool::Wrapper.new(timeout: 0, size: 1) { Object.new }
467
495
 
468
496
  wrapper.with do
469
- assert_raises Timeout::Error do
470
- Thread.new do
471
- wrapper.with { flunk 'connection checked out :(' }
472
- end.join
473
- end
497
+ Thread.new {
498
+ assert_raises Timeout::Error do
499
+ wrapper.with { flunk "connection checked out :(" }
500
+ end
501
+ }.join
474
502
  end
475
503
 
476
- assert Thread.new { wrapper.with { } }.join
504
+ assert Thread.new { wrapper.with {} }.join
477
505
  end
478
506
 
479
507
  class ConnWithEval
@@ -493,10 +521,10 @@ class TestConnectionPool < Minitest::Test
493
521
  pool = ConnectionPool.new(size: 1) { recorder }
494
522
  wrapper = ConnectionPool::Wrapper.new(pool: pool)
495
523
 
496
- pool.with { |r| r.do_work('with') }
497
- wrapper.do_work('wrapped')
524
+ pool.with { |r| r.do_work("with") }
525
+ wrapper.do_work("wrapped")
498
526
 
499
- assert_equal ['with', 'wrapped'], recorder.calls
527
+ assert_equal ["with", "wrapped"], recorder.calls
500
528
  end
501
529
 
502
530
  def test_stats_without_active_connection
@@ -513,4 +541,13 @@ class TestConnectionPool < Minitest::Test
513
541
  assert_equal(1, pool.available)
514
542
  end
515
543
  end
544
+
545
+ def test_stats_with_string_size
546
+ pool = ConnectionPool.new(size: "2") { NetworkConnection.new }
547
+
548
+ pool.with do
549
+ assert_equal(2, pool.size)
550
+ assert_equal(1, pool.available)
551
+ end
552
+ end
516
553
  end
@@ -1,7 +1,6 @@
1
- require_relative 'helper'
1
+ require_relative "helper"
2
2
 
3
3
  class TestConnectionPoolTimedStack < Minitest::Test
4
-
5
4
  def setup
6
5
  @stack = ConnectionPool::TimedStack.new { Object.new }
7
6
  end
@@ -35,18 +34,18 @@ class TestConnectionPoolTimedStack < Minitest::Test
35
34
  end
36
35
 
37
36
  def test_object_creation_fails
38
- stack = ConnectionPool::TimedStack.new(2) { raise 'failure' }
37
+ stack = ConnectionPool::TimedStack.new(2) { raise "failure" }
39
38
 
40
39
  begin
41
40
  stack.pop
42
41
  rescue => error
43
- assert_equal 'failure', error.message
42
+ assert_equal "failure", error.message
44
43
  end
45
44
 
46
45
  begin
47
46
  stack.pop
48
47
  rescue => error
49
- assert_equal 'failure', error.message
48
+ assert_equal "failure", error.message
50
49
  end
51
50
 
52
51
  refute_empty stack
@@ -63,19 +62,13 @@ class TestConnectionPoolTimedStack < Minitest::Test
63
62
  end
64
63
 
65
64
  def test_pop_empty
66
- e = assert_raises Timeout::Error do
67
- @stack.pop timeout: 0
68
- end
69
-
70
- assert_equal 'Waited 0 sec', e.message
65
+ e = assert_raises(ConnectionPool::TimeoutError) { @stack.pop timeout: 0 }
66
+ assert_equal "Waited 0 sec", e.message
71
67
  end
72
68
 
73
69
  def test_pop_empty_2_0_compatibility
74
- e = assert_raises Timeout::Error do
75
- @stack.pop 0
76
- end
77
-
78
- assert_equal 'Waited 0 sec', e.message
70
+ e = assert_raises(Timeout::Error) { @stack.pop 0 }
71
+ assert_equal "Waited 0 sec", e.message
79
72
  end
80
73
 
81
74
  def test_pop_full
@@ -88,11 +81,11 @@ class TestConnectionPoolTimedStack < Minitest::Test
88
81
  end
89
82
 
90
83
  def test_pop_wait
91
- thread = Thread.start do
84
+ thread = Thread.start {
92
85
  @stack.pop
93
- end
86
+ }
94
87
 
95
- Thread.pass while thread.status == 'run'
88
+ Thread.pass while thread.status == "run"
96
89
 
97
90
  object = Object.new
98
91
 
@@ -102,7 +95,7 @@ class TestConnectionPoolTimedStack < Minitest::Test
102
95
  end
103
96
 
104
97
  def test_pop_shutdown
105
- @stack.shutdown { }
98
+ @stack.shutdown {}
106
99
 
107
100
  assert_raises ConnectionPool::PoolShuttingDownError do
108
101
  @stack.pop
@@ -144,6 +137,4 @@ class TestConnectionPoolTimedStack < Minitest::Test
144
137
  refute_empty called
145
138
  assert_empty @stack
146
139
  end
147
-
148
140
  end
149
-
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: 2.2.2
4
+ version: 2.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Perham
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-05-24 00:00:00.000000000 Z
12
+ date: 2020-06-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -70,9 +70,9 @@ files:
70
70
  - Rakefile
71
71
  - connection_pool.gemspec
72
72
  - lib/connection_pool.rb
73
- - lib/connection_pool/monotonic_time.rb
74
73
  - lib/connection_pool/timed_stack.rb
75
74
  - lib/connection_pool/version.rb
75
+ - lib/connection_pool/wrapper.rb
76
76
  - test/helper.rb
77
77
  - test/test_connection_pool.rb
78
78
  - test/test_connection_pool_timed_stack.rb
@@ -95,8 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  requirements: []
98
- rubyforge_project:
99
- rubygems_version: 2.6.13
98
+ rubygems_version: 3.1.2
100
99
  signing_key:
101
100
  specification_version: 4
102
101
  summary: Generic connection pool for Ruby
@@ -1,66 +0,0 @@
1
- # Global monotonic clock from Concurrent Ruby 1.0.
2
- # Copyright (c) Jerry D'Antonio -- released under the MIT license.
3
- # Slightly modified; used with permission.
4
- # https://github.com/ruby-concurrency/concurrent-ruby
5
-
6
- require 'thread'
7
-
8
- class ConnectionPool
9
-
10
- class_definition = Class.new do
11
-
12
- if defined?(Process::CLOCK_MONOTONIC)
13
-
14
- # @!visibility private
15
- def get_time
16
- Process.clock_gettime(Process::CLOCK_MONOTONIC)
17
- end
18
-
19
- elsif defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
20
-
21
- # @!visibility private
22
- def get_time
23
- java.lang.System.nanoTime() / 1_000_000_000.0
24
- end
25
-
26
- else
27
-
28
- # @!visibility private
29
- def initialize
30
- @mutex = Mutex.new
31
- @last_time = Time.now.to_f
32
- end
33
-
34
- # @!visibility private
35
- def get_time
36
- @mutex.synchronize do
37
- now = Time.now.to_f
38
- if @last_time < now
39
- @last_time = now
40
- else # clock has moved back in time
41
- @last_time += 0.000_001
42
- end
43
- end
44
- end
45
- end
46
- end
47
-
48
- ##
49
- # Clock that cannot be set and represents monotonic time since
50
- # some unspecified starting point.
51
- #
52
- # @!visibility private
53
- GLOBAL_MONOTONIC_CLOCK = class_definition.new
54
- private_constant :GLOBAL_MONOTONIC_CLOCK
55
-
56
- class << self
57
- ##
58
- # Returns the current time a tracked by the application monotonic clock.
59
- #
60
- # @return [Float] The current monotonic time when `since` not given else
61
- # the elapsed monotonic time between `since` and the current time
62
- def monotonic_time
63
- GLOBAL_MONOTONIC_CLOCK.get_time
64
- end
65
- end
66
- end