generic_connection_pool 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README +47 -0
- data/Rakefile +31 -0
- data/lib/connection_pool.rb +247 -0
- data/lib/generic_connection_pool.rb +1 -0
- data/spec/connection_pool_spec.rb +98 -0
- data/spec/spec_helper.rb +2 -0
- metadata +105 -0
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Kame Chen
|
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
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
= generic_connection_pool
|
2
|
+
|
3
|
+
== DESCRIPTION
|
4
|
+
Always network clients require a connection pool, like database connection, cache connection and others.
|
5
|
+
Generic connection pool can be used with anything. It is inspired from ActiveRecord ConnectionPool.
|
6
|
+
Sharing a limited number of network connections among many threads.
|
7
|
+
Connections are created delayed.
|
8
|
+
|
9
|
+
== USEAGE
|
10
|
+
|
11
|
+
Connections can be obtained and used from a connection pool in several
|
12
|
+
ways:
|
13
|
+
|
14
|
+
1. Use connection_pool.connection to obtain a connection instance.
|
15
|
+
and when you're done with the connection(s) and wish it to be returned
|
16
|
+
to the pool, you can call connection_pool.release_connection to release
|
17
|
+
connection back to the connection pool.
|
18
|
+
2. Manually check out a connection from the pool with connection_pool.checkout.
|
19
|
+
You are responsible for returning this connection to the pool when
|
20
|
+
finished by calling connection_pool.checkin(connection).
|
21
|
+
3. Use connection_pool.with_connection(&block), which obtains a connection,
|
22
|
+
yields it as the sole argument to the block, and returns it to the pool
|
23
|
+
after the block completes.
|
24
|
+
|
25
|
+
Connections in the pool may be Adapter instance that should implete methods like
|
26
|
+
verify!, disconnect!, active? etc.
|
27
|
+
|
28
|
+
== Example
|
29
|
+
require 'generic_connection_pool'
|
30
|
+
connection_pool = ConnectionPool.new(:size => 5, :timeout => 5) do
|
31
|
+
new_connection_adapter
|
32
|
+
end
|
33
|
+
connection_pool.connection
|
34
|
+
connection_pool.release_connection
|
35
|
+
|
36
|
+
connection = connection_pool.checkout
|
37
|
+
connection_pool.checkin(connection)
|
38
|
+
|
39
|
+
connection.with_connection{|connection| do_somting_with_connection}
|
40
|
+
|
41
|
+
Do something in the block, that always create an adapter instance or connect to a server.
|
42
|
+
|
43
|
+
== INSTALL
|
44
|
+
gem install generic_connection_pool
|
45
|
+
|
46
|
+
== AUTHOR
|
47
|
+
Kame Chen
|
data/Rakefile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
require 'rake/gempackagetask'
|
6
|
+
require 'spec'
|
7
|
+
require 'spec/rake/spectask'
|
8
|
+
|
9
|
+
desc 'Default: run test.'
|
10
|
+
task :default => :spec
|
11
|
+
|
12
|
+
desc 'Test the ao_locked gem.'
|
13
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
14
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
15
|
+
t.spec_opts = ['-c','-f','nested']
|
16
|
+
end
|
17
|
+
|
18
|
+
desc 'Generate documentation for the ao_locked gem.'
|
19
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
20
|
+
rdoc.rdoc_dir = 'rdoc'
|
21
|
+
rdoc.title = 'ConnectionPool'
|
22
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
23
|
+
rdoc.rdoc_files.include('README')
|
24
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
25
|
+
end
|
26
|
+
|
27
|
+
spec = eval(File.read(File.expand_path("../generic_connection_pool.gemspec", __FILE__)))
|
28
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
29
|
+
pkg.need_zip = false
|
30
|
+
pkg.need_tar = false
|
31
|
+
end
|
@@ -0,0 +1,247 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_support/core_ext/module/synchronization'
|
3
|
+
require 'monitor'
|
4
|
+
require 'set'
|
5
|
+
require 'timeout'
|
6
|
+
# Generic connection pool class inspired from ActiveRecord ConnectionPool.
|
7
|
+
# Sharing a limited number of network connections among many threads.
|
8
|
+
# Connections are created delayed.
|
9
|
+
#
|
10
|
+
# == Introduction
|
11
|
+
#
|
12
|
+
# A connection pool synchronizes thread access to a limited number of
|
13
|
+
# network connections. The basic idea is that each thread checks out a
|
14
|
+
# database connection from the pool, uses that connection, and checks the
|
15
|
+
# connection back in. ConnectionPool is completely thread-safe, and will
|
16
|
+
# ensure that a connection cannot be used by two threads at the same time,
|
17
|
+
# as long as ConnectionPool's contract is correctly followed. It will also
|
18
|
+
# handle cases in which there are more threads than connections: if all
|
19
|
+
# connections have been checked out, and a thread tries to checkout a
|
20
|
+
# connection anyway, then ConnectionPool will wait until some other thread
|
21
|
+
# has checked in a connection.
|
22
|
+
#
|
23
|
+
# == Obtaining (checking out) a connection
|
24
|
+
#
|
25
|
+
# Connections can be obtained and used from a connection pool in several
|
26
|
+
# ways:
|
27
|
+
#
|
28
|
+
# 1. Use connection_pool.connection to obtain a connection instance.
|
29
|
+
# and when you're done with the connection(s) and wish it to be returned
|
30
|
+
# to the pool, you can call connection_pool.release_connection to release
|
31
|
+
# connection back to the connection pool.
|
32
|
+
# 2. Manually check out a connection from the pool with connection_pool.checkout.
|
33
|
+
# You are responsible for returning this connection to the pool when
|
34
|
+
# finished by calling connection_pool.checkin(connection).
|
35
|
+
# 3. Use connection_pool.with_connection(&block), which obtains a connection,
|
36
|
+
# yields it as the sole argument to the block, and returns it to the pool
|
37
|
+
# after the block completes.
|
38
|
+
#
|
39
|
+
# Connections in the pool may be Adapter instance that should implete methods like
|
40
|
+
# verify!, disconnect!, active? etc.
|
41
|
+
#
|
42
|
+
# == Example
|
43
|
+
#
|
44
|
+
# connection_pool = ConnectionPool.new(:size => 5, :timeout => 5) do
|
45
|
+
# new_connection_adapter
|
46
|
+
# end
|
47
|
+
# connection_pool.connection
|
48
|
+
# connection_pool.release_connection
|
49
|
+
#
|
50
|
+
# connection = connection_pool.checkout
|
51
|
+
# connection_pool.checkin(connection)
|
52
|
+
#
|
53
|
+
# connection.with_connection{|connection| do_somting_with_connection}
|
54
|
+
#
|
55
|
+
#
|
56
|
+
# Do something in the block, that always create an adapter instance or connect to a server.
|
57
|
+
#
|
58
|
+
class ConnectionPool
|
59
|
+
VERSION = '0.1.0'
|
60
|
+
|
61
|
+
class ConnectionTimeoutError < ::Timeout::Error
|
62
|
+
end
|
63
|
+
|
64
|
+
attr_reader :options
|
65
|
+
|
66
|
+
DEFAULT_OPTIONS = { :size => 5, :timeout => 5 }
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
# Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification
|
71
|
+
# object which describes database connection information (e.g. adapter,
|
72
|
+
# host name, username, password, etc), as well as the maximum size for
|
73
|
+
# this ConnectionPool.
|
74
|
+
#
|
75
|
+
# The default ConnectionPool maximum size is 5.
|
76
|
+
def initialize(options = {}, &block)
|
77
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
78
|
+
|
79
|
+
raise ArgumentError, "Connection pool requires a block that create a new connection!" unless block
|
80
|
+
|
81
|
+
@connection_block = block
|
82
|
+
|
83
|
+
# The cache of reserved connections mapped to threads
|
84
|
+
@reserved_connections = {}
|
85
|
+
|
86
|
+
# The mutex used to synchronize pool access
|
87
|
+
@connection_mutex = Monitor.new
|
88
|
+
@queue = @connection_mutex.new_cond
|
89
|
+
|
90
|
+
# default 5 second timeout
|
91
|
+
@timeout = @options[:timeout]
|
92
|
+
|
93
|
+
# default max pool size to 5
|
94
|
+
@size = @options[:size]
|
95
|
+
|
96
|
+
@connections = []
|
97
|
+
@checked_out = []
|
98
|
+
end
|
99
|
+
|
100
|
+
# Retrieve the connection associated with the current thread, or call
|
101
|
+
# #checkout to obtain one if necessary.
|
102
|
+
#
|
103
|
+
# #connection can be called any number of times; the connection is
|
104
|
+
# held in a hash keyed by the thread id.
|
105
|
+
def connection
|
106
|
+
@reserved_connections[current_connection_id] ||= checkout
|
107
|
+
end
|
108
|
+
|
109
|
+
# Signal that the thread is finished with the current connection.
|
110
|
+
# #release_connection releases the connection-thread association
|
111
|
+
# and returns the connection to the pool.
|
112
|
+
def release_connection
|
113
|
+
conn = @reserved_connections.delete(current_connection_id)
|
114
|
+
checkin conn if conn
|
115
|
+
end
|
116
|
+
|
117
|
+
# If a connection already exists yield it to the block. If no connection
|
118
|
+
# exists checkout a connection, yield it to the block, and checkin the
|
119
|
+
# connection when finished.
|
120
|
+
def with_connection
|
121
|
+
fresh_connection = true unless connection_cached?
|
122
|
+
yield connection
|
123
|
+
ensure
|
124
|
+
release_connection if fresh_connection
|
125
|
+
end
|
126
|
+
|
127
|
+
# Returns true if a connection has already been opened.
|
128
|
+
def connected?
|
129
|
+
!@connections.empty?
|
130
|
+
end
|
131
|
+
|
132
|
+
# Disconnects all connections in the pool, and clears the pool.
|
133
|
+
def disconnect!
|
134
|
+
@reserved_connections.each do |name,conn|
|
135
|
+
checkin conn
|
136
|
+
end
|
137
|
+
@reserved_connections = {}
|
138
|
+
@connections.each do |conn|
|
139
|
+
conn.disconnect!
|
140
|
+
end
|
141
|
+
@connections = []
|
142
|
+
end
|
143
|
+
|
144
|
+
# Verify active connections and remove and disconnect connections
|
145
|
+
# associated with stale threads.
|
146
|
+
def verify_active_connections! #:nodoc:
|
147
|
+
clear_stale_cached_connections!
|
148
|
+
@connections.each do |connection|
|
149
|
+
connection.verify!
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Return any checked-out connections back to the pool by threads that
|
154
|
+
# are no longer alive.
|
155
|
+
def clear_stale_cached_connections!
|
156
|
+
keys = @reserved_connections.keys - Thread.list.find_all { |t|
|
157
|
+
t.alive?
|
158
|
+
}.map { |thread| thread.object_id }
|
159
|
+
keys.each do |key|
|
160
|
+
checkin @reserved_connections[key]
|
161
|
+
@reserved_connections.delete(key)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# Check-out a database connection from the pool, indicating that you want
|
166
|
+
# to use it. You should call #checkin when you no longer need this.
|
167
|
+
#
|
168
|
+
# This is done by either returning an existing connection, or by creating
|
169
|
+
# a new connection. If the maximum number of connections for this pool has
|
170
|
+
# already been reached, but the pool is empty (i.e. they're all being used),
|
171
|
+
# then this method will wait until a thread has checked in a connection.
|
172
|
+
# The wait time is bounded however: if no connection can be checked out
|
173
|
+
# within the timeout specified for this pool, then a ConnectionTimeoutError
|
174
|
+
# exception will be raised.
|
175
|
+
#
|
176
|
+
# Returns: connection instance return by the connection_block
|
177
|
+
#
|
178
|
+
def checkout
|
179
|
+
# Checkout an available connection
|
180
|
+
@connection_mutex.synchronize do
|
181
|
+
loop do
|
182
|
+
conn = if @checked_out.size < @connections.size
|
183
|
+
checkout_existing_connection
|
184
|
+
elsif @connections.size < @size
|
185
|
+
checkout_new_connection
|
186
|
+
end
|
187
|
+
return conn if conn
|
188
|
+
# No connections available; wait for one
|
189
|
+
if @queue.wait(@timeout)
|
190
|
+
next
|
191
|
+
else
|
192
|
+
# try looting dead threads
|
193
|
+
clear_stale_cached_connections!
|
194
|
+
if @size == @checked_out.size
|
195
|
+
raise ConnectionTimeoutError, "Could not obtain a connection within #{@timeout} seconds. The max pool size is currently #{@size}; consider increasing it."
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
# Check-in a connection back into the pool, indicating that you
|
203
|
+
# no longer need this connection.
|
204
|
+
#
|
205
|
+
# +conn+: which was obtained by earlier by calling +checkout+ on this pool.
|
206
|
+
def checkin(conn)
|
207
|
+
@connection_mutex.synchronize do
|
208
|
+
@checked_out.delete conn
|
209
|
+
@queue.signal
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
# whether connection cached in the current thread
|
214
|
+
def connection_cached?
|
215
|
+
!!@reserved_connections[current_connection_id]
|
216
|
+
end
|
217
|
+
|
218
|
+
synchronize :verify_active_connections!, :connected?, :disconnect!, :with => :@connection_mutex
|
219
|
+
|
220
|
+
private
|
221
|
+
def new_connection
|
222
|
+
@connection_block.call
|
223
|
+
end
|
224
|
+
|
225
|
+
def current_connection_id #:nodoc:
|
226
|
+
Thread.current.object_id
|
227
|
+
end
|
228
|
+
|
229
|
+
def checkout_new_connection
|
230
|
+
c = new_connection
|
231
|
+
@connections << c
|
232
|
+
checkout_and_verify(c)
|
233
|
+
end
|
234
|
+
|
235
|
+
def checkout_existing_connection
|
236
|
+
c = (@connections - @checked_out).first
|
237
|
+
checkout_and_verify(c)
|
238
|
+
end
|
239
|
+
|
240
|
+
def checkout_and_verify(c)
|
241
|
+
# connection must have verify! method that verify the connection active;
|
242
|
+
# it should auto retry to reconnect if not active.
|
243
|
+
c.verify!
|
244
|
+
@checked_out << c
|
245
|
+
c
|
246
|
+
end
|
247
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require File.expand_path('../connection_pool', __FILE__)
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require File.expand_path("../", __FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
def mock_connection_adapter
|
4
|
+
mock_connection_adapter = mock("connection_adapter")
|
5
|
+
mock_connection_adapter.stub!(:verify!)
|
6
|
+
mock_connection_adapter.stub!(:active?)
|
7
|
+
mock_connection_adapter.stub!(:disconnect!)
|
8
|
+
mock_connection_adapter
|
9
|
+
end
|
10
|
+
|
11
|
+
describe ConnectionPool do
|
12
|
+
describe "initialize ConnectionPool" do
|
13
|
+
it "raise ArgumentError if block not given" do
|
14
|
+
lambda{ConnectionPool.new}.should raise_error(ArgumentError)
|
15
|
+
end
|
16
|
+
it "connection pool size default 5, and can customize" do
|
17
|
+
ConnectionPool.new{}.options[:size].should == 5
|
18
|
+
ConnectionPool.new(:size => 10){}.options[:size].should == 10
|
19
|
+
end
|
20
|
+
it "connection timeout default 5, and can customize" do
|
21
|
+
ConnectionPool.new{}.options[:timeout].should == 5
|
22
|
+
ConnectionPool.new(:timeout => 10){}.options[:timeout].should == 10
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#connection" do
|
27
|
+
before do
|
28
|
+
@connection_pool = ConnectionPool.new{mock_connection_adapter}
|
29
|
+
end
|
30
|
+
it "should return a connection from connection pool" do
|
31
|
+
@connection_pool.connection.should_not be_nil
|
32
|
+
end
|
33
|
+
it "should cache the connection when call the #connection method and repeat call multi times should return the same connection if in the same thread" do
|
34
|
+
@connection_pool.connection.should == @connection_pool.connection
|
35
|
+
@connection_pool.should be_connection_cached
|
36
|
+
end
|
37
|
+
it "in different threads should return different connection when call #connection method" do
|
38
|
+
main_thread_connection = @connection_pool.connection
|
39
|
+
Thread.new{@connection_pool.connection.should_not == main_thread_connection}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#release_connection" do
|
44
|
+
before do
|
45
|
+
@connection_pool = ConnectionPool.new{mock_connection_adapter}
|
46
|
+
end
|
47
|
+
it "should delete the cached connection" do
|
48
|
+
@connection_pool.connection
|
49
|
+
@connection_pool.release_connection
|
50
|
+
@connection_pool.should_not be_connection_cached
|
51
|
+
end
|
52
|
+
it "should check in the connection back to the connection pool" do
|
53
|
+
@connection_pool.connection
|
54
|
+
@connection_pool.release_connection
|
55
|
+
@connection_pool.instance_variable_get("@checked_out").should be_empty
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#checkout " do
|
60
|
+
before do
|
61
|
+
@connection_pool = ConnectionPool.new{mock_connection_adapter}
|
62
|
+
@exist_connections = []
|
63
|
+
5.times do
|
64
|
+
Thread.new{con = @connection_pool.checkout; @exist_connections << con}
|
65
|
+
end
|
66
|
+
@exist_connections.each{|con|@connection_pool.checkin(con)}
|
67
|
+
end
|
68
|
+
it "should checkout the exist connection if connections not empty" do
|
69
|
+
con = @connection_pool.checkout
|
70
|
+
@exist_connections.should include(con)
|
71
|
+
end
|
72
|
+
it "should raise error if can not obtain a connection for timeout" do
|
73
|
+
threads = []
|
74
|
+
5.times do
|
75
|
+
threads << Thread.new{@connection_pool.checkout; sleep(5)}
|
76
|
+
end
|
77
|
+
lambda{@connection_pool.checkout}.should raise_error(ConnectionPool::ConnectionTimeoutError)
|
78
|
+
threads.each(&:join)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "#with_connection" do
|
83
|
+
before do
|
84
|
+
@connection_pool = ConnectionPool.new{mock_connection_adapter}
|
85
|
+
end
|
86
|
+
it "should check in the connection back to the pool if it is a fresh connection" do
|
87
|
+
@connection_pool.with_connection{|connection|}
|
88
|
+
@connection_pool.should_not be_connection_cached
|
89
|
+
@connection_pool.instance_variable_get("@checked_out").should be_empty
|
90
|
+
end
|
91
|
+
it "should not check in the connection back to the pool if it is a cached connection" do
|
92
|
+
@connection_pool.connection
|
93
|
+
@connection_pool.with_connection{|connection|}
|
94
|
+
@connection_pool.should be_connection_cached
|
95
|
+
@connection_pool.instance_variable_get("@checked_out").should_not be_empty
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: generic_connection_pool
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- kame
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-12-28 00:00:00 +08:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: activesupport
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rspec
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
49
|
+
description: " Always network clients require a connection pool, like database connection, cache connection and others.\n\
|
50
|
+
Generic connection pool can be used with anything. It is inspired from ActiveRecord ConnectionPool.\n\
|
51
|
+
Sharing a limited number of network connections among many threads.\n\
|
52
|
+
Connections are created delayed.\n"
|
53
|
+
email:
|
54
|
+
- kamechb@gmail.com
|
55
|
+
executables: []
|
56
|
+
|
57
|
+
extensions: []
|
58
|
+
|
59
|
+
extra_rdoc_files: []
|
60
|
+
|
61
|
+
files:
|
62
|
+
- lib/connection_pool.rb
|
63
|
+
- lib/generic_connection_pool.rb
|
64
|
+
- spec/connection_pool_spec.rb
|
65
|
+
- spec/spec_helper.rb
|
66
|
+
- Rakefile
|
67
|
+
- README
|
68
|
+
- Gemfile
|
69
|
+
- LICENSE
|
70
|
+
has_rdoc: true
|
71
|
+
homepage:
|
72
|
+
licenses: []
|
73
|
+
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
hash: 3
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
hash: 3
|
94
|
+
segments:
|
95
|
+
- 0
|
96
|
+
version: "0"
|
97
|
+
requirements: []
|
98
|
+
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 1.6.2
|
101
|
+
signing_key:
|
102
|
+
specification_version: 3
|
103
|
+
summary: Always network clients require a connection pool, like database connection, cache connection and others. Generic connection pool can be used with anything. It is inspired from ActiveRecord ConnectionPool. Sharing a limited number of network connections among many threads. Connections are created delayed.
|
104
|
+
test_files: []
|
105
|
+
|