connection_pool 1.2.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +10 -0
- data/Changes.md +7 -1
- data/README.md +46 -39
- data/lib/connection_pool.rb +14 -5
- data/lib/connection_pool/timed_stack.rb +11 -4
- data/lib/connection_pool/version.rb +1 -1
- data/test/helper.rb +4 -0
- data/test/test_connection_pool.rb +207 -32
- data/test/test_connection_pool_timed_stack.rb +122 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b24f806aed835d638868cfeee4d30cd53b32c561
|
4
|
+
data.tar.gz: eeb809403e4ae18c350800712b97d9b65cff0194
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f815103822aaced056e316cf955a3d6a35fbb07b9e87d6f646e83a324e8c28aba570c55f0561ef94bcd76134670320f441c1141bcc2103f82843aa17d0ab42a2
|
7
|
+
data.tar.gz: d5883346fa243b8d0de199288722d4ec84092dbe4a8c984c33c4c48c3deb4f4ce0d11187be0a83941bac1231341b4a98f7f2d5968c6d4f5c159df6a15eddc365
|
data/.travis.yml
ADDED
data/Changes.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
2.0.0
|
2
|
+
-----
|
3
|
+
|
4
|
+
- The connection pool is now lazy. Connections are created as needed
|
5
|
+
and retained until the pool is shut down. [drbrain, #52]
|
6
|
+
|
1
7
|
1.2.0
|
2
8
|
-----
|
3
9
|
|
@@ -16,7 +22,7 @@ end
|
|
16
22
|
This method accepts a block and calls the block for each
|
17
23
|
connection in the pool. After calling this method, trying to get a
|
18
24
|
connection from the pool raises `PoolShuttingDownError`.
|
19
|
-
|
25
|
+
|
20
26
|
1.0.0
|
21
27
|
-----
|
22
28
|
|
data/README.md
CHANGED
@@ -1,40 +1,28 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
connection\_pool
|
2
|
+
=================
|
3
3
|
|
4
4
|
Generic connection pooling for Ruby.
|
5
5
|
|
6
|
-
MongoDB has its own connection pool. ActiveRecord has its own connection pool.
|
7
|
-
|
8
|
-
|
9
|
-
Install
|
10
|
-
------------
|
11
|
-
|
12
|
-
gem install connection_pool
|
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.
|
6
|
+
MongoDB has its own connection pool. ActiveRecord has its own connection pool.
|
7
|
+
This is a generic connection pool that can be used with anything, e.g. Redis,
|
8
|
+
Dalli and other Ruby network clients.
|
22
9
|
|
23
10
|
|
24
11
|
Usage
|
25
|
-
|
12
|
+
-----
|
26
13
|
|
27
|
-
Create a pool of objects to share amongst the fibers or threads in your Ruby
|
14
|
+
Create a pool of objects to share amongst the fibers or threads in your Ruby
|
15
|
+
application:
|
28
16
|
|
29
17
|
``` ruby
|
30
|
-
|
18
|
+
$memcached = ConnectionPool.new(size: 5, timeout: 5) { Dalli::Client.new }
|
31
19
|
```
|
32
20
|
|
33
21
|
Then use the pool in your application:
|
34
22
|
|
35
23
|
``` ruby
|
36
|
-
|
37
|
-
|
24
|
+
$memcached.with do |conn|
|
25
|
+
conn.get('some-count')
|
38
26
|
end
|
39
27
|
```
|
40
28
|
|
@@ -45,29 +33,30 @@ until one becomes available. If no object is available within `:timeout` second
|
|
45
33
|
Optionally, you can specify a timeout override using the with-block semantics:
|
46
34
|
|
47
35
|
``` ruby
|
48
|
-
|
49
|
-
|
36
|
+
$memcached.with(timeout: 2.0) do |conn|
|
37
|
+
conn.get('some-count')
|
50
38
|
end
|
51
39
|
```
|
52
40
|
|
53
|
-
This will only modify the resource-get timeout for this particular
|
54
|
-
is useful if you want to fail-fast on certain non critical
|
55
|
-
is not available, or conversely if you are comfortable
|
56
|
-
resource. This is not implemented in the below
|
41
|
+
This will only modify the resource-get timeout for this particular
|
42
|
+
invocation. This is useful if you want to fail-fast on certain non critical
|
43
|
+
sections when a resource is not available, or conversely if you are comfortable
|
44
|
+
blocking longer on a particular resource. This is not implemented in the below
|
45
|
+
`ConnectionPool::Wrapper` class.
|
57
46
|
|
58
|
-
You can use `ConnectionPool::Wrapper` to wrap a single global connection,
|
59
|
-
it easier to port your connection code over time:
|
47
|
+
You can use `ConnectionPool::Wrapper` to wrap a single global connection,
|
48
|
+
making it easier to port your connection code over time:
|
60
49
|
|
61
50
|
``` ruby
|
62
|
-
$redis = ConnectionPool::Wrapper.new(:
|
51
|
+
$redis = ConnectionPool::Wrapper.new(size: 5, timeout: 3) { Redis.connect }
|
63
52
|
$redis.sadd('foo', 1)
|
64
53
|
$redis.smembers('foo')
|
65
54
|
```
|
66
55
|
|
67
|
-
The
|
68
|
-
|
69
|
-
|
70
|
-
|
56
|
+
The wrapper uses `method_missing` to checkout a connection, run the requested
|
57
|
+
method and then immediately check the connection back into the pool. It's
|
58
|
+
**not** high-performance so you'll want to port your performance sensitive code
|
59
|
+
to use `with` as soon as possible.
|
71
60
|
|
72
61
|
``` ruby
|
73
62
|
$redis.with do |conn|
|
@@ -76,10 +65,28 @@ $redis.with do |conn|
|
|
76
65
|
end
|
77
66
|
```
|
78
67
|
|
79
|
-
Once you've ported your entire system to use `with`, you can simply
|
80
|
-
|
68
|
+
Once you've ported your entire system to use `with`, you can simply remove
|
69
|
+
`Wrapper` and use the simpler and faster `ConnectionPool`.
|
70
|
+
|
71
|
+
|
72
|
+
Notes
|
73
|
+
-----
|
74
|
+
|
75
|
+
- Connections are lazily created as needed.
|
76
|
+
- There is no provision for repairing or checking the health of a connection;
|
77
|
+
connections should be self-repairing. This is true of the Dalli and Redis
|
78
|
+
clients.
|
79
|
+
|
80
|
+
|
81
|
+
Install
|
82
|
+
-------
|
83
|
+
|
84
|
+
```
|
85
|
+
$ gem install connection_pool
|
86
|
+
```
|
87
|
+
|
81
88
|
|
82
89
|
Author
|
83
|
-
|
90
|
+
------
|
84
91
|
|
85
92
|
Mike Perham, [@mperham](https://twitter.com/mperham), <http://mikeperham.com>
|
data/lib/connection_pool.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_relative 'connection_pool/version'
|
2
|
+
require_relative 'connection_pool/timed_stack'
|
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.
|
@@ -33,6 +33,9 @@ require 'connection_pool/timed_stack'
|
|
33
33
|
class ConnectionPool
|
34
34
|
DEFAULTS = {size: 5, timeout: 5}
|
35
35
|
|
36
|
+
class Error < RuntimeError
|
37
|
+
end
|
38
|
+
|
36
39
|
def self.wrap(options, &block)
|
37
40
|
Wrapper.new(options, &block)
|
38
41
|
end
|
@@ -74,6 +77,9 @@ class ConnectionPool
|
|
74
77
|
|
75
78
|
def checkin
|
76
79
|
stack = ::Thread.current[@key]
|
80
|
+
raise ConnectionPool::Error, 'no connections are checked out' if
|
81
|
+
!stack || stack.empty?
|
82
|
+
|
77
83
|
conn = stack.pop
|
78
84
|
if stack.empty?
|
79
85
|
@available << conn
|
@@ -93,9 +99,12 @@ class ConnectionPool
|
|
93
99
|
end
|
94
100
|
|
95
101
|
def with
|
96
|
-
|
97
|
-
|
98
|
-
|
102
|
+
conn = @pool.checkout
|
103
|
+
begin
|
104
|
+
yield conn
|
105
|
+
ensure
|
106
|
+
@pool.checkin
|
107
|
+
end
|
99
108
|
end
|
100
109
|
|
101
110
|
def pool_shutdown(&block)
|
@@ -5,8 +5,11 @@ class ConnectionPool::PoolShuttingDownError < RuntimeError; end
|
|
5
5
|
|
6
6
|
class ConnectionPool::TimedStack
|
7
7
|
|
8
|
-
def initialize(size = 0)
|
9
|
-
@
|
8
|
+
def initialize(size = 0, &block)
|
9
|
+
@create_block = block
|
10
|
+
@created = 0
|
11
|
+
@que = []
|
12
|
+
@max = size
|
10
13
|
@mutex = Mutex.new
|
11
14
|
@resource = ConditionVariable.new
|
12
15
|
@shutdown_block = nil
|
@@ -31,6 +34,10 @@ class ConnectionPool::TimedStack
|
|
31
34
|
loop do
|
32
35
|
raise ConnectionPool::PoolShuttingDownError if @shutdown_block
|
33
36
|
return @que.pop unless @que.empty?
|
37
|
+
unless @created == @max
|
38
|
+
@created += 1
|
39
|
+
return @create_block.call
|
40
|
+
end
|
34
41
|
to_wait = deadline - Time.now
|
35
42
|
raise Timeout::Error, "Waited #{timeout} sec" if to_wait <= 0
|
36
43
|
@resource.wait(@mutex, to_wait)
|
@@ -53,10 +60,10 @@ class ConnectionPool::TimedStack
|
|
53
60
|
end
|
54
61
|
|
55
62
|
def empty?
|
56
|
-
@que.
|
63
|
+
(@created - @que.length) >= @max
|
57
64
|
end
|
58
65
|
|
59
66
|
def length
|
60
|
-
@que.length
|
67
|
+
@max - @created + @que.length
|
61
68
|
end
|
62
69
|
end
|
data/test/helper.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
require 'helper'
|
1
|
+
require_relative 'helper'
|
3
2
|
|
4
3
|
class TestConnectionPool < Minitest::Test
|
5
4
|
|
@@ -41,11 +40,24 @@ class TestConnectionPool < Minitest::Test
|
|
41
40
|
end
|
42
41
|
end
|
43
42
|
|
43
|
+
def use_pool(pool, size)
|
44
|
+
Array.new(size) do
|
45
|
+
Thread.new do
|
46
|
+
pool.with do sleep end
|
47
|
+
end
|
48
|
+
end.each do |thread|
|
49
|
+
Thread.pass until thread.status == 'sleep'
|
50
|
+
end.map do |thread|
|
51
|
+
thread.kill
|
52
|
+
Thread.pass while thread.alive?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
44
56
|
def test_basic_multithreaded_usage
|
45
57
|
pool = ConnectionPool.new(:size => 5) { NetworkConnection.new }
|
46
|
-
|
47
|
-
15
|
48
|
-
|
58
|
+
|
59
|
+
threads = Array.new(15) do
|
60
|
+
Thread.new do
|
49
61
|
pool.with do |net|
|
50
62
|
net.do_something
|
51
63
|
end
|
@@ -60,56 +72,169 @@ class TestConnectionPool < Minitest::Test
|
|
60
72
|
end
|
61
73
|
|
62
74
|
def test_timeout
|
63
|
-
pool = ConnectionPool.new(:timeout => 0
|
64
|
-
Thread.new do
|
75
|
+
pool = ConnectionPool.new(:timeout => 0, :size => 1) { NetworkConnection.new }
|
76
|
+
thread = Thread.new do
|
65
77
|
pool.with do |net|
|
66
78
|
net.do_something
|
67
|
-
sleep 0.
|
79
|
+
sleep 0.01
|
68
80
|
end
|
69
81
|
end
|
70
|
-
|
82
|
+
|
83
|
+
Thread.pass while thread.status == 'run'
|
84
|
+
|
71
85
|
assert_raises Timeout::Error do
|
72
86
|
pool.with { |net| net.do_something }
|
73
87
|
end
|
74
88
|
|
75
|
-
|
89
|
+
thread.join
|
90
|
+
|
76
91
|
pool.with do |conn|
|
77
92
|
refute_nil conn
|
78
93
|
end
|
79
94
|
end
|
80
|
-
|
81
|
-
def
|
82
|
-
pool = ConnectionPool.new(:timeout => 0
|
83
|
-
|
95
|
+
|
96
|
+
def test_with
|
97
|
+
pool = ConnectionPool.new(:timeout => 0, :size => 1) { Object.new }
|
98
|
+
|
99
|
+
pool.with do
|
100
|
+
assert_raises Timeout::Error do
|
101
|
+
Thread.new { pool.checkout }.join
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
assert Thread.new { pool.checkout }.join
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_with_timeout_override
|
109
|
+
pool = ConnectionPool.new(:timeout => 0, :size => 1) { NetworkConnection.new }
|
110
|
+
|
111
|
+
t = Thread.new do
|
84
112
|
pool.with do |net|
|
85
113
|
net.do_something
|
86
|
-
sleep 0.
|
114
|
+
sleep 0.01
|
87
115
|
end
|
88
116
|
end
|
89
|
-
|
117
|
+
|
118
|
+
Thread.pass while t.status == 'run'
|
119
|
+
|
90
120
|
assert_raises Timeout::Error do
|
91
121
|
pool.with { |net| net.do_something }
|
92
|
-
end
|
93
|
-
|
122
|
+
end
|
123
|
+
|
124
|
+
pool.with(:timeout => 0.1) do |conn|
|
94
125
|
refute_nil conn
|
95
|
-
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_checkin
|
130
|
+
pool = ConnectionPool.new(:timeout => 0, :size => 1) { NetworkConnection.new }
|
131
|
+
conn = pool.checkout
|
132
|
+
|
133
|
+
t1 = Thread.new do
|
134
|
+
pool.checkout
|
135
|
+
end
|
136
|
+
|
137
|
+
assert_raises Timeout::Error do
|
138
|
+
t1.join
|
139
|
+
end
|
140
|
+
|
141
|
+
pool.checkin
|
142
|
+
|
143
|
+
t2 = Thread.new do
|
144
|
+
pool.checkout
|
145
|
+
end
|
146
|
+
|
147
|
+
assert_same conn, t2.value
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_checkin_never_checkout
|
151
|
+
pool = ConnectionPool.new(:timeout => 0, :size => 1) { Object.new }
|
152
|
+
|
153
|
+
e = assert_raises ConnectionPool::Error do
|
154
|
+
pool.checkin
|
155
|
+
end
|
156
|
+
|
157
|
+
assert_equal 'no connections are checked out', e.message
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_checkin_no_current_checkout
|
161
|
+
pool = ConnectionPool.new(:timeout => 0, :size => 1) { Object.new }
|
162
|
+
|
163
|
+
pool.checkout
|
164
|
+
pool.checkin
|
165
|
+
|
166
|
+
assert_raises ConnectionPool::Error do
|
167
|
+
pool.checkin
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def test_checkin_twice
|
172
|
+
pool = ConnectionPool.new(:timeout => 0, :size => 1) { Object.new }
|
173
|
+
|
174
|
+
pool.checkout
|
175
|
+
pool.checkout
|
176
|
+
|
177
|
+
pool.checkin
|
178
|
+
|
179
|
+
assert_raises Timeout::Error do
|
180
|
+
Thread.new do
|
181
|
+
pool.checkout
|
182
|
+
end.join
|
183
|
+
end
|
184
|
+
|
185
|
+
pool.checkin
|
186
|
+
|
187
|
+
assert Thread.new { pool.checkout }.join
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_checkout
|
191
|
+
pool = ConnectionPool.new(:size => 1) { NetworkConnection.new }
|
192
|
+
|
193
|
+
conn = pool.checkout
|
194
|
+
|
195
|
+
assert_kind_of NetworkConnection, conn
|
196
|
+
|
197
|
+
assert_same conn, pool.checkout
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_checkout_multithread
|
201
|
+
pool = ConnectionPool.new(:size => 2) { NetworkConnection.new }
|
202
|
+
conn = pool.checkout
|
203
|
+
|
204
|
+
t = Thread.new do
|
205
|
+
pool.checkout
|
206
|
+
end
|
207
|
+
|
208
|
+
refute_same conn, t.value
|
209
|
+
end
|
210
|
+
|
211
|
+
def test_checkout_timeout
|
212
|
+
pool = ConnectionPool.new(:timeout => 0, :size => 0) { Object.new }
|
213
|
+
|
214
|
+
assert_raises Timeout::Error do
|
215
|
+
pool.checkout
|
216
|
+
end
|
96
217
|
end
|
97
218
|
|
98
219
|
def test_checkout_timeout_override
|
99
|
-
pool = ConnectionPool.new(:timeout => 0
|
100
|
-
|
220
|
+
pool = ConnectionPool.new(:timeout => 0, :size => 1) { NetworkConnection.new }
|
221
|
+
|
222
|
+
thread = Thread.new do
|
101
223
|
pool.with do |net|
|
102
224
|
net.do_something
|
103
|
-
sleep 0.
|
225
|
+
sleep 0.01
|
104
226
|
end
|
105
|
-
end
|
106
|
-
|
227
|
+
end
|
228
|
+
|
229
|
+
Thread.pass while thread.status == 'run'
|
230
|
+
|
107
231
|
assert_raises Timeout::Error do
|
108
|
-
pool.checkout
|
232
|
+
pool.checkout
|
109
233
|
end
|
110
|
-
|
234
|
+
|
235
|
+
assert pool.checkout :timeout => 0.1
|
111
236
|
end
|
112
|
-
|
237
|
+
|
113
238
|
def test_passthru
|
114
239
|
pool = ConnectionPool.wrap(:timeout => 0.1, :size => 1) { NetworkConnection.new }
|
115
240
|
assert_equal 1, pool.do_something
|
@@ -136,14 +261,16 @@ class TestConnectionPool < Minitest::Test
|
|
136
261
|
|
137
262
|
def test_heavy_threading
|
138
263
|
pool = ConnectionPool.new(:timeout => 0.5, :size => 3) { NetworkConnection.new }
|
139
|
-
|
264
|
+
|
265
|
+
threads = Array.new(20) do
|
140
266
|
Thread.new do
|
141
267
|
pool.with do |net|
|
142
|
-
sleep 0.
|
268
|
+
sleep 0.01
|
143
269
|
end
|
144
270
|
end
|
145
271
|
end
|
146
|
-
|
272
|
+
|
273
|
+
threads.map { |thread| thread.join }
|
147
274
|
end
|
148
275
|
|
149
276
|
def test_reuses_objects_when_pool_not_saturated
|
@@ -170,7 +297,7 @@ class TestConnectionPool < Minitest::Test
|
|
170
297
|
r_inner.do_work('inner')
|
171
298
|
end
|
172
299
|
|
173
|
-
|
300
|
+
Thread.pass
|
174
301
|
|
175
302
|
r_outer.do_work('outer')
|
176
303
|
end
|
@@ -187,6 +314,8 @@ class TestConnectionPool < Minitest::Test
|
|
187
314
|
Recorder.new.tap { |r| recorders << r }
|
188
315
|
end
|
189
316
|
|
317
|
+
use_pool pool, 3
|
318
|
+
|
190
319
|
pool.shutdown do |recorder|
|
191
320
|
recorder.do_work("shutdown")
|
192
321
|
end
|
@@ -211,13 +340,15 @@ class TestConnectionPool < Minitest::Test
|
|
211
340
|
Recorder.new.tap { |r| recorders << r }
|
212
341
|
end
|
213
342
|
|
343
|
+
use_pool pool, 3
|
344
|
+
|
214
345
|
pool.checkout
|
215
346
|
|
216
347
|
pool.shutdown do |recorder|
|
217
348
|
recorder.do_work("shutdown")
|
218
349
|
end
|
219
350
|
|
220
|
-
assert_equal [[
|
351
|
+
assert_equal [[], ["shutdown"], ["shutdown"]], recorders.map { |r| r.calls }.sort
|
221
352
|
|
222
353
|
pool.checkin
|
223
354
|
|
@@ -239,10 +370,54 @@ class TestConnectionPool < Minitest::Test
|
|
239
370
|
Recorder.new.tap { |r| recorders << r }
|
240
371
|
end
|
241
372
|
|
373
|
+
use_pool wrapper, 3
|
374
|
+
|
242
375
|
wrapper.pool_shutdown do |recorder|
|
243
376
|
recorder.do_work("shutdown")
|
244
377
|
end
|
245
378
|
|
246
379
|
assert_equal [["shutdown"]] * 3, recorders.map { |r| r.calls }
|
247
380
|
end
|
381
|
+
|
382
|
+
def test_wrapper_method_missing
|
383
|
+
wrapper = ConnectionPool::Wrapper.new { NetworkConnection.new }
|
384
|
+
|
385
|
+
assert_equal 1, wrapper.fast
|
386
|
+
end
|
387
|
+
|
388
|
+
def test_wrapper_respond_to_eh
|
389
|
+
wrapper = ConnectionPool::Wrapper.new { NetworkConnection.new }
|
390
|
+
|
391
|
+
assert_respond_to wrapper, :with
|
392
|
+
|
393
|
+
assert_respond_to wrapper, :fast
|
394
|
+
refute_respond_to wrapper, :"nonexistent method"
|
395
|
+
end
|
396
|
+
|
397
|
+
def test_wrapper_with
|
398
|
+
wrapper = ConnectionPool::Wrapper.new(:timeout => 0, :size => 1) { Object.new }
|
399
|
+
|
400
|
+
wrapper.with do
|
401
|
+
assert_raises Timeout::Error do
|
402
|
+
Thread.new do
|
403
|
+
wrapper.with { flunk 'connection checked out :(' }
|
404
|
+
end.join
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
assert Thread.new { wrapper.with { } }.join
|
409
|
+
end
|
410
|
+
|
411
|
+
class ConnWithEval
|
412
|
+
def eval(arg)
|
413
|
+
"eval'ed #{arg}"
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
def test_wrapper_kernel_methods
|
418
|
+
wrapper = ConnectionPool::Wrapper.new(timeout: 0, size: 1) { ConnWithEval.new }
|
419
|
+
|
420
|
+
assert_equal "eval'ed 1", wrapper.eval(1)
|
421
|
+
end
|
422
|
+
|
248
423
|
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require_relative 'helper'
|
2
|
+
|
3
|
+
class TestConnectionPoolTimedStack < Minitest::Test
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@stack = ConnectionPool::TimedStack.new { Object.new }
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_empty_eh
|
10
|
+
stack = ConnectionPool::TimedStack.new(1) { Object.new }
|
11
|
+
|
12
|
+
refute_empty stack
|
13
|
+
|
14
|
+
popped = stack.pop
|
15
|
+
|
16
|
+
assert_empty stack
|
17
|
+
|
18
|
+
stack.push popped
|
19
|
+
|
20
|
+
refute_empty stack
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_length
|
24
|
+
stack = ConnectionPool::TimedStack.new(1) { Object.new }
|
25
|
+
|
26
|
+
assert_equal 1, stack.length
|
27
|
+
|
28
|
+
popped = stack.pop
|
29
|
+
|
30
|
+
assert_equal 0, stack.length
|
31
|
+
|
32
|
+
stack.push popped
|
33
|
+
|
34
|
+
assert_equal 1, stack.length
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_pop
|
38
|
+
object = Object.new
|
39
|
+
@stack.push object
|
40
|
+
|
41
|
+
popped = @stack.pop
|
42
|
+
|
43
|
+
assert_same object, popped
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_pop_empty
|
47
|
+
e = assert_raises Timeout::Error do
|
48
|
+
@stack.pop 0
|
49
|
+
end
|
50
|
+
|
51
|
+
assert_equal 'Waited 0 sec', e.message
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_pop_full
|
55
|
+
stack = ConnectionPool::TimedStack.new(1) { Object.new }
|
56
|
+
|
57
|
+
popped = stack.pop
|
58
|
+
|
59
|
+
refute_nil popped
|
60
|
+
assert_empty stack
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_pop_wait
|
64
|
+
thread = Thread.start do
|
65
|
+
@stack.pop
|
66
|
+
end
|
67
|
+
|
68
|
+
Thread.pass while thread.status == 'run'
|
69
|
+
|
70
|
+
object = Object.new
|
71
|
+
|
72
|
+
@stack.push object
|
73
|
+
|
74
|
+
assert_same object, thread.value
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_pop_shutdown
|
78
|
+
@stack.shutdown { }
|
79
|
+
|
80
|
+
assert_raises ConnectionPool::PoolShuttingDownError do
|
81
|
+
@stack.pop
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_push
|
86
|
+
stack = ConnectionPool::TimedStack.new(1) { Object.new }
|
87
|
+
|
88
|
+
conn = stack.pop
|
89
|
+
|
90
|
+
stack.push conn
|
91
|
+
|
92
|
+
refute_empty stack
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_push_shutdown
|
96
|
+
called = []
|
97
|
+
|
98
|
+
@stack.shutdown do |object|
|
99
|
+
called << object
|
100
|
+
end
|
101
|
+
|
102
|
+
@stack.push Object.new
|
103
|
+
|
104
|
+
refute_empty called
|
105
|
+
assert_empty @stack
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_shutdown
|
109
|
+
@stack.push Object.new
|
110
|
+
|
111
|
+
called = []
|
112
|
+
|
113
|
+
@stack.shutdown do |object|
|
114
|
+
called << object
|
115
|
+
end
|
116
|
+
|
117
|
+
refute_empty called
|
118
|
+
assert_empty @stack
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
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:
|
4
|
+
version: 2.0.0
|
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:
|
12
|
+
date: 2014-03-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: minitest
|
@@ -48,6 +48,7 @@ extensions: []
|
|
48
48
|
extra_rdoc_files: []
|
49
49
|
files:
|
50
50
|
- .gitignore
|
51
|
+
- .travis.yml
|
51
52
|
- Changes.md
|
52
53
|
- Gemfile
|
53
54
|
- LICENSE
|
@@ -59,6 +60,7 @@ files:
|
|
59
60
|
- lib/connection_pool/version.rb
|
60
61
|
- test/helper.rb
|
61
62
|
- test/test_connection_pool.rb
|
63
|
+
- test/test_connection_pool_timed_stack.rb
|
62
64
|
homepage: https://github.com/mperham/connection_pool
|
63
65
|
licenses:
|
64
66
|
- MIT
|
@@ -79,10 +81,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
79
81
|
version: '0'
|
80
82
|
requirements: []
|
81
83
|
rubyforge_project:
|
82
|
-
rubygems_version: 2.
|
84
|
+
rubygems_version: 2.0.14
|
83
85
|
signing_key:
|
84
86
|
specification_version: 4
|
85
87
|
summary: Generic connection pool for Ruby
|
86
88
|
test_files:
|
87
89
|
- test/helper.rb
|
88
90
|
- test/test_connection_pool.rb
|
91
|
+
- test/test_connection_pool_timed_stack.rb
|