connection_pool 0.0.1 → 0.0.2
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/Gemfile +2 -0
- data/LICENSE +20 -0
- data/README.md +30 -0
- data/Rakefile +9 -0
- data/lib/connection_pool.rb +5 -3
- data/lib/connection_pool/timed_queue.rb +6 -14
- data/lib/connection_pool/version.rb +1 -1
- data/test/helper.rb +16 -0
- data/test/test_connection_pool.rb +68 -0
- metadata +9 -15
data/Gemfile
CHANGED
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,30 @@
|
|
1
|
+
connection_pool
|
2
|
+
======================
|
3
|
+
|
4
|
+
Generic connection pooling for Ruby.
|
5
|
+
|
6
|
+
MongoDB has its own connection pool. ActiveRecord has its own connection pool. This is a generic connection pool that can be used with anything, e.g. Redis, Dalli and other Ruby network clients.
|
7
|
+
|
8
|
+
Install
|
9
|
+
------------
|
10
|
+
|
11
|
+
gem install connection_pool
|
12
|
+
|
13
|
+
Usage
|
14
|
+
------------
|
15
|
+
|
16
|
+
Create a pool of objects to share amongst the fibers or threads in your Ruby application:
|
17
|
+
|
18
|
+
@memcached = ConnectionPool.new(:size => 5, :timeout => 5) { Dalli::Client.new }
|
19
|
+
|
20
|
+
Then use the pool in your application:
|
21
|
+
|
22
|
+
@memcached.with_connection do |dalli|
|
23
|
+
dalli.get('some-count')
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
Author
|
28
|
+
--------------
|
29
|
+
|
30
|
+
Mike Perham, [@mperham](https://twitter.com/mperham), <http://mikeperham.com>
|
data/Rakefile
CHANGED
data/lib/connection_pool.rb
CHANGED
@@ -8,7 +8,7 @@ require 'connection_pool/timed_queue'
|
|
8
8
|
# @pool = ConnectionPool.new { Redis.new }
|
9
9
|
#
|
10
10
|
# @pool.with do |redis|
|
11
|
-
# redis.lpop if redis.llen('my-list') > 0
|
11
|
+
# redis.lpop('my-list') if redis.llen('my-list') > 0
|
12
12
|
# end
|
13
13
|
#
|
14
14
|
# Example usage replacing a global connection (slower):
|
@@ -16,7 +16,7 @@ require 'connection_pool/timed_queue'
|
|
16
16
|
# REDIS = ConnectionPool.new { Redis.new }
|
17
17
|
#
|
18
18
|
# def do_work
|
19
|
-
# REDIS.lpop if REDIS.llen('my-list') > 0
|
19
|
+
# REDIS.lpop('my-list') if REDIS.llen('my-list') > 0
|
20
20
|
# end
|
21
21
|
#
|
22
22
|
# Accepts the following options:
|
@@ -42,6 +42,7 @@ class ConnectionPool
|
|
42
42
|
ensure
|
43
43
|
checkin
|
44
44
|
end
|
45
|
+
alias_method :with_connection, :with
|
45
46
|
|
46
47
|
def method_missing(name, *args)
|
47
48
|
checkout.send(name, *args)
|
@@ -62,9 +63,10 @@ class ConnectionPool
|
|
62
63
|
def checkin
|
63
64
|
conn = Thread.current[:"current-#{self.object_id}"]
|
64
65
|
Thread.current[:"current-#{self.object_id}"] = nil
|
66
|
+
return unless conn
|
65
67
|
@busy.delete(conn)
|
66
68
|
@available << conn
|
67
69
|
nil
|
68
70
|
end
|
69
71
|
|
70
|
-
end
|
72
|
+
end
|
@@ -4,7 +4,6 @@ require 'timeout'
|
|
4
4
|
class TimedQueue
|
5
5
|
def initialize
|
6
6
|
@que = []
|
7
|
-
@waiting = []
|
8
7
|
@mutex = Mutex.new
|
9
8
|
@resource = ConditionVariable.new
|
10
9
|
end
|
@@ -15,22 +14,15 @@ class TimedQueue
|
|
15
14
|
@resource.signal
|
16
15
|
end
|
17
16
|
end
|
18
|
-
|
17
|
+
alias_method :<<, :push
|
19
18
|
|
20
19
|
def timed_pop(timeout=0.5)
|
21
|
-
|
22
|
-
@
|
23
|
-
@
|
24
|
-
if @que.empty?
|
25
|
-
@waiting.push Thread.current
|
26
|
-
@resource.wait(@mutex, timeout)
|
27
|
-
raise TimeoutError if @que.empty?
|
28
|
-
else
|
29
|
-
retval = @que.shift
|
30
|
-
@resource.signal
|
31
|
-
return retval
|
32
|
-
end
|
20
|
+
@mutex.synchronize do
|
21
|
+
if @que.empty?
|
22
|
+
@resource.wait(@mutex, timeout)
|
23
|
+
raise Timeout::Error if @que.empty?
|
33
24
|
end
|
25
|
+
return @que.shift
|
34
26
|
end
|
35
27
|
end
|
36
28
|
|
data/test/helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
|
4
|
+
require 'connection_pool'
|
5
|
+
|
6
|
+
puts RUBY_DESCRIPTION
|
7
|
+
|
8
|
+
class MiniTest::Unit::TestCase
|
9
|
+
|
10
|
+
def async_test(time=0.5)
|
11
|
+
q = TimedQueue.new
|
12
|
+
yield Proc.new { q << nil }
|
13
|
+
q.timed_pop(time)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestConnectionPool < MiniTest::Unit::TestCase
|
4
|
+
|
5
|
+
class NetworkConnection
|
6
|
+
def initialize
|
7
|
+
@x = 0
|
8
|
+
end
|
9
|
+
def do_something
|
10
|
+
@x += 1
|
11
|
+
sleep 0.05
|
12
|
+
@x
|
13
|
+
end
|
14
|
+
def fast
|
15
|
+
@x += 1
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_basic_multithreaded_usage
|
20
|
+
pool = ConnectionPool.new(:size => 5) { NetworkConnection.new }
|
21
|
+
threads = []
|
22
|
+
15.times do
|
23
|
+
threads << Thread.new do
|
24
|
+
pool.with_connection do |net|
|
25
|
+
net.do_something
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
a = Time.now
|
31
|
+
result = threads.map(&:value)
|
32
|
+
b = Time.now
|
33
|
+
assert_operator((b - a), :>, 0.125)
|
34
|
+
assert_equal(result, [1,2,3].cycle(5).sort)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_timeout
|
38
|
+
pool = ConnectionPool.new(:timeout => 0.05, :size => 1) { NetworkConnection.new }
|
39
|
+
Thread.new do
|
40
|
+
pool.with do |net|
|
41
|
+
net.do_something
|
42
|
+
sleep 0.1
|
43
|
+
end
|
44
|
+
end
|
45
|
+
sleep 0.05
|
46
|
+
assert_raises Timeout::Error do
|
47
|
+
pool.do_something
|
48
|
+
end
|
49
|
+
|
50
|
+
pool.with do |conn|
|
51
|
+
refute_nil conn
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_passthru
|
56
|
+
pool = ConnectionPool.new(:timeout => 0.1, :size => 1) { NetworkConnection.new }
|
57
|
+
assert_equal 1, pool.do_something
|
58
|
+
assert_equal 2, pool.do_something
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_return_value
|
62
|
+
pool = ConnectionPool.new(:timeout => 0.1, :size => 1) { NetworkConnection.new }
|
63
|
+
result = pool.with_connection do |net|
|
64
|
+
net.fast
|
65
|
+
end
|
66
|
+
assert_equal 1, result
|
67
|
+
end
|
68
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: connection_pool
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 29
|
5
4
|
prerelease:
|
6
|
-
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 1
|
10
|
-
version: 0.0.1
|
5
|
+
version: 0.0.2
|
11
6
|
platform: ruby
|
12
7
|
authors:
|
13
8
|
- Mike Perham
|
@@ -15,7 +10,7 @@ autorequire:
|
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
12
|
|
18
|
-
date: 2011-
|
13
|
+
date: 2011-09-09 00:00:00 -07:00
|
19
14
|
default_executable:
|
20
15
|
dependencies: []
|
21
16
|
|
@@ -31,11 +26,15 @@ extra_rdoc_files: []
|
|
31
26
|
files:
|
32
27
|
- .gitignore
|
33
28
|
- Gemfile
|
29
|
+
- LICENSE
|
30
|
+
- README.md
|
34
31
|
- Rakefile
|
35
32
|
- connection_pool.gemspec
|
36
33
|
- lib/connection_pool.rb
|
37
34
|
- lib/connection_pool/timed_queue.rb
|
38
35
|
- lib/connection_pool/version.rb
|
36
|
+
- test/helper.rb
|
37
|
+
- test/test_connection_pool.rb
|
39
38
|
has_rdoc: true
|
40
39
|
homepage: ""
|
41
40
|
licenses: []
|
@@ -50,18 +49,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
50
49
|
requirements:
|
51
50
|
- - ">="
|
52
51
|
- !ruby/object:Gem::Version
|
53
|
-
hash: 3
|
54
|
-
segments:
|
55
|
-
- 0
|
56
52
|
version: "0"
|
57
53
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
54
|
none: false
|
59
55
|
requirements:
|
60
56
|
- - ">="
|
61
57
|
- !ruby/object:Gem::Version
|
62
|
-
hash: 3
|
63
|
-
segments:
|
64
|
-
- 0
|
65
58
|
version: "0"
|
66
59
|
requirements: []
|
67
60
|
|
@@ -70,5 +63,6 @@ rubygems_version: 1.5.2
|
|
70
63
|
signing_key:
|
71
64
|
specification_version: 3
|
72
65
|
summary: Generic connection pool for Ruby
|
73
|
-
test_files:
|
74
|
-
|
66
|
+
test_files:
|
67
|
+
- test/helper.rb
|
68
|
+
- test/test_connection_pool.rb
|