connection_pool 2.2.0 → 2.2.5
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 +5 -5
- data/.github/workflows/ci.yml +26 -0
- data/Changes.md +32 -2
- data/README.md +54 -20
- data/Rakefile +3 -3
- data/connection_pool.gemspec +14 -14
- data/lib/connection_pool.rb +50 -72
- data/lib/connection_pool/timed_stack.rb +18 -18
- data/lib/connection_pool/version.rb +1 -1
- data/lib/connection_pool/wrapper.rb +57 -0
- data/test/helper.rb +4 -4
- data/test/test_connection_pool.rb +187 -104
- data/test/test_connection_pool_timed_stack.rb +22 -21
- metadata +9 -9
- data/.travis.yml +0 -14
@@ -0,0 +1,57 @@
|
|
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
|
+
if ::RUBY_VERSION >= "3.0.0"
|
36
|
+
def method_missing(name, *args, **kwargs, &block)
|
37
|
+
with do |connection|
|
38
|
+
connection.send(name, *args, **kwargs, &block)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
elsif ::RUBY_VERSION >= "2.7.0"
|
42
|
+
ruby2_keywords def method_missing(name, *args, &block)
|
43
|
+
with do |connection|
|
44
|
+
connection.send(name, *args, &block)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
else
|
48
|
+
def method_missing(name, *args, &block)
|
49
|
+
with do |connection|
|
50
|
+
connection.send(name, *args, &block)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
# rubocop:enable Style/MethodMissingSuper
|
55
|
+
# rubocop:enable Style/MissingRespondToMissing
|
56
|
+
end
|
57
|
+
end
|
data/test/helper.rb
CHANGED
@@ -1,15 +1,22 @@
|
|
1
|
-
require_relative
|
1
|
+
require_relative "helper"
|
2
2
|
|
3
3
|
class TestConnectionPool < Minitest::Test
|
4
|
-
|
5
4
|
class NetworkConnection
|
5
|
+
SLEEP_TIME = 0.1
|
6
|
+
|
6
7
|
def initialize
|
7
8
|
@x = 0
|
8
9
|
end
|
9
10
|
|
10
|
-
def do_something
|
11
|
-
@x +=
|
12
|
-
sleep
|
11
|
+
def do_something(*_args, increment: 1)
|
12
|
+
@x += increment
|
13
|
+
sleep SLEEP_TIME
|
14
|
+
@x
|
15
|
+
end
|
16
|
+
|
17
|
+
def do_something_with_positional_hash(options)
|
18
|
+
@x += options[:increment] || 1
|
19
|
+
sleep SLEEP_TIME
|
13
20
|
@x
|
14
21
|
end
|
15
22
|
|
@@ -19,7 +26,7 @@ class TestConnectionPool < Minitest::Test
|
|
19
26
|
|
20
27
|
def do_something_with_block
|
21
28
|
@x += yield
|
22
|
-
sleep
|
29
|
+
sleep SLEEP_TIME
|
23
30
|
@x
|
24
31
|
end
|
25
32
|
|
@@ -41,12 +48,12 @@ class TestConnectionPool < Minitest::Test
|
|
41
48
|
end
|
42
49
|
|
43
50
|
def use_pool(pool, size)
|
44
|
-
Array.new(size)
|
51
|
+
Array.new(size) {
|
45
52
|
Thread.new do
|
46
|
-
pool.with
|
53
|
+
pool.with { sleep }
|
47
54
|
end
|
48
|
-
|
49
|
-
Thread.pass until thread.status ==
|
55
|
+
}.each do |thread|
|
56
|
+
Thread.pass until thread.status == "sleep"
|
50
57
|
end
|
51
58
|
end
|
52
59
|
|
@@ -58,33 +65,38 @@ class TestConnectionPool < Minitest::Test
|
|
58
65
|
end
|
59
66
|
|
60
67
|
def test_basic_multithreaded_usage
|
61
|
-
|
68
|
+
pool_size = 5
|
69
|
+
pool = ConnectionPool.new(size: pool_size) { NetworkConnection.new }
|
70
|
+
|
71
|
+
start = Time.new
|
72
|
+
|
73
|
+
generations = 3
|
62
74
|
|
63
|
-
|
75
|
+
result = Array.new(pool_size * generations) {
|
64
76
|
Thread.new do
|
65
77
|
pool.with do |net|
|
66
78
|
net.do_something
|
67
79
|
end
|
68
80
|
end
|
69
|
-
|
81
|
+
}.map(&:value)
|
82
|
+
|
83
|
+
finish = Time.new
|
70
84
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
assert_operator((b - a), :>, 0.125)
|
75
|
-
assert_equal([1,2,3].cycle(5).sort, result.sort)
|
85
|
+
assert_equal((1..generations).cycle(pool_size).sort, result.sort)
|
86
|
+
|
87
|
+
assert_operator(finish - start, :>, generations * NetworkConnection::SLEEP_TIME)
|
76
88
|
end
|
77
89
|
|
78
90
|
def test_timeout
|
79
|
-
pool = ConnectionPool.new(:
|
80
|
-
thread = Thread.new
|
91
|
+
pool = ConnectionPool.new(timeout: 0, size: 1) { NetworkConnection.new }
|
92
|
+
thread = Thread.new {
|
81
93
|
pool.with do |net|
|
82
94
|
net.do_something
|
83
95
|
sleep 0.01
|
84
96
|
end
|
85
|
-
|
97
|
+
}
|
86
98
|
|
87
|
-
Thread.pass while thread.status ==
|
99
|
+
Thread.pass while thread.status == "run"
|
88
100
|
|
89
101
|
assert_raises Timeout::Error do
|
90
102
|
pool.with { |net| net.do_something }
|
@@ -98,42 +110,58 @@ class TestConnectionPool < Minitest::Test
|
|
98
110
|
end
|
99
111
|
|
100
112
|
def test_with
|
101
|
-
pool = ConnectionPool.new(:
|
113
|
+
pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
|
102
114
|
|
103
115
|
pool.with do
|
104
|
-
|
105
|
-
|
106
|
-
|
116
|
+
Thread.new {
|
117
|
+
assert_raises Timeout::Error do
|
118
|
+
pool.checkout
|
119
|
+
end
|
120
|
+
}.join
|
107
121
|
end
|
108
122
|
|
109
123
|
assert Thread.new { pool.checkout }.join
|
110
124
|
end
|
111
125
|
|
126
|
+
def test_then
|
127
|
+
pool = ConnectionPool.new { Object.new }
|
128
|
+
|
129
|
+
assert_equal pool.method(:then), pool.method(:with)
|
130
|
+
end
|
131
|
+
|
112
132
|
def test_with_timeout
|
113
|
-
pool = ConnectionPool.new(:
|
133
|
+
pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
|
114
134
|
|
115
135
|
assert_raises Timeout::Error do
|
116
136
|
Timeout.timeout(0.01) do
|
117
137
|
pool.with do |obj|
|
118
|
-
assert_equal 0, pool.
|
138
|
+
assert_equal 0, pool.available
|
119
139
|
sleep 0.015
|
120
140
|
end
|
121
141
|
end
|
122
142
|
end
|
123
|
-
assert_equal 1, pool.
|
143
|
+
assert_equal 1, pool.available
|
124
144
|
end
|
125
145
|
|
126
|
-
def
|
127
|
-
|
146
|
+
def test_invalid_size
|
147
|
+
assert_raises ArgumentError, TypeError do
|
148
|
+
ConnectionPool.new(timeout: 0, size: nil) { Object.new }
|
149
|
+
end
|
150
|
+
assert_raises ArgumentError, TypeError do
|
151
|
+
ConnectionPool.new(timeout: 0, size: "") { Object.new }
|
152
|
+
end
|
153
|
+
end
|
128
154
|
|
129
|
-
|
155
|
+
def test_handle_interrupt_ensures_checkin
|
156
|
+
pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
|
130
157
|
def pool.checkout(options)
|
131
158
|
sleep 0.015
|
132
159
|
super
|
133
160
|
end
|
134
161
|
|
135
162
|
did_something = false
|
136
|
-
|
163
|
+
|
164
|
+
action = lambda do
|
137
165
|
Timeout.timeout(0.01) do
|
138
166
|
pool.with do |obj|
|
139
167
|
did_something = true
|
@@ -145,18 +173,33 @@ class TestConnectionPool < Minitest::Test
|
|
145
173
|
end
|
146
174
|
end
|
147
175
|
end
|
148
|
-
|
149
|
-
|
176
|
+
|
177
|
+
if RUBY_ENGINE == "ruby"
|
178
|
+
# These asserts rely on the Ruby implementation reaching `did_something =
|
179
|
+
# true` before the interrupt is detected by the thread. Interrupt
|
180
|
+
# detection timing is implementation-specific in practice, with JRuby,
|
181
|
+
# Rubinius, and TruffleRuby all having different interrupt timings to MRI.
|
182
|
+
# In fact they generally detect interrupts more quickly than MRI, so they
|
183
|
+
# may not reach `did_something = true` before detecting the interrupt.
|
184
|
+
|
185
|
+
assert_raises Timeout::Error, &action
|
186
|
+
|
187
|
+
assert did_something
|
188
|
+
else
|
189
|
+
action.call
|
190
|
+
end
|
191
|
+
|
192
|
+
assert_equal 1, pool.available
|
150
193
|
end
|
151
194
|
|
152
195
|
def test_explicit_return
|
153
|
-
pool = ConnectionPool.new(:
|
196
|
+
pool = ConnectionPool.new(timeout: 0, size: 1) {
|
154
197
|
mock = Minitest::Mock.new
|
155
198
|
def mock.disconnect!
|
156
199
|
raise "should not disconnect upon explicit return"
|
157
200
|
end
|
158
201
|
mock
|
159
|
-
|
202
|
+
}
|
160
203
|
|
161
204
|
pool.with do |conn|
|
162
205
|
return true
|
@@ -164,33 +207,35 @@ class TestConnectionPool < Minitest::Test
|
|
164
207
|
end
|
165
208
|
|
166
209
|
def test_with_timeout_override
|
167
|
-
pool = ConnectionPool.new(:
|
210
|
+
pool = ConnectionPool.new(timeout: 0, size: 1) { NetworkConnection.new }
|
168
211
|
|
169
|
-
t = Thread.new
|
212
|
+
t = Thread.new {
|
170
213
|
pool.with do |net|
|
171
214
|
net.do_something
|
172
215
|
sleep 0.01
|
173
216
|
end
|
174
|
-
|
217
|
+
}
|
175
218
|
|
176
|
-
Thread.pass while t.status ==
|
219
|
+
Thread.pass while t.status == "run"
|
177
220
|
|
178
221
|
assert_raises Timeout::Error do
|
179
222
|
pool.with { |net| net.do_something }
|
180
223
|
end
|
181
224
|
|
182
|
-
pool.with(:
|
225
|
+
pool.with(timeout: 2 * NetworkConnection::SLEEP_TIME) do |conn|
|
183
226
|
refute_nil conn
|
184
227
|
end
|
185
228
|
end
|
186
229
|
|
187
230
|
def test_checkin
|
188
|
-
pool = ConnectionPool.new(:
|
231
|
+
pool = ConnectionPool.new(timeout: 0, size: 1) { NetworkConnection.new }
|
189
232
|
conn = pool.checkout
|
190
233
|
|
191
|
-
|
192
|
-
|
193
|
-
|
234
|
+
Thread.new {
|
235
|
+
assert_raises Timeout::Error do
|
236
|
+
pool.checkout
|
237
|
+
end
|
238
|
+
}.join
|
194
239
|
|
195
240
|
pool.checkin
|
196
241
|
|
@@ -198,22 +243,19 @@ class TestConnectionPool < Minitest::Test
|
|
198
243
|
end
|
199
244
|
|
200
245
|
def test_returns_value
|
201
|
-
pool = ConnectionPool.new(:
|
202
|
-
assert_equal 1, pool.with {|o| 1 }
|
246
|
+
pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
|
247
|
+
assert_equal 1, pool.with { |o| 1 }
|
203
248
|
end
|
204
249
|
|
205
250
|
def test_checkin_never_checkout
|
206
|
-
pool = ConnectionPool.new(:
|
207
|
-
|
208
|
-
e = assert_raises ConnectionPool::Error do
|
209
|
-
pool.checkin
|
210
|
-
end
|
251
|
+
pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
|
211
252
|
|
212
|
-
|
253
|
+
e = assert_raises(ConnectionPool::Error) { pool.checkin }
|
254
|
+
assert_equal "no connections are checked out", e.message
|
213
255
|
end
|
214
256
|
|
215
257
|
def test_checkin_no_current_checkout
|
216
|
-
pool = ConnectionPool.new(:
|
258
|
+
pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
|
217
259
|
|
218
260
|
pool.checkout
|
219
261
|
pool.checkin
|
@@ -224,18 +266,18 @@ class TestConnectionPool < Minitest::Test
|
|
224
266
|
end
|
225
267
|
|
226
268
|
def test_checkin_twice
|
227
|
-
pool = ConnectionPool.new(:
|
269
|
+
pool = ConnectionPool.new(timeout: 0, size: 1) { Object.new }
|
228
270
|
|
229
271
|
pool.checkout
|
230
272
|
pool.checkout
|
231
273
|
|
232
274
|
pool.checkin
|
233
275
|
|
234
|
-
|
235
|
-
|
276
|
+
Thread.new {
|
277
|
+
assert_raises Timeout::Error do
|
236
278
|
pool.checkout
|
237
|
-
end
|
238
|
-
|
279
|
+
end
|
280
|
+
}.join
|
239
281
|
|
240
282
|
pool.checkin
|
241
283
|
|
@@ -243,7 +285,7 @@ class TestConnectionPool < Minitest::Test
|
|
243
285
|
end
|
244
286
|
|
245
287
|
def test_checkout
|
246
|
-
pool = ConnectionPool.new(:
|
288
|
+
pool = ConnectionPool.new(size: 1) { NetworkConnection.new }
|
247
289
|
|
248
290
|
conn = pool.checkout
|
249
291
|
|
@@ -253,18 +295,18 @@ class TestConnectionPool < Minitest::Test
|
|
253
295
|
end
|
254
296
|
|
255
297
|
def test_checkout_multithread
|
256
|
-
pool = ConnectionPool.new(:
|
298
|
+
pool = ConnectionPool.new(size: 2) { NetworkConnection.new }
|
257
299
|
conn = pool.checkout
|
258
300
|
|
259
|
-
t = Thread.new
|
301
|
+
t = Thread.new {
|
260
302
|
pool.checkout
|
261
|
-
|
303
|
+
}
|
262
304
|
|
263
305
|
refute_same conn, t.value
|
264
306
|
end
|
265
307
|
|
266
308
|
def test_checkout_timeout
|
267
|
-
pool = ConnectionPool.new(:
|
309
|
+
pool = ConnectionPool.new(timeout: 0, size: 0) { Object.new }
|
268
310
|
|
269
311
|
assert_raises Timeout::Error do
|
270
312
|
pool.checkout
|
@@ -272,34 +314,36 @@ class TestConnectionPool < Minitest::Test
|
|
272
314
|
end
|
273
315
|
|
274
316
|
def test_checkout_timeout_override
|
275
|
-
pool = ConnectionPool.new(:
|
317
|
+
pool = ConnectionPool.new(timeout: 0, size: 1) { NetworkConnection.new }
|
276
318
|
|
277
|
-
thread = Thread.new
|
319
|
+
thread = Thread.new {
|
278
320
|
pool.with do |net|
|
279
321
|
net.do_something
|
280
322
|
sleep 0.01
|
281
323
|
end
|
282
|
-
|
324
|
+
}
|
283
325
|
|
284
|
-
Thread.pass while thread.status ==
|
326
|
+
Thread.pass while thread.status == "run"
|
285
327
|
|
286
328
|
assert_raises Timeout::Error do
|
287
329
|
pool.checkout
|
288
330
|
end
|
289
331
|
|
290
|
-
assert pool.checkout :
|
332
|
+
assert pool.checkout timeout: 2 * NetworkConnection::SLEEP_TIME
|
291
333
|
end
|
292
334
|
|
293
335
|
def test_passthru
|
294
|
-
pool = ConnectionPool.wrap(:
|
336
|
+
pool = ConnectionPool.wrap(timeout: 2 * NetworkConnection::SLEEP_TIME, size: 1) { NetworkConnection.new }
|
295
337
|
assert_equal 1, pool.do_something
|
296
338
|
assert_equal 2, pool.do_something
|
297
339
|
assert_equal 5, pool.do_something_with_block { 3 }
|
298
340
|
assert_equal 6, pool.with { |net| net.fast }
|
341
|
+
assert_equal 8, pool.do_something(increment: 2)
|
342
|
+
assert_equal 10, pool.do_something_with_positional_hash({ increment: 2, symbol_key: 3, "string_key" => 4 })
|
299
343
|
end
|
300
344
|
|
301
345
|
def test_passthru_respond_to
|
302
|
-
pool = ConnectionPool.wrap(:
|
346
|
+
pool = ConnectionPool.wrap(timeout: 2 * NetworkConnection::SLEEP_TIME, size: 1) { NetworkConnection.new }
|
303
347
|
assert pool.respond_to?(:with)
|
304
348
|
assert pool.respond_to?(:do_something)
|
305
349
|
assert pool.respond_to?(:do_magic)
|
@@ -307,67 +351,67 @@ class TestConnectionPool < Minitest::Test
|
|
307
351
|
end
|
308
352
|
|
309
353
|
def test_return_value
|
310
|
-
pool = ConnectionPool.new(:
|
311
|
-
result = pool.with
|
354
|
+
pool = ConnectionPool.new(timeout: 2 * NetworkConnection::SLEEP_TIME, size: 1) { NetworkConnection.new }
|
355
|
+
result = pool.with { |net|
|
312
356
|
net.fast
|
313
|
-
|
357
|
+
}
|
314
358
|
assert_equal 1, result
|
315
359
|
end
|
316
360
|
|
317
361
|
def test_heavy_threading
|
318
|
-
pool = ConnectionPool.new(:
|
362
|
+
pool = ConnectionPool.new(timeout: 0.5, size: 3) { NetworkConnection.new }
|
319
363
|
|
320
|
-
threads = Array.new(20)
|
364
|
+
threads = Array.new(20) {
|
321
365
|
Thread.new do
|
322
366
|
pool.with do |net|
|
323
367
|
sleep 0.01
|
324
368
|
end
|
325
369
|
end
|
326
|
-
|
370
|
+
}
|
327
371
|
|
328
372
|
threads.map { |thread| thread.join }
|
329
373
|
end
|
330
374
|
|
331
375
|
def test_reuses_objects_when_pool_not_saturated
|
332
|
-
pool = ConnectionPool.new(:
|
376
|
+
pool = ConnectionPool.new(size: 5) { NetworkConnection.new }
|
333
377
|
|
334
|
-
ids = 10.times.map
|
378
|
+
ids = 10.times.map {
|
335
379
|
pool.with { |c| c.object_id }
|
336
|
-
|
380
|
+
}
|
337
381
|
|
338
382
|
assert_equal 1, ids.uniq.size
|
339
383
|
end
|
340
384
|
|
341
385
|
def test_nested_checkout
|
342
386
|
recorder = Recorder.new
|
343
|
-
pool = ConnectionPool.new(:
|
387
|
+
pool = ConnectionPool.new(size: 1) { recorder }
|
344
388
|
pool.with do |r_outer|
|
345
|
-
@other = Thread.new
|
389
|
+
@other = Thread.new { |t|
|
346
390
|
pool.with do |r_other|
|
347
|
-
r_other.do_work(
|
391
|
+
r_other.do_work("other")
|
348
392
|
end
|
349
|
-
|
393
|
+
}
|
350
394
|
|
351
395
|
pool.with do |r_inner|
|
352
|
-
r_inner.do_work(
|
396
|
+
r_inner.do_work("inner")
|
353
397
|
end
|
354
398
|
|
355
399
|
Thread.pass
|
356
400
|
|
357
|
-
r_outer.do_work(
|
401
|
+
r_outer.do_work("outer")
|
358
402
|
end
|
359
403
|
|
360
404
|
@other.join
|
361
405
|
|
362
|
-
assert_equal [
|
406
|
+
assert_equal ["inner", "outer", "other"], recorder.calls
|
363
407
|
end
|
364
408
|
|
365
409
|
def test_shutdown_is_executed_for_all_connections
|
366
410
|
recorders = []
|
367
411
|
|
368
|
-
pool = ConnectionPool.new(:
|
412
|
+
pool = ConnectionPool.new(size: 3) {
|
369
413
|
Recorder.new.tap { |r| recorders << r }
|
370
|
-
|
414
|
+
}
|
371
415
|
|
372
416
|
threads = use_pool pool, 3
|
373
417
|
|
@@ -381,9 +425,9 @@ class TestConnectionPool < Minitest::Test
|
|
381
425
|
end
|
382
426
|
|
383
427
|
def test_raises_error_after_shutting_down
|
384
|
-
pool = ConnectionPool.new(:
|
428
|
+
pool = ConnectionPool.new(size: 1) { true }
|
385
429
|
|
386
|
-
pool.shutdown {
|
430
|
+
pool.shutdown {}
|
387
431
|
|
388
432
|
assert_raises ConnectionPool::PoolShuttingDownError do
|
389
433
|
pool.checkout
|
@@ -393,9 +437,9 @@ class TestConnectionPool < Minitest::Test
|
|
393
437
|
def test_runs_shutdown_block_asynchronously_if_connection_was_in_use
|
394
438
|
recorders = []
|
395
439
|
|
396
|
-
pool = ConnectionPool.new(:
|
440
|
+
pool = ConnectionPool.new(size: 3) {
|
397
441
|
Recorder.new.tap { |r| recorders << r }
|
398
|
-
|
442
|
+
}
|
399
443
|
|
400
444
|
threads = use_pool pool, 2
|
401
445
|
|
@@ -415,7 +459,7 @@ class TestConnectionPool < Minitest::Test
|
|
415
459
|
end
|
416
460
|
|
417
461
|
def test_raises_an_error_if_shutdown_is_called_without_a_block
|
418
|
-
pool = ConnectionPool.new(:
|
462
|
+
pool = ConnectionPool.new(size: 1) {}
|
419
463
|
|
420
464
|
assert_raises ArgumentError do
|
421
465
|
pool.shutdown
|
@@ -425,9 +469,9 @@ class TestConnectionPool < Minitest::Test
|
|
425
469
|
def test_shutdown_is_executed_for_all_connections_in_wrapped_pool
|
426
470
|
recorders = []
|
427
471
|
|
428
|
-
wrapper = ConnectionPool::Wrapper.new(:
|
472
|
+
wrapper = ConnectionPool::Wrapper.new(size: 3) {
|
429
473
|
Recorder.new.tap { |r| recorders << r }
|
430
|
-
|
474
|
+
}
|
431
475
|
|
432
476
|
threads = use_pool wrapper, 3
|
433
477
|
|
@@ -440,6 +484,11 @@ class TestConnectionPool < Minitest::Test
|
|
440
484
|
assert_equal [["shutdown"]] * 3, recorders.map { |r| r.calls }
|
441
485
|
end
|
442
486
|
|
487
|
+
def test_wrapper_wrapped_pool
|
488
|
+
wrapper = ConnectionPool::Wrapper.new { NetworkConnection.new }
|
489
|
+
assert_equal ConnectionPool, wrapper.wrapped_pool.class
|
490
|
+
end
|
491
|
+
|
443
492
|
def test_wrapper_method_missing
|
444
493
|
wrapper = ConnectionPool::Wrapper.new { NetworkConnection.new }
|
445
494
|
|
@@ -456,17 +505,17 @@ class TestConnectionPool < Minitest::Test
|
|
456
505
|
end
|
457
506
|
|
458
507
|
def test_wrapper_with
|
459
|
-
wrapper = ConnectionPool::Wrapper.new(:
|
508
|
+
wrapper = ConnectionPool::Wrapper.new(timeout: 0, size: 1) { Object.new }
|
460
509
|
|
461
510
|
wrapper.with do
|
462
|
-
|
463
|
-
|
464
|
-
wrapper.with { flunk
|
465
|
-
end
|
466
|
-
|
511
|
+
Thread.new {
|
512
|
+
assert_raises Timeout::Error do
|
513
|
+
wrapper.with { flunk "connection checked out :(" }
|
514
|
+
end
|
515
|
+
}.join
|
467
516
|
end
|
468
517
|
|
469
|
-
assert Thread.new { wrapper.with {
|
518
|
+
assert Thread.new { wrapper.with {} }.join
|
470
519
|
end
|
471
520
|
|
472
521
|
class ConnWithEval
|
@@ -481,4 +530,38 @@ class TestConnectionPool < Minitest::Test
|
|
481
530
|
assert_equal "eval'ed 1", wrapper.eval(1)
|
482
531
|
end
|
483
532
|
|
533
|
+
def test_wrapper_with_connection_pool
|
534
|
+
recorder = Recorder.new
|
535
|
+
pool = ConnectionPool.new(size: 1) { recorder }
|
536
|
+
wrapper = ConnectionPool::Wrapper.new(pool: pool)
|
537
|
+
|
538
|
+
pool.with { |r| r.do_work("with") }
|
539
|
+
wrapper.do_work("wrapped")
|
540
|
+
|
541
|
+
assert_equal ["with", "wrapped"], recorder.calls
|
542
|
+
end
|
543
|
+
|
544
|
+
def test_stats_without_active_connection
|
545
|
+
pool = ConnectionPool.new(size: 2) { NetworkConnection.new }
|
546
|
+
|
547
|
+
assert_equal(2, pool.size)
|
548
|
+
assert_equal(2, pool.available)
|
549
|
+
end
|
550
|
+
|
551
|
+
def test_stats_with_active_connection
|
552
|
+
pool = ConnectionPool.new(size: 2) { NetworkConnection.new }
|
553
|
+
|
554
|
+
pool.with do
|
555
|
+
assert_equal(1, pool.available)
|
556
|
+
end
|
557
|
+
end
|
558
|
+
|
559
|
+
def test_stats_with_string_size
|
560
|
+
pool = ConnectionPool.new(size: "2") { NetworkConnection.new }
|
561
|
+
|
562
|
+
pool.with do
|
563
|
+
assert_equal(2, pool.size)
|
564
|
+
assert_equal(1, pool.available)
|
565
|
+
end
|
566
|
+
end
|
484
567
|
end
|