hot_tub 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.
- checksums.yaml +4 -4
- data/.travis.yml +2 -1
- data/HISTORY.md +7 -0
- data/README.md +1 -28
- data/hot_tub.gemspec +1 -1
- data/lib/hot_tub/pool.rb +79 -51
- data/lib/hot_tub/version.rb +1 -1
- data/spec/hot_tub/integration/net_http_spec.rb +79 -76
- data/spec/hot_tub/pool_spec.rb +23 -1
- metadata +7 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b7eacafcd3cdc2be1e1f0b27ed6c6c4d351e8858
|
|
4
|
+
data.tar.gz: 6b0d4c6305a8a5779b5f736e9c1c489328b8f8dd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 339f265c1f55963cc9981ba58cd466ac6af16ccf15ef72af5e3c703f6a316cb405c3f8d63d91cf8633cdd92c2d5529e34e27f27c4e2def3b321a457bb75dbb42
|
|
7
|
+
data.tar.gz: eebf1efe482e2a84bdd6ddd1d6523d46657f43d684922b14e7850b0eb9d88d94733c09278bf7389f6267209cb354fc8b1be70d744546e49a0875b51e99bb693c
|
data/.travis.yml
CHANGED
data/HISTORY.md
CHANGED
data/README.md
CHANGED
|
@@ -140,35 +140,8 @@ a lambda that accepts the client as an argument or symbol representing a method
|
|
|
140
140
|
|
|
141
141
|
## Forking
|
|
142
142
|
|
|
143
|
-
HotTub
|
|
144
|
-
to the pool and attempts to close orphaned connections as they attempt to return.
|
|
143
|
+
HotTub::Pool automatically detects forks and drains the pool, so no additional "after fork" code is required.
|
|
145
144
|
|
|
146
|
-
# Puma
|
|
147
|
-
on_worker_boot do
|
|
148
|
-
|
|
149
|
-
# If you let HotTub manage all your connections
|
|
150
|
-
HotTub.reset!
|
|
151
|
-
|
|
152
|
-
# If you have your own HotTub::Sessions
|
|
153
|
-
MY_SESSIONS.reset!
|
|
154
|
-
|
|
155
|
-
# If you have any one-off pools
|
|
156
|
-
MY_POOL.reset!
|
|
157
|
-
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
# Unicorn
|
|
161
|
-
before_fork do |server, worker|
|
|
162
|
-
|
|
163
|
-
# If you let HotTub manage all your connections
|
|
164
|
-
HotTub.reset!
|
|
165
|
-
|
|
166
|
-
# If you have your own HotTub::Sessions
|
|
167
|
-
MY_SESSIONS.reset!
|
|
168
|
-
|
|
169
|
-
# If you have any one-off pools
|
|
170
|
-
MY_POOL.reset!
|
|
171
|
-
end
|
|
172
145
|
|
|
173
146
|
|
|
174
147
|
## Contributing to HotTub
|
data/hot_tub.gemspec
CHANGED
|
@@ -14,7 +14,7 @@ Gem::Specification.new do |s|
|
|
|
14
14
|
|
|
15
15
|
s.rubyforge_project = "hot_tub"
|
|
16
16
|
|
|
17
|
-
s.add_development_dependency "rspec"
|
|
17
|
+
s.add_development_dependency "rspec", "~> 3.0"
|
|
18
18
|
s.add_development_dependency "rspec-autotest"
|
|
19
19
|
s.add_development_dependency "autotest"
|
|
20
20
|
s.add_development_dependency "sinatra"
|
data/lib/hot_tub/pool.rb
CHANGED
|
@@ -87,10 +87,13 @@ module HotTub
|
|
|
87
87
|
# [:reap_timeout]
|
|
88
88
|
# Default is 600 seconds. An integer that represents the timeout for reaping the pool in seconds.
|
|
89
89
|
#
|
|
90
|
+
# [:detect_fork]
|
|
91
|
+
# Set to false to disable fork detection
|
|
92
|
+
#
|
|
90
93
|
def initialize(opts={},&client_block)
|
|
91
94
|
raise ArgumentError, 'a block that initializes a new client is required' unless block_given?
|
|
92
95
|
@name = (opts[:name] || self.class.name)
|
|
93
|
-
@size = (opts[:size] || 5)
|
|
96
|
+
@size = (opts[:size] || 5)
|
|
94
97
|
@wait_timeout = (opts[:wait_timeout] || 10) # in seconds
|
|
95
98
|
@reap_timeout = (opts[:reap_timeout] || 600) # the interval to reap connections in seconds
|
|
96
99
|
@max_size = (opts[:max_size] || 0) # maximum size of pool when non-blocking, 0 means no limit
|
|
@@ -102,7 +105,7 @@ module HotTub
|
|
|
102
105
|
|
|
103
106
|
@_pool = [] # stores available clients
|
|
104
107
|
@_pool.taint
|
|
105
|
-
@_out =
|
|
108
|
+
@_out = {} # stores all checked out clients
|
|
106
109
|
@_out.taint
|
|
107
110
|
|
|
108
111
|
@mutex = Mutex.new
|
|
@@ -116,12 +119,15 @@ module HotTub
|
|
|
116
119
|
|
|
117
120
|
@never_block = (@max_size == 0)
|
|
118
121
|
|
|
122
|
+
@pid = Process.pid unless opts[:detect_fork] == false
|
|
123
|
+
|
|
119
124
|
at_exit {shutdown!} unless @sessions_key
|
|
120
125
|
end
|
|
121
126
|
|
|
122
127
|
# Preform an operations with a client/connection.
|
|
123
128
|
# Requires a block that receives the client.
|
|
124
129
|
def run
|
|
130
|
+
drain! if forked?
|
|
125
131
|
clnt = pop
|
|
126
132
|
yield clnt
|
|
127
133
|
ensure
|
|
@@ -133,10 +139,15 @@ module HotTub
|
|
|
133
139
|
def clean!
|
|
134
140
|
HotTub.logger.info "[HotTub] Cleaning pool #{@name}!" if HotTub.logger
|
|
135
141
|
@mutex.synchronize do
|
|
136
|
-
|
|
137
|
-
|
|
142
|
+
begin
|
|
143
|
+
@_pool.each do |clnt|
|
|
144
|
+
clean_client(clnt)
|
|
145
|
+
end
|
|
146
|
+
ensure
|
|
147
|
+
@cond.signal
|
|
138
148
|
end
|
|
139
149
|
end
|
|
150
|
+
nil
|
|
140
151
|
end
|
|
141
152
|
|
|
142
153
|
# Drain the pool of all clients currently checked into the pool.
|
|
@@ -153,47 +164,22 @@ module HotTub
|
|
|
153
164
|
ensure
|
|
154
165
|
@_out.clear
|
|
155
166
|
@_pool.clear
|
|
156
|
-
@
|
|
157
|
-
end
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
alias :close! :drain!
|
|
161
|
-
|
|
162
|
-
# Reset the pool.
|
|
163
|
-
# or if shutdown allow threads to quickly finish their work
|
|
164
|
-
# Clients from the previous pool will not return to pool.
|
|
165
|
-
def reset!
|
|
166
|
-
HotTub.logger.info "[HotTub] Resetting pool #{@name}!" if HotTub.logger
|
|
167
|
-
@mutex.synchronize do
|
|
168
|
-
begin
|
|
169
|
-
while clnt = @_pool.pop
|
|
170
|
-
close_client(clnt)
|
|
171
|
-
end
|
|
172
|
-
ensure
|
|
173
|
-
@_out.clear
|
|
174
|
-
@_pool.clear
|
|
167
|
+
@pid = Process.pid
|
|
175
168
|
@cond.broadcast
|
|
176
169
|
end
|
|
177
170
|
end
|
|
178
171
|
nil
|
|
179
172
|
end
|
|
173
|
+
alias :close! :drain!
|
|
174
|
+
alias :reset! :drain!
|
|
180
175
|
|
|
181
176
|
# Kills the reaper and drains the pool.
|
|
182
177
|
def shutdown!
|
|
183
178
|
HotTub.logger.info "[HotTub] Shutting down pool #{@name}!" if HotTub.logger
|
|
184
179
|
@shutdown = true
|
|
185
180
|
kill_reaper if @reaper
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
while clnt = @_pool.pop
|
|
189
|
-
close_client(clnt)
|
|
190
|
-
end
|
|
191
|
-
ensure
|
|
192
|
-
@_out.clear
|
|
193
|
-
@_pool.clear
|
|
194
|
-
@cond.broadcast
|
|
195
|
-
end
|
|
196
|
-
end
|
|
181
|
+
drain!
|
|
182
|
+
@shutdown = false
|
|
197
183
|
nil
|
|
198
184
|
end
|
|
199
185
|
|
|
@@ -202,21 +188,33 @@ module HotTub
|
|
|
202
188
|
# reaping is a low priority action
|
|
203
189
|
def reap!
|
|
204
190
|
HotTub.logger.info "[HotTub] Reaping pool #{@name}!" if HotTub.log_trace?
|
|
205
|
-
reaped = nil
|
|
206
191
|
while !@shutdown
|
|
192
|
+
reaped = nil
|
|
207
193
|
@mutex.synchronize do
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
194
|
+
begin
|
|
195
|
+
if _reap?
|
|
196
|
+
if _dead_clients?
|
|
197
|
+
reaped = @_out.select { |clnt, thrd| !thrd.alive? }.keys
|
|
198
|
+
@_out.delete_if { |k,v| reaped.include? k }
|
|
199
|
+
else
|
|
200
|
+
reaped = [@_pool.shift]
|
|
201
|
+
end
|
|
202
|
+
else
|
|
203
|
+
reaped = nil
|
|
204
|
+
end
|
|
205
|
+
ensure
|
|
206
|
+
@cond.signal
|
|
212
207
|
end
|
|
213
208
|
end
|
|
214
209
|
if reaped
|
|
215
|
-
|
|
210
|
+
reaped.each do |clnt|
|
|
211
|
+
close_client(clnt)
|
|
212
|
+
end
|
|
216
213
|
else
|
|
217
214
|
break
|
|
218
215
|
end
|
|
219
216
|
end
|
|
217
|
+
nil
|
|
220
218
|
end
|
|
221
219
|
|
|
222
220
|
def current_size
|
|
@@ -232,9 +230,13 @@ module HotTub
|
|
|
232
230
|
@max_size = max_size
|
|
233
231
|
end
|
|
234
232
|
|
|
233
|
+
def forked?
|
|
234
|
+
(@pid && (@pid != Process.pid))
|
|
235
|
+
end
|
|
236
|
+
|
|
235
237
|
private
|
|
236
238
|
|
|
237
|
-
ALARM_MESSAGE = "Could not fetch a free client in time. Consider increasing your pool size."
|
|
239
|
+
ALARM_MESSAGE = "Could not fetch a free client in time. Consider increasing your pool size.".freeze
|
|
238
240
|
|
|
239
241
|
def raise_alarm
|
|
240
242
|
message = ALARM_MESSAGE
|
|
@@ -242,28 +244,36 @@ module HotTub
|
|
|
242
244
|
raise Timeout, message
|
|
243
245
|
end
|
|
244
246
|
|
|
247
|
+
def close_orphan(clnt)
|
|
248
|
+
HotTub.logger.info "[HotTub] An orphaned client attempted to return to #{@name}." if HotTub.log_trace?
|
|
249
|
+
close_client(clnt)
|
|
250
|
+
end
|
|
251
|
+
|
|
245
252
|
# Safely add client back to pool, only if
|
|
246
253
|
# that client is registered
|
|
247
254
|
def push(clnt)
|
|
248
255
|
if clnt
|
|
256
|
+
orphaned = false
|
|
249
257
|
@mutex.synchronize do
|
|
250
258
|
begin
|
|
251
259
|
if !@shutdown && @_out.delete(clnt)
|
|
252
260
|
@_pool << clnt
|
|
253
261
|
else
|
|
254
|
-
|
|
255
|
-
HotTub.logger.info "[HotTub] An orphaned client attempted to return to #{@name}." if HotTub.log_trace?
|
|
262
|
+
orphaned = true
|
|
256
263
|
end
|
|
257
264
|
ensure
|
|
258
265
|
@cond.signal
|
|
259
266
|
end
|
|
260
267
|
end
|
|
268
|
+
close_orphan(clnt) if orphaned
|
|
261
269
|
reap! if @blocking_reap
|
|
262
270
|
end
|
|
263
271
|
nil
|
|
264
272
|
end
|
|
265
273
|
|
|
266
274
|
# Safely pull client from pool, adding if allowed
|
|
275
|
+
# If a client is not available, check for dead
|
|
276
|
+
# resources and schedule reap if nesseccary
|
|
267
277
|
def pop
|
|
268
278
|
alarm = (Time.now + @wait_timeout)
|
|
269
279
|
clnt = nil
|
|
@@ -271,13 +281,20 @@ module HotTub
|
|
|
271
281
|
while !@shutdown
|
|
272
282
|
raise_alarm if (Time.now > alarm)
|
|
273
283
|
@mutex.synchronize do
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
284
|
+
begin
|
|
285
|
+
if clnt = @_pool.pop
|
|
286
|
+
dirty = true
|
|
287
|
+
else
|
|
288
|
+
clnt = _fetch_new(&@client_block)
|
|
289
|
+
end
|
|
290
|
+
ensure
|
|
291
|
+
if clnt
|
|
292
|
+
_checkout(clnt)
|
|
293
|
+
@cond.signal
|
|
294
|
+
else
|
|
295
|
+
@reaper.wakeup if @reaper && _dead_clients?
|
|
296
|
+
@cond.wait(@mutex,@wait_timeout)
|
|
297
|
+
end
|
|
281
298
|
end
|
|
282
299
|
end
|
|
283
300
|
break if clnt
|
|
@@ -288,6 +305,10 @@ module HotTub
|
|
|
288
305
|
|
|
289
306
|
### START VOLATILE METHODS ###
|
|
290
307
|
|
|
308
|
+
def _checkout(clnt)
|
|
309
|
+
@_out[clnt] = Thread.current
|
|
310
|
+
end
|
|
311
|
+
|
|
291
312
|
# Returns the total number of clients in the pool
|
|
292
313
|
# and checked out. _total_current_size is volatile and
|
|
293
314
|
# may be inaccurate if called outside @mutex.synchronize {}
|
|
@@ -316,7 +337,14 @@ module HotTub
|
|
|
316
337
|
# volatile; and may be inaccurate if called outside
|
|
317
338
|
# @mutex.synchronize {}
|
|
318
339
|
def _reap?
|
|
319
|
-
(!@shutdown && ((@_pool.length > @size) || reap_client?(@_pool[0])))
|
|
340
|
+
(!@shutdown && ((@_pool.length > @size) || _dead_clients? || reap_client?(@_pool[0])))
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
# Returns true if we have checked out clients whose resource is dead.
|
|
344
|
+
# _dead_clients? is volatile; and may be inaccurate if called outside
|
|
345
|
+
# @mutex.synchronize {}
|
|
346
|
+
def _dead_clients?
|
|
347
|
+
@_out.detect { |clnt, thrd| !thrd.alive? }
|
|
320
348
|
end
|
|
321
349
|
|
|
322
350
|
### END VOLATILE METHODS ###
|
data/lib/hot_tub/version.rb
CHANGED
|
@@ -1,104 +1,107 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
|
+
|
|
3
4
|
describe HotTub do
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
unless HotTub.jruby?
|
|
6
|
+
context "blocking (size equals max_size)" do
|
|
7
|
+
let(:pool) do
|
|
8
|
+
HotTub::Pool.new(:size => 4, :max_size => 4) {
|
|
9
|
+
uri = URI.parse(HotTub::Server.url)
|
|
10
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
11
|
+
http.use_ssl = false
|
|
12
|
+
http.start
|
|
13
|
+
http
|
|
14
|
+
}
|
|
15
|
+
end
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
let(:threads) { [] }
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
before(:each) do
|
|
20
|
+
20.times do
|
|
21
|
+
net_http_thread_work(pool, 10, threads)
|
|
22
|
+
end
|
|
20
23
|
end
|
|
21
|
-
end
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
it { expect(pool.current_size).to eql(4) }
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
it "should work" do
|
|
28
|
+
results = threads.collect{ |t| t[:status]}
|
|
29
|
+
expect(results.length).to eql(200)
|
|
30
|
+
expect(results.uniq).to eql(['200'])
|
|
31
|
+
end
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
it "should shutdown" do
|
|
34
|
+
pool.shutdown!
|
|
35
|
+
expect(pool.current_size).to eql(0)
|
|
36
|
+
end
|
|
34
37
|
end
|
|
35
|
-
end
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
context "with larger max" do
|
|
40
|
+
let(:pool) do
|
|
41
|
+
HotTub::Pool.new(:size => 4, :max_size => 8) {
|
|
42
|
+
uri = URI.parse(HotTub::Server.url)
|
|
43
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
44
|
+
http.use_ssl = false
|
|
45
|
+
http.start
|
|
46
|
+
http
|
|
47
|
+
}
|
|
48
|
+
end
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
let(:threads) { [] }
|
|
49
51
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
before(:each) do
|
|
53
|
+
20.times do
|
|
54
|
+
net_http_thread_work(pool, 10, threads)
|
|
55
|
+
end
|
|
53
56
|
end
|
|
54
|
-
end
|
|
55
57
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
it { expect(pool.current_size).to be >= 4 }
|
|
59
|
+
it { expect(pool.current_size).to be <= 8 }
|
|
60
|
+
it "should work" do
|
|
61
|
+
results = threads.collect{ |t| t[:status]}
|
|
62
|
+
expect(results.length).to eql(200)
|
|
63
|
+
expect(results.uniq).to eql(['200'])
|
|
64
|
+
end
|
|
62
65
|
end
|
|
63
|
-
end
|
|
64
66
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
67
|
+
context "sized without max" do
|
|
68
|
+
let(:pool) do
|
|
69
|
+
HotTub::Pool.new(:size => 4) {
|
|
70
|
+
uri = URI.parse(HotTub::Server.url)
|
|
71
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
72
|
+
http.use_ssl = false
|
|
73
|
+
http.start
|
|
74
|
+
http
|
|
75
|
+
}
|
|
76
|
+
end
|
|
75
77
|
|
|
76
|
-
|
|
78
|
+
let(:threads) { [] }
|
|
77
79
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
before(:each) do
|
|
81
|
+
20.times do
|
|
82
|
+
net_http_thread_work(pool, 10, threads)
|
|
83
|
+
end
|
|
81
84
|
end
|
|
82
|
-
end
|
|
83
85
|
|
|
84
|
-
|
|
86
|
+
it { expect(pool.current_size).to be > 4 }
|
|
85
87
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
it "should work" do
|
|
89
|
+
results = threads.collect{ |t| t[:status]}
|
|
90
|
+
expect(results.length).to eql(200)
|
|
91
|
+
expect(results.uniq).to eql(['200'])
|
|
92
|
+
end
|
|
90
93
|
end
|
|
91
94
|
end
|
|
92
|
-
end
|
|
93
95
|
|
|
94
|
-
def net_http_thread_work(pool,thread_count=0, threads=[])
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
def net_http_thread_work(pool,thread_count=0, threads=[])
|
|
97
|
+
thread_count.times.each do
|
|
98
|
+
threads << Thread.new do
|
|
99
|
+
uri = URI.parse(HotTub::Server.url)
|
|
100
|
+
pool.run{|connection| Thread.current[:status] = connection.get(uri.path).code }
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
threads.each do |t|
|
|
104
|
+
t.join
|
|
99
105
|
end
|
|
100
|
-
end
|
|
101
|
-
threads.each do |t|
|
|
102
|
-
t.join
|
|
103
106
|
end
|
|
104
107
|
end
|
data/spec/hot_tub/pool_spec.rb
CHANGED
|
@@ -169,10 +169,22 @@ describe HotTub::Pool do
|
|
|
169
169
|
expect(pool.current_size).to eql(1)
|
|
170
170
|
expect(old_client).to be_closed
|
|
171
171
|
end
|
|
172
|
+
|
|
173
|
+
context "when client is lost with dead thread" do
|
|
174
|
+
it "should close dead client" do
|
|
175
|
+
pool = HotTub::Pool.new({ :size => 1, :close => :close }) { MocClient.new }
|
|
176
|
+
thread = Thread.new {}
|
|
177
|
+
thread.join
|
|
178
|
+
client = MocClient.new
|
|
179
|
+
pool.instance_variable_set(:@_out, {client => thread})
|
|
180
|
+
pool.reap!
|
|
181
|
+
expect(client).to be_closed
|
|
182
|
+
end
|
|
183
|
+
end
|
|
172
184
|
end
|
|
173
185
|
|
|
174
186
|
context 'private methods' do
|
|
175
|
-
let(:pool) { HotTub::Pool.new(:close => :close) { MocClient.new} }
|
|
187
|
+
let(:pool) { HotTub::Pool.new( :close => :close) { MocClient.new} }
|
|
176
188
|
|
|
177
189
|
describe '#pop' do
|
|
178
190
|
context "is allowed" do
|
|
@@ -180,6 +192,16 @@ describe HotTub::Pool do
|
|
|
180
192
|
expect(pool.send(:pop)).to be_a(MocClient)
|
|
181
193
|
end
|
|
182
194
|
end
|
|
195
|
+
context "has dead client" do
|
|
196
|
+
it "should return new client" do
|
|
197
|
+
pool.max_size = 1
|
|
198
|
+
thread = Thread.new {}
|
|
199
|
+
thread.join
|
|
200
|
+
client = MocClient.new
|
|
201
|
+
pool.instance_variable_set(:@_out, {client => thread})
|
|
202
|
+
expect(pool.send(:pop)).to be_a(MocClient)
|
|
203
|
+
end
|
|
204
|
+
end
|
|
183
205
|
end
|
|
184
206
|
|
|
185
207
|
describe '#push' do
|
metadata
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hot_tub
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joshua Mckinney
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2016-05-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rspec
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - "
|
|
17
|
+
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '0'
|
|
19
|
+
version: '3.0'
|
|
20
20
|
type: :development
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- - "
|
|
24
|
+
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '0'
|
|
26
|
+
version: '3.0'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rspec-autotest
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -152,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
152
152
|
version: '0'
|
|
153
153
|
requirements: []
|
|
154
154
|
rubyforge_project: hot_tub
|
|
155
|
-
rubygems_version: 2.
|
|
155
|
+
rubygems_version: 2.5.1
|
|
156
156
|
signing_key:
|
|
157
157
|
specification_version: 4
|
|
158
158
|
summary: Flexible connection pooling for Ruby.
|