gene_pool 1.2.4 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.md +4 -0
- data/README.md +2 -0
- data/lib/gene_pool.rb +51 -16
- data/test/gene_pool_test.rb +41 -6
- metadata +37 -45
data/History.md
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
GenePool Changelog
|
2
2
|
=====================
|
3
3
|
|
4
|
+
1.3.0 / 2012-09-10
|
5
|
+
|
6
|
+
- Allow :timeout option to raise Timeout::Error if waiting for a connection exceeds this value.
|
7
|
+
|
4
8
|
1.2.4 / 2012-09-05
|
5
9
|
|
6
10
|
- require 'thread' under ruby 1.8 so that mutex is defined (Thanks soupmatt!)
|
data/README.md
CHANGED
@@ -20,8 +20,10 @@ Generic pooling library for connection pools.
|
|
20
20
|
class MyClient
|
21
21
|
# Print a logger warning if it requires more than 0.25 seconds to acquire a connection.
|
22
22
|
# Close and reopen the connection if it hasn't been used for 10 seconds.
|
23
|
+
# Raise Timeout::Error if waiting for a connection more than 3 seconds.
|
23
24
|
@@gene_pool = GenePool.new(:name => 'MyClient',
|
24
25
|
:pool_size => 10,
|
26
|
+
:timeout => 3,
|
25
27
|
:warn_timeout => 0.25,
|
26
28
|
:idle_timeout => 10,
|
27
29
|
:logger => Rails.logger,
|
data/lib/gene_pool.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'logger'
|
2
|
-
require 'thread'
|
2
|
+
require 'thread'
|
3
3
|
|
4
4
|
# Generic connection pool class
|
5
5
|
class GenePool
|
@@ -9,18 +9,20 @@ class GenePool
|
|
9
9
|
# Creates a gene_pool. The passed block will be used to initialize a single instance of
|
10
10
|
# the item being pooled (i.e., socket connection or whatever)
|
11
11
|
# options -
|
12
|
-
# name
|
13
|
-
# pool_size
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
12
|
+
# name - The name used in logging messages.
|
13
|
+
# pool_size - The maximum number of instances that will be created (Defaults to 1).
|
14
|
+
# timeout - Will raise a Timeout exception if waiting on a connection for this many seconds.
|
15
|
+
# warn_timeout - Displays an error message if a checkout takes longer that the given time (used to give hints to increase the pool size).
|
16
|
+
# idle_timeout - If set, the connection will be renewed if it hasn't been used in this amount of time (seconds).
|
17
|
+
# logger - The logger used for log messages, defaults to STDERR.
|
18
|
+
# close_proc - The process or method used to close a pooled instance when it is removed.
|
18
19
|
# Defaults to :close. Set to nil for no-op or a symbol for a method or a proc that takes an argument for the instance.
|
19
20
|
def initialize(options={}, &connect_block)
|
20
21
|
@connect_block = connect_block
|
21
22
|
|
22
23
|
@name = options[:name] || 'GenePool'
|
23
24
|
@pool_size = options[:pool_size] || 1
|
25
|
+
@timeout = options[:timeout]
|
24
26
|
@warn_timeout = options[:warn_timeout] || 5.0
|
25
27
|
@idle_timeout = options[:idle_timeout]
|
26
28
|
@logger = options[:logger]
|
@@ -31,17 +33,13 @@ class GenePool
|
|
31
33
|
@logger.level = Logger::INFO
|
32
34
|
end
|
33
35
|
|
34
|
-
# Mutex for synchronizing pool access
|
35
|
-
@mutex = Mutex.new
|
36
|
-
|
37
|
-
# Condition variable for waiting for an available connection
|
38
|
-
@condition = ConditionVariable.new
|
39
|
-
|
40
36
|
@connections = []
|
41
37
|
@checked_out = []
|
42
38
|
# Map the original connections object_id within the with_connection method to the final connection.
|
43
39
|
# This could change if the connection is renew'ed.
|
44
40
|
@with_map = {}
|
41
|
+
|
42
|
+
setup_mutex
|
45
43
|
end
|
46
44
|
|
47
45
|
def size
|
@@ -84,7 +82,7 @@ class GenePool
|
|
84
82
|
@logger.debug {"#{@name}: Created connection ##{@connections.size} #{connection}(#{connection.object_id}) for #{name}"}
|
85
83
|
else
|
86
84
|
@logger.info "#{@name}: Waiting for an available connection, all #{@pool_size} connections are checked out."
|
87
|
-
|
85
|
+
wait_mutex(start_time)
|
88
86
|
end
|
89
87
|
end
|
90
88
|
end
|
@@ -231,8 +229,8 @@ class GenePool
|
|
231
229
|
|
232
230
|
def close(timeout=10)
|
233
231
|
self.pool_size = 0
|
234
|
-
|
235
|
-
while (Time.now -
|
232
|
+
start_time = Time.now
|
233
|
+
while (Time.now - start_time) < timeout
|
236
234
|
sleep 1
|
237
235
|
@mutex.synchronize do
|
238
236
|
return if @connections.empty?
|
@@ -287,4 +285,41 @@ class GenePool
|
|
287
285
|
@connections.delete(connection)
|
288
286
|
close_connection(connection)
|
289
287
|
end
|
288
|
+
|
289
|
+
if RUBY_VERSION < '1.9'
|
290
|
+
require 'monitor'
|
291
|
+
def setup_mutex
|
292
|
+
@connections.extend(MonitorMixin)
|
293
|
+
# Mutex for synchronizing pool access
|
294
|
+
@mutex = @connections
|
295
|
+
# Condition variable for waiting for an available connection
|
296
|
+
@condition = @mutex.new_cond
|
297
|
+
end
|
298
|
+
|
299
|
+
def wait_mutex(start_time)
|
300
|
+
return @condition.wait unless @timeout
|
301
|
+
delta = @timeout - (Time.now - start_time)
|
302
|
+
raise Timeout::Error if delta <= 0.0
|
303
|
+
@condition.wait(delta)
|
304
|
+
delta = @timeout - (Time.now - start_time)
|
305
|
+
raise Timeout::Error if delta <= 0.0
|
306
|
+
end
|
307
|
+
|
308
|
+
else # RUBY_VERSION >= '1.9'
|
309
|
+
def setup_mutex
|
310
|
+
# Mutex for synchronizing pool access
|
311
|
+
@mutex = Mutex.new
|
312
|
+
# Condition variable for waiting for an available connection
|
313
|
+
@condition = ConditionVariable.new
|
314
|
+
end
|
315
|
+
|
316
|
+
def wait_mutex(start_time)
|
317
|
+
return @condition.wait(@mutex) unless @timeout
|
318
|
+
delta = @timeout - (Time.now - start_time)
|
319
|
+
raise Timeout::Error if delta <= 0.0
|
320
|
+
@condition.wait(@mutex, delta)
|
321
|
+
delta = @timeout - (Time.now - start_time)
|
322
|
+
raise Timeout::Error if delta <= 0.0
|
323
|
+
end
|
324
|
+
end
|
290
325
|
end
|
data/test/gene_pool_test.rb
CHANGED
@@ -169,7 +169,7 @@ class GenePoolTest < Test::Unit::TestCase
|
|
169
169
|
should 'handle aborted connection' do
|
170
170
|
@gene_pool.with_connection do |conn1|
|
171
171
|
@sleep = 2
|
172
|
-
|
172
|
+
assert_raises Timeout::Error do
|
173
173
|
Timeout.timeout(1) do
|
174
174
|
@gene_pool.with_connection { |conn2| }
|
175
175
|
end
|
@@ -200,13 +200,10 @@ class GenePoolTest < Test::Unit::TestCase
|
|
200
200
|
assert_equal i, @gene_pool.checked_out.size
|
201
201
|
assert_equal conns, @gene_pool.connections
|
202
202
|
end
|
203
|
-
|
203
|
+
assert_raises Timeout::Error do
|
204
204
|
Timeout.timeout(1) do
|
205
205
|
@gene_pool.checkout
|
206
206
|
end
|
207
|
-
flunk "connection should have timed out"
|
208
|
-
rescue Timeout::Error => e
|
209
|
-
#pass "successfully timed out connection"
|
210
207
|
end
|
211
208
|
(1..pool_size).each do |i|
|
212
209
|
@gene_pool.checkin(conns[i-1])
|
@@ -281,7 +278,7 @@ class GenePoolTest < Test::Unit::TestCase
|
|
281
278
|
end
|
282
279
|
|
283
280
|
should 'not auto-retry on timeout' do
|
284
|
-
|
281
|
+
assert_raises Timeout::Error do
|
285
282
|
Timeout.timeout(1) do
|
286
283
|
@gene_pool.with_connection_auto_retry do |conn|
|
287
284
|
sleep 2
|
@@ -401,6 +398,44 @@ class GenePoolTest < Test::Unit::TestCase
|
|
401
398
|
assert_same conn, close_conn
|
402
399
|
assert_equal 2, foo
|
403
400
|
end
|
401
|
+
end
|
402
|
+
|
403
|
+
context 'timeout' do
|
404
|
+
setup do
|
405
|
+
@gene_pool = GenePool.new(:name => 'TestGenePool',
|
406
|
+
:pool_size => 2,
|
407
|
+
:close_proc => nil,
|
408
|
+
:timeout => 1.0) do
|
409
|
+
Object.new
|
410
|
+
end
|
411
|
+
end
|
404
412
|
|
413
|
+
should 'timeout when the timeout period has expired' do
|
414
|
+
pool_size = @gene_pool.pool_size
|
415
|
+
# Do it with new connections and old connections
|
416
|
+
(1..2).each do |n|
|
417
|
+
(1..pool_size).each do |i|
|
418
|
+
Thread.new do
|
419
|
+
@gene_pool.with_connection do |c|
|
420
|
+
sleep(2)
|
421
|
+
end
|
422
|
+
end
|
423
|
+
end
|
424
|
+
# Let the threads get the connections
|
425
|
+
sleep(0.1)
|
426
|
+
start_time = Time.now
|
427
|
+
assert_raises Timeout::Error do
|
428
|
+
@gene_pool.with_connection { |c| }
|
429
|
+
puts "No timeout after #{Time.now - start_time} seconds"
|
430
|
+
end
|
431
|
+
puts "#{Time.now-start_time} should be around 1.0"
|
432
|
+
assert_equal pool_size, @gene_pool.connections.size
|
433
|
+
assert_equal pool_size, @gene_pool.checked_out.size
|
434
|
+
# Let the threads complete so we can do it again
|
435
|
+
sleep 2
|
436
|
+
assert_equal pool_size, @gene_pool.connections.size
|
437
|
+
assert_equal 0, @gene_pool.checked_out.size
|
438
|
+
end
|
439
|
+
end
|
405
440
|
end
|
406
441
|
end
|
metadata
CHANGED
@@ -1,67 +1,59 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: gene_pool
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.3.0
|
4
5
|
prerelease:
|
5
|
-
version: 1.2.4
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
8
|
-
|
7
|
+
authors:
|
8
|
+
- Brad Pardee
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
date: 2012-09-06 00:00:00 Z
|
12
|
+
date: 2012-09-10 00:00:00.000000000 Z
|
14
13
|
dependencies: []
|
15
|
-
|
16
14
|
description: Generic pooling library for creating a connection pool
|
17
|
-
email:
|
18
|
-
|
15
|
+
email:
|
16
|
+
- bradpardee@gmail.com
|
19
17
|
executables: []
|
20
|
-
|
21
18
|
extensions: []
|
22
|
-
|
23
19
|
extra_rdoc_files: []
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
- test/gene_pool_test.rb
|
20
|
+
files:
|
21
|
+
- lib/gene_pool.rb
|
22
|
+
- LICENSE.txt
|
23
|
+
- Rakefile
|
24
|
+
- Gemfile
|
25
|
+
- History.md
|
26
|
+
- README.md
|
27
|
+
- test/gene_pool_test.rb
|
33
28
|
homepage: http://github.com/bpardee/gene_pool
|
34
29
|
licenses: []
|
35
|
-
|
36
30
|
post_install_message:
|
37
31
|
rdoc_options: []
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
32
|
+
require_paths:
|
33
|
+
- lib
|
34
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
35
|
none: false
|
43
|
-
requirements:
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ! '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
segments:
|
41
|
+
- 0
|
42
|
+
hash: 102611247716920126
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
44
|
none: false
|
52
|
-
requirements:
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
segments:
|
50
|
+
- 0
|
51
|
+
hash: 102611247716920126
|
59
52
|
requirements: []
|
60
|
-
|
61
53
|
rubyforge_project:
|
62
|
-
rubygems_version: 1.8.
|
54
|
+
rubygems_version: 1.8.23
|
63
55
|
signing_key:
|
64
56
|
specification_version: 3
|
65
57
|
summary: Generic pooling library for creating a connection pool
|
66
|
-
test_files:
|
67
|
-
|
58
|
+
test_files:
|
59
|
+
- test/gene_pool_test.rb
|