gene_pool 1.2.4 → 1.3.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.
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' if RUBY_VERSION < '1.9'
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 - The name used in logging messages
13
- # pool_size - The maximum number of instances that will be created (Defaults to 1).
14
- # warn_timeout - Displays an error message if a checkout takes longer that the given time (used to give hints to increase the pool size)
15
- # idle_timeout - If set, the connection will be renewed if it hasn't been used in this amount of time (seconds)
16
- # logger - The logger used for log messages, defaults to STDERR.
17
- # close_proc - The process or method used to close a pooled instance when it is removed.
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
- @condition.wait(@mutex)
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
- start = Time.now
235
- while (Time.now - start) < timeout
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
@@ -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
- e = assert_raises Timeout::Error do
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
- begin
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
- e = assert_raises Timeout::Error do
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
- - Brad Pardee
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
- - bradpardee@gmail.com
15
+ email:
16
+ - bradpardee@gmail.com
19
17
  executables: []
20
-
21
18
  extensions: []
22
-
23
19
  extra_rdoc_files: []
24
-
25
- files:
26
- - lib/gene_pool.rb
27
- - LICENSE.txt
28
- - Rakefile
29
- - Gemfile
30
- - History.md
31
- - README.md
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
- require_paths:
40
- - lib
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
- - !ruby/object:Gem::Version
46
- hash: 2
47
- segments:
48
- - 0
49
- version: "0"
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
- - !ruby/object:Gem::Version
55
- hash: 2
56
- segments:
57
- - 0
58
- version: "0"
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.9
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
- - test/gene_pool_test.rb
58
+ test_files:
59
+ - test/gene_pool_test.rb