r18_connection_pool 2.2.2a
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 +7 -0
- data/.gitignore +4 -0
- data/.travis.yml +10 -0
- data/Changes.md +123 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +107 -0
- data/Rakefile +6 -0
- data/devjournal +15 -0
- data/lib/connection_pool/monotonic_time.rb +66 -0
- data/lib/connection_pool/timed_stack.rb +176 -0
- data/lib/connection_pool/version.rb +3 -0
- data/lib/connection_pool.rb +161 -0
- data/r18_connection_pool.gemspec +21 -0
- data/test/helper.rb +8 -0
- data/test/test_connection_pool.rb +516 -0
- data/test/test_connection_pool_timed_stack.rb +149 -0
- metadata +103 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: c24bd0aef22d03af8f4cb6d589696e5c6bbe8f0e0f4c6d3be3f96e8a1a4a21a0
|
|
4
|
+
data.tar.gz: 17778a4163543a80f269f39edbe26e20e026734f747294b8c01a7c307ad78661
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: a87b9e013ac7dd203c70aa4269183161850f9c017c369f4a150dd0875383104f3627239e88de1cdac3a3c86773a62969b101f9065edf25497f134911b208094a
|
|
7
|
+
data.tar.gz: c659492935abc74d1757b1d187a0c7a08b87cd11608b27d41ce705ea1dc0d710b6920d664edd9c1eddf034af19ac5d7c9e760a439f1a401b64ec3fa811b42569
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Changes.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
connection\_pool changelog
|
|
2
|
+
---------------------------
|
|
3
|
+
|
|
4
|
+
2.2.2
|
|
5
|
+
------
|
|
6
|
+
|
|
7
|
+
- Add pool `size` and `available` accessors for metrics and monitoring
|
|
8
|
+
purposes [#97, robholland]
|
|
9
|
+
|
|
10
|
+
2.2.1
|
|
11
|
+
------
|
|
12
|
+
|
|
13
|
+
- Allow CP::Wrapper to use an existing pool [#87, etiennebarrie]
|
|
14
|
+
- Use monotonic time for more accurate timeouts [#84, jdantonio]
|
|
15
|
+
|
|
16
|
+
2.2.0
|
|
17
|
+
------
|
|
18
|
+
|
|
19
|
+
- Rollback `Timeout` handling introduced in 2.1.1 and 2.1.2. It seems
|
|
20
|
+
impossible to safely work around the issue. Please never, ever use
|
|
21
|
+
`Timeout.timeout` in your code or you will see rare but mysterious bugs. [#75]
|
|
22
|
+
|
|
23
|
+
2.1.3
|
|
24
|
+
------
|
|
25
|
+
|
|
26
|
+
- Don't increment created count until connection is successfully
|
|
27
|
+
created. [mylesmegyesi, #73]
|
|
28
|
+
|
|
29
|
+
2.1.2
|
|
30
|
+
------
|
|
31
|
+
|
|
32
|
+
- The connection\_pool will now close any connections which respond to
|
|
33
|
+
`close` (Dalli) or `disconnect!` (Redis). This ensures discarded connections
|
|
34
|
+
from the fix in 2.1.1 are torn down ASAP and don't linger open.
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
2.1.1
|
|
38
|
+
------
|
|
39
|
+
|
|
40
|
+
- Work around a subtle race condition with code which uses `Timeout.timeout` and
|
|
41
|
+
checks out a connection within the timeout block. This might cause
|
|
42
|
+
connections to get into a bad state and raise very odd errors. [tamird, #67]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
2.1.0
|
|
46
|
+
------
|
|
47
|
+
|
|
48
|
+
- Refactoring to better support connection pool subclasses [drbrain,
|
|
49
|
+
#55]
|
|
50
|
+
- `with` should return value of the last expression [#59]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
2.0.0
|
|
54
|
+
-----
|
|
55
|
+
|
|
56
|
+
- The connection pool is now lazy. Connections are created as needed
|
|
57
|
+
and retained until the pool is shut down. [drbrain, #52]
|
|
58
|
+
|
|
59
|
+
1.2.0
|
|
60
|
+
-----
|
|
61
|
+
|
|
62
|
+
- Add `with(options)` and `checkout(options)`. [mattcamuto]
|
|
63
|
+
Allows the caller to override the pool timeout.
|
|
64
|
+
```ruby
|
|
65
|
+
@pool.with(:timeout => 2) do |conn|
|
|
66
|
+
end
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
1.1.0
|
|
70
|
+
-----
|
|
71
|
+
|
|
72
|
+
- New `#shutdown` method (simao)
|
|
73
|
+
|
|
74
|
+
This method accepts a block and calls the block for each
|
|
75
|
+
connection in the pool. After calling this method, trying to get a
|
|
76
|
+
connection from the pool raises `PoolShuttingDownError`.
|
|
77
|
+
|
|
78
|
+
1.0.0
|
|
79
|
+
-----
|
|
80
|
+
|
|
81
|
+
- `#with_connection` is now gone in favor of `#with`.
|
|
82
|
+
|
|
83
|
+
- We no longer pollute the top level namespace with our internal
|
|
84
|
+
`TimedStack` class.
|
|
85
|
+
|
|
86
|
+
0.9.3
|
|
87
|
+
--------
|
|
88
|
+
|
|
89
|
+
- `#with_connection` is now deprecated in favor of `#with`.
|
|
90
|
+
|
|
91
|
+
A warning will be issued in the 0.9 series and the method will be
|
|
92
|
+
removed in 1.0.
|
|
93
|
+
|
|
94
|
+
- We now reuse objects when possible.
|
|
95
|
+
|
|
96
|
+
This means that under no contention, the same object will be checked
|
|
97
|
+
out from the pool after subsequent calls to `ConnectionPool#with`.
|
|
98
|
+
|
|
99
|
+
This change should have no impact on end user performance. If
|
|
100
|
+
anything, it should be an improvement, depending on what objects you
|
|
101
|
+
are pooling.
|
|
102
|
+
|
|
103
|
+
0.9.2
|
|
104
|
+
--------
|
|
105
|
+
|
|
106
|
+
- Fix reentrant checkout leading to early checkin.
|
|
107
|
+
|
|
108
|
+
0.9.1
|
|
109
|
+
--------
|
|
110
|
+
|
|
111
|
+
- Fix invalid superclass in version.rb
|
|
112
|
+
|
|
113
|
+
0.9.0
|
|
114
|
+
--------
|
|
115
|
+
|
|
116
|
+
- Move method\_missing magic into ConnectionPool::Wrapper (djanowski)
|
|
117
|
+
- Remove BasicObject superclass (djanowski)
|
|
118
|
+
|
|
119
|
+
0.1.0
|
|
120
|
+
--------
|
|
121
|
+
|
|
122
|
+
- More precise timeouts and better error message
|
|
123
|
+
- ConnectionPool now subclasses BasicObject so `method_missing` is more effective.
|
data/Gemfile
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2011 Mike Perham
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
connection\_pool
|
|
2
|
+
=================
|
|
3
|
+
[](https://travis-ci.org/mperham/connection_pool)
|
|
4
|
+
|
|
5
|
+
Generic connection pooling for Ruby.
|
|
6
|
+
|
|
7
|
+
MongoDB has its own connection pool. ActiveRecord has its own connection pool.
|
|
8
|
+
This is a generic connection pool that can be used with anything, e.g. Redis,
|
|
9
|
+
Dalli and other Ruby network clients.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
Usage
|
|
13
|
+
-----
|
|
14
|
+
|
|
15
|
+
Create a pool of objects to share amongst the fibers or threads in your Ruby
|
|
16
|
+
application:
|
|
17
|
+
|
|
18
|
+
``` ruby
|
|
19
|
+
$memcached = ConnectionPool.new(size: 5, timeout: 5) { Dalli::Client.new }
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Then use the pool in your application:
|
|
23
|
+
|
|
24
|
+
``` ruby
|
|
25
|
+
$memcached.with do |conn|
|
|
26
|
+
conn.get('some-count')
|
|
27
|
+
end
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
If all the objects in the connection pool are in use, `with` will block
|
|
31
|
+
until one becomes available. If no object is available within `:timeout` seconds,
|
|
32
|
+
`with` will raise a `Timeout::Error`.
|
|
33
|
+
|
|
34
|
+
Optionally, you can specify a timeout override using the with-block semantics:
|
|
35
|
+
|
|
36
|
+
``` ruby
|
|
37
|
+
$memcached.with(timeout: 2.0) do |conn|
|
|
38
|
+
conn.get('some-count')
|
|
39
|
+
end
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
This will only modify the resource-get timeout for this particular
|
|
43
|
+
invocation. This is useful if you want to fail-fast on certain non critical
|
|
44
|
+
sections when a resource is not available, or conversely if you are comfortable
|
|
45
|
+
blocking longer on a particular resource. This is not implemented in the below
|
|
46
|
+
`ConnectionPool::Wrapper` class.
|
|
47
|
+
|
|
48
|
+
## Migrating to a Connection Pool
|
|
49
|
+
|
|
50
|
+
You can use `ConnectionPool::Wrapper` to wrap a single global connection,
|
|
51
|
+
making it easier to migrate existing connection code over time:
|
|
52
|
+
|
|
53
|
+
``` ruby
|
|
54
|
+
$redis = ConnectionPool::Wrapper.new(size: 5, timeout: 3) { Redis.connect }
|
|
55
|
+
$redis.sadd('foo', 1)
|
|
56
|
+
$redis.smembers('foo')
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The wrapper uses `method_missing` to checkout a connection, run the requested
|
|
60
|
+
method and then immediately check the connection back into the pool. It's
|
|
61
|
+
**not** high-performance so you'll want to port your performance sensitive code
|
|
62
|
+
to use `with` as soon as possible.
|
|
63
|
+
|
|
64
|
+
``` ruby
|
|
65
|
+
$redis.with do |conn|
|
|
66
|
+
conn.sadd('foo', 1)
|
|
67
|
+
conn.smembers('foo')
|
|
68
|
+
end
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Once you've ported your entire system to use `with`, you can simply remove
|
|
72
|
+
`Wrapper` and use the simpler and faster `ConnectionPool`.
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
## Shutdown
|
|
76
|
+
|
|
77
|
+
You can shut down a ConnectionPool instance once it should no longer be used.
|
|
78
|
+
Further checkout attempts will immediately raise an error but existing checkouts
|
|
79
|
+
will work.
|
|
80
|
+
|
|
81
|
+
```ruby
|
|
82
|
+
cp = ConnectionPool.new { Redis.new }
|
|
83
|
+
cp.shutdown { |conn| conn.quit }
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Shutting down a connection pool will block until all connections are checked in and closed.
|
|
87
|
+
**Note that shutting down is completely optional**; Ruby's garbage collector will reclaim
|
|
88
|
+
unreferenced pools under normal circumstances.
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
Notes
|
|
92
|
+
-----
|
|
93
|
+
|
|
94
|
+
- Connections are lazily created as needed.
|
|
95
|
+
- There is no provision for repairing or checking the health of a connection;
|
|
96
|
+
connections should be self-repairing. This is true of the Dalli and Redis
|
|
97
|
+
clients.
|
|
98
|
+
- **WARNING**: Don't ever use `Timeout.timeout` in your Ruby code or you will see
|
|
99
|
+
occasional silent corruption and mysterious errors. The Timeout API is unsafe
|
|
100
|
+
and cannot be used correctly, ever. Use proper socket timeout options as
|
|
101
|
+
exposed by Net::HTTP, Redis, Dalli, etc.
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
Author
|
|
105
|
+
------
|
|
106
|
+
|
|
107
|
+
Mike Perham, [@mperham](https://twitter.com/mperham), <http://mikeperham.com>
|
data/Rakefile
ADDED
data/devjournal
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
--------------------------------
|
|
2
|
+
2023/08/04 takeshi:
|
|
3
|
+
|
|
4
|
+
I need connection_pool to run on ruby 1.8.
|
|
5
|
+
So I searched for a suitable gem version and it seems 2.2.3 (8b830d21fdc4c9ae1a41cc587e436478a280513c) will work with some small adjustment.
|
|
6
|
+
|
|
7
|
+
However, eventually, 2.2.3 required
|
|
8
|
+
Process::CLOCK_MONOTONIC
|
|
9
|
+
which we don't have in ruby 1.8
|
|
10
|
+
|
|
11
|
+
But 2.2.2 uses
|
|
12
|
+
Process::CLOCK_MONOTONIC
|
|
13
|
+
only if available so lets try to switch to it.
|
|
14
|
+
|
|
15
|
+
So this branch was created based on 2.2.2 (608f0f407161275d95e044adad48b9ae44d55ec1).
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Global monotonic clock from Concurrent Ruby 1.0.
|
|
2
|
+
# Copyright (c) Jerry D'Antonio -- released under the MIT license.
|
|
3
|
+
# Slightly modified; used with permission.
|
|
4
|
+
# https://github.com/ruby-concurrency/concurrent-ruby
|
|
5
|
+
|
|
6
|
+
require 'thread'
|
|
7
|
+
|
|
8
|
+
class ConnectionPool
|
|
9
|
+
|
|
10
|
+
class_definition = Class.new do
|
|
11
|
+
|
|
12
|
+
if defined?(Process::CLOCK_MONOTONIC)
|
|
13
|
+
|
|
14
|
+
# @!visibility private
|
|
15
|
+
def get_time
|
|
16
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
elsif defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
|
20
|
+
|
|
21
|
+
# @!visibility private
|
|
22
|
+
def get_time
|
|
23
|
+
java.lang.System.nanoTime() / 1_000_000_000.0
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
else
|
|
27
|
+
|
|
28
|
+
# @!visibility private
|
|
29
|
+
def initialize
|
|
30
|
+
@mutex = Mutex.new
|
|
31
|
+
@last_time = Time.now.to_f
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @!visibility private
|
|
35
|
+
def get_time
|
|
36
|
+
@mutex.synchronize do
|
|
37
|
+
now = Time.now.to_f
|
|
38
|
+
if @last_time < now
|
|
39
|
+
@last_time = now
|
|
40
|
+
else # clock has moved back in time
|
|
41
|
+
@last_time += 0.000_001
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
##
|
|
49
|
+
# Clock that cannot be set and represents monotonic time since
|
|
50
|
+
# some unspecified starting point.
|
|
51
|
+
#
|
|
52
|
+
# @!visibility private
|
|
53
|
+
GLOBAL_MONOTONIC_CLOCK = class_definition.new
|
|
54
|
+
#private_constant :GLOBAL_MONOTONIC_CLOCK # MayamaTakeshi to permit to use in ruby 1.8
|
|
55
|
+
|
|
56
|
+
class << self
|
|
57
|
+
##
|
|
58
|
+
# Returns the current time a tracked by the application monotonic clock.
|
|
59
|
+
#
|
|
60
|
+
# @return [Float] The current monotonic time when `since` not given else
|
|
61
|
+
# the elapsed monotonic time between `since` and the current time
|
|
62
|
+
def monotonic_time
|
|
63
|
+
GLOBAL_MONOTONIC_CLOCK.get_time
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
require 'thread'
|
|
2
|
+
require 'timeout'
|
|
3
|
+
require 'connection_pool/monotonic_time'
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# Raised when you attempt to retrieve a connection from a pool that has been
|
|
7
|
+
# shut down.
|
|
8
|
+
|
|
9
|
+
class ConnectionPool::PoolShuttingDownError < RuntimeError; end
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# The TimedStack manages a pool of homogeneous connections (or any resource
|
|
13
|
+
# you wish to manage). Connections are created lazily up to a given maximum
|
|
14
|
+
# number.
|
|
15
|
+
|
|
16
|
+
# Examples:
|
|
17
|
+
#
|
|
18
|
+
# ts = TimedStack.new(1) { MyConnection.new }
|
|
19
|
+
#
|
|
20
|
+
# # fetch a connection
|
|
21
|
+
# conn = ts.pop
|
|
22
|
+
#
|
|
23
|
+
# # return a connection
|
|
24
|
+
# ts.push conn
|
|
25
|
+
#
|
|
26
|
+
# conn = ts.pop
|
|
27
|
+
# ts.pop timeout: 5
|
|
28
|
+
# #=> raises Timeout::Error after 5 seconds
|
|
29
|
+
|
|
30
|
+
class ConnectionPool::TimedStack
|
|
31
|
+
attr_reader :max
|
|
32
|
+
|
|
33
|
+
##
|
|
34
|
+
# Creates a new pool with +size+ connections that are created from the given
|
|
35
|
+
# +block+.
|
|
36
|
+
|
|
37
|
+
def initialize(size = 0, &block)
|
|
38
|
+
@create_block = block
|
|
39
|
+
@created = 0
|
|
40
|
+
@que = []
|
|
41
|
+
@max = size
|
|
42
|
+
@mutex = Mutex.new
|
|
43
|
+
@resource = ConditionVariable.new
|
|
44
|
+
@shutdown_block = nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# Returns +obj+ to the stack. +options+ is ignored in TimedStack but may be
|
|
49
|
+
# used by subclasses that extend TimedStack.
|
|
50
|
+
|
|
51
|
+
def push(obj, options = {})
|
|
52
|
+
@mutex.synchronize do
|
|
53
|
+
if @shutdown_block
|
|
54
|
+
@shutdown_block.call(obj)
|
|
55
|
+
else
|
|
56
|
+
store_connection obj, options
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
@resource.broadcast
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
alias_method :<<, :push
|
|
63
|
+
|
|
64
|
+
##
|
|
65
|
+
# Retrieves a connection from the stack. If a connection is available it is
|
|
66
|
+
# immediately returned. If no connection is available within the given
|
|
67
|
+
# timeout a Timeout::Error is raised.
|
|
68
|
+
#
|
|
69
|
+
# +:timeout+ is the only checked entry in +options+ and is preferred over
|
|
70
|
+
# the +timeout+ argument (which will be removed in a future release). Other
|
|
71
|
+
# options may be used by subclasses that extend TimedStack.
|
|
72
|
+
|
|
73
|
+
def pop(timeout = 0.5, options = {})
|
|
74
|
+
options, timeout = timeout, 0.5 if Hash === timeout
|
|
75
|
+
timeout = options.fetch :timeout, timeout
|
|
76
|
+
|
|
77
|
+
deadline = ConnectionPool.monotonic_time + timeout
|
|
78
|
+
@mutex.synchronize do
|
|
79
|
+
loop do
|
|
80
|
+
raise ConnectionPool::PoolShuttingDownError if @shutdown_block
|
|
81
|
+
return fetch_connection(options) if connection_stored?(options)
|
|
82
|
+
|
|
83
|
+
connection = try_create(options)
|
|
84
|
+
return connection if connection
|
|
85
|
+
|
|
86
|
+
to_wait = deadline - ConnectionPool.monotonic_time
|
|
87
|
+
raise Timeout::Error, "Waited #{timeout} sec" if to_wait <= 0
|
|
88
|
+
@resource.wait(@mutex, to_wait)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
##
|
|
94
|
+
# Shuts down the TimedStack which prevents connections from being checked
|
|
95
|
+
# out. The +block+ is called once for each connection on the stack.
|
|
96
|
+
|
|
97
|
+
def shutdown(&block)
|
|
98
|
+
raise ArgumentError, "shutdown must receive a block" unless block_given?
|
|
99
|
+
|
|
100
|
+
@mutex.synchronize do
|
|
101
|
+
@shutdown_block = block
|
|
102
|
+
@resource.broadcast
|
|
103
|
+
|
|
104
|
+
shutdown_connections
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
##
|
|
109
|
+
# Returns +true+ if there are no available connections.
|
|
110
|
+
|
|
111
|
+
def empty?
|
|
112
|
+
(@created - @que.length) >= @max
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
##
|
|
116
|
+
# The number of connections available on the stack.
|
|
117
|
+
|
|
118
|
+
def length
|
|
119
|
+
@max - @created + @que.length
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
private
|
|
123
|
+
|
|
124
|
+
##
|
|
125
|
+
# This is an extension point for TimedStack and is called with a mutex.
|
|
126
|
+
#
|
|
127
|
+
# This method must returns true if a connection is available on the stack.
|
|
128
|
+
|
|
129
|
+
def connection_stored?(options = nil)
|
|
130
|
+
!@que.empty?
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
##
|
|
134
|
+
# This is an extension point for TimedStack and is called with a mutex.
|
|
135
|
+
#
|
|
136
|
+
# This method must return a connection from the stack.
|
|
137
|
+
|
|
138
|
+
def fetch_connection(options = nil)
|
|
139
|
+
@que.pop
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
##
|
|
143
|
+
# This is an extension point for TimedStack and is called with a mutex.
|
|
144
|
+
#
|
|
145
|
+
# This method must shut down all connections on the stack.
|
|
146
|
+
|
|
147
|
+
def shutdown_connections(options = nil)
|
|
148
|
+
while connection_stored?(options)
|
|
149
|
+
conn = fetch_connection(options)
|
|
150
|
+
@shutdown_block.call(conn)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
##
|
|
155
|
+
# This is an extension point for TimedStack and is called with a mutex.
|
|
156
|
+
#
|
|
157
|
+
# This method must return +obj+ to the stack.
|
|
158
|
+
|
|
159
|
+
def store_connection(obj, options = nil)
|
|
160
|
+
@que.push obj
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
##
|
|
164
|
+
# This is an extension point for TimedStack and is called with a mutex.
|
|
165
|
+
#
|
|
166
|
+
# This method must create a connection if and only if the total number of
|
|
167
|
+
# connections allowed has not been met.
|
|
168
|
+
|
|
169
|
+
def try_create(options = nil)
|
|
170
|
+
unless @created == @max
|
|
171
|
+
object = @create_block.call
|
|
172
|
+
@created += 1
|
|
173
|
+
object
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|