connection_pool 0.0.1
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/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +2 -0
- data/connection_pool.gemspec +17 -0
- data/lib/connection_pool.rb +70 -0
- data/lib/connection_pool/timed_queue.rb +48 -0
- data/lib/connection_pool/version.rb +3 -0
- metadata +74 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require "./lib/connection_pool/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "connection_pool"
|
6
|
+
s.version = ConnectionPool::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["Mike Perham"]
|
9
|
+
s.email = ["mperham@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.description = s.summary = %q{Generic connection pool for Ruby}
|
12
|
+
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'connection_pool/timed_queue'
|
2
|
+
|
3
|
+
# Generic connection pool class for e.g. sharing a limited number of network connections
|
4
|
+
# among many threads. Note: Connections are eager created.
|
5
|
+
#
|
6
|
+
# Example usage with block (faster):
|
7
|
+
#
|
8
|
+
# @pool = ConnectionPool.new { Redis.new }
|
9
|
+
#
|
10
|
+
# @pool.with do |redis|
|
11
|
+
# redis.lpop if redis.llen('my-list') > 0
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# Example usage replacing a global connection (slower):
|
15
|
+
#
|
16
|
+
# REDIS = ConnectionPool.new { Redis.new }
|
17
|
+
#
|
18
|
+
# def do_work
|
19
|
+
# REDIS.lpop if REDIS.llen('my-list') > 0
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# Accepts the following options:
|
23
|
+
# - :size - number of connections to pool, defaults to 5
|
24
|
+
# - :timeout - amount of time to wait for a connection if none currently available, defaults to 5 seconds
|
25
|
+
#
|
26
|
+
class ConnectionPool
|
27
|
+
DEFAULTS = { :size => 5, :timeout => 5 }
|
28
|
+
|
29
|
+
def initialize(options={})
|
30
|
+
raise ArgumentError, 'Connection pool requires a block' unless block_given?
|
31
|
+
|
32
|
+
@available = TimedQueue.new
|
33
|
+
@options = DEFAULTS.merge(options)
|
34
|
+
@options[:size].times do
|
35
|
+
@available << yield
|
36
|
+
end
|
37
|
+
@busy = []
|
38
|
+
end
|
39
|
+
|
40
|
+
def with(&block)
|
41
|
+
yield checkout
|
42
|
+
ensure
|
43
|
+
checkin
|
44
|
+
end
|
45
|
+
|
46
|
+
def method_missing(name, *args)
|
47
|
+
checkout.send(name, *args)
|
48
|
+
ensure
|
49
|
+
checkin
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def checkout
|
55
|
+
Thread.current[:"current-#{self.object_id}"] ||= begin
|
56
|
+
conn = @available.timed_pop(@options[:timeout])
|
57
|
+
@busy << conn
|
58
|
+
conn
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def checkin
|
63
|
+
conn = Thread.current[:"current-#{self.object_id}"]
|
64
|
+
Thread.current[:"current-#{self.object_id}"] = nil
|
65
|
+
@busy.delete(conn)
|
66
|
+
@available << conn
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'thread'
|
2
|
+
require 'timeout'
|
3
|
+
|
4
|
+
class TimedQueue
|
5
|
+
def initialize
|
6
|
+
@que = []
|
7
|
+
@waiting = []
|
8
|
+
@mutex = Mutex.new
|
9
|
+
@resource = ConditionVariable.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def push(obj)
|
13
|
+
@mutex.synchronize do
|
14
|
+
@que.push obj
|
15
|
+
@resource.signal
|
16
|
+
end
|
17
|
+
end
|
18
|
+
alias << push
|
19
|
+
|
20
|
+
def timed_pop(timeout=0.5)
|
21
|
+
while true
|
22
|
+
@mutex.synchronize do
|
23
|
+
@waiting.delete(Thread.current)
|
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
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def empty?
|
38
|
+
@que.empty?
|
39
|
+
end
|
40
|
+
|
41
|
+
def clear
|
42
|
+
@que.clear
|
43
|
+
end
|
44
|
+
|
45
|
+
def length
|
46
|
+
@que.length
|
47
|
+
end
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: connection_pool
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Mike Perham
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-05-14 00:00:00 -07:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Generic connection pool for Ruby
|
23
|
+
email:
|
24
|
+
- mperham@gmail.com
|
25
|
+
executables: []
|
26
|
+
|
27
|
+
extensions: []
|
28
|
+
|
29
|
+
extra_rdoc_files: []
|
30
|
+
|
31
|
+
files:
|
32
|
+
- .gitignore
|
33
|
+
- Gemfile
|
34
|
+
- Rakefile
|
35
|
+
- connection_pool.gemspec
|
36
|
+
- lib/connection_pool.rb
|
37
|
+
- lib/connection_pool/timed_queue.rb
|
38
|
+
- lib/connection_pool/version.rb
|
39
|
+
has_rdoc: true
|
40
|
+
homepage: ""
|
41
|
+
licenses: []
|
42
|
+
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
hash: 3
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
version: "0"
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
hash: 3
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
66
|
+
requirements: []
|
67
|
+
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 1.5.2
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: Generic connection pool for Ruby
|
73
|
+
test_files: []
|
74
|
+
|