connection_pool 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b24f806aed835d638868cfeee4d30cd53b32c561
4
- data.tar.gz: eeb809403e4ae18c350800712b97d9b65cff0194
3
+ metadata.gz: d46787d5f1cdf8901aff57ded2eb518418fea245
4
+ data.tar.gz: 0ffd3058f4269e9155070e901dd4eb29db2e81d7
5
5
  SHA512:
6
- metadata.gz: f815103822aaced056e316cf955a3d6a35fbb07b9e87d6f646e83a324e8c28aba570c55f0561ef94bcd76134670320f441c1141bcc2103f82843aa17d0ab42a2
7
- data.tar.gz: d5883346fa243b8d0de199288722d4ec84092dbe4a8c984c33c4c48c3deb4f4ce0d11187be0a83941bac1231341b4a98f7f2d5968c6d4f5c159df6a15eddc365
6
+ metadata.gz: 9adff3406500853bcf8fcd480cce510cab1cf03b3d31cf2429648e92973b012000ba9d4a8e252efbce486f38f00b7df86527073d9d3f0212e967d8624675fe03
7
+ data.tar.gz: 609a9f24d0472bf9df5989e6830118873a9ae779738945e80c7b5e7010aa205b545af949fc4fa2233ccb5bb4379e9b54d2118f42c4900ac81bb262e790b53a53
data/Changes.md CHANGED
@@ -1,3 +1,11 @@
1
+ 2.1.0
2
+ ------
3
+
4
+ - Refactoring to better support connection pool subclasses [drbrain,
5
+ #55]
6
+ - `with` should return value of the last expression [#59]
7
+
8
+
1
9
  2.0.0
2
10
  -----
3
11
 
data/README.md CHANGED
@@ -68,6 +68,19 @@ end
68
68
  Once you've ported your entire system to use `with`, you can simply remove
69
69
  `Wrapper` and use the simpler and faster `ConnectionPool`.
70
70
 
71
+ You can shut down a ConnectionPool instance once it should no longer be used.
72
+ Further checkout attempts will immediately raise an error but existing checkouts
73
+ will work.
74
+
75
+ ```ruby
76
+ cp = ConnectionPool.new { Redis.new }
77
+ cp.shutdown { |conn| conn.close }
78
+ ```
79
+
80
+ Shutting down a connection pool will block until all connections are checked in and closed.
81
+ Note that shutting down is completely optional; Ruby's garbage collector will reclaim
82
+ unreferenced pools under normal circumstances.
83
+
71
84
 
72
85
  Notes
73
86
  -----
@@ -66,7 +66,7 @@ class ConnectionPool
66
66
 
67
67
  if stack.empty?
68
68
  timeout = options[:timeout] || @timeout
69
- conn = @available.pop(timeout)
69
+ conn = @available.pop(timeout: timeout)
70
70
  else
71
71
  conn = stack.last
72
72
  end
@@ -1,10 +1,37 @@
1
1
  require 'thread'
2
2
  require 'timeout'
3
3
 
4
+ ##
5
+ # Raised when you attempt to retrieve a connection from a pool that has been
6
+ # shut down.
7
+
4
8
  class ConnectionPool::PoolShuttingDownError < RuntimeError; end
5
9
 
10
+ ##
11
+ # The TimedStack manages a pool of homogeneous connections (or any resource
12
+ # you wish to manage). Connections are created lazily up to a given maximum
13
+ # number.
14
+
15
+ # Examples:
16
+ #
17
+ # ts = TimedStack.new(1) { MyConnection.new }
18
+ #
19
+ # # fetch a connection
20
+ # conn = ts.pop
21
+ #
22
+ # # return a connection
23
+ # ts.push conn
24
+ #
25
+ # conn = ts.pop
26
+ # ts.pop timeout: 5
27
+ # #=> raises Timeout::Error after 5 seconds
28
+
6
29
  class ConnectionPool::TimedStack
7
30
 
31
+ ##
32
+ # Creates a new pool with +size+ connections that are created from the given
33
+ # +block+.
34
+
8
35
  def initialize(size = 0, &block)
9
36
  @create_block = block
10
37
  @created = 0
@@ -15,12 +42,16 @@ class ConnectionPool::TimedStack
15
42
  @shutdown_block = nil
16
43
  end
17
44
 
18
- def push(obj)
45
+ ##
46
+ # Returns +obj+ to the stack. +options+ is ignored in TimedStack but may be
47
+ # used by subclasses that extend TimedStack.
48
+
49
+ def push(obj, options = {})
19
50
  @mutex.synchronize do
20
51
  if @shutdown_block
21
52
  @shutdown_block.call(obj)
22
53
  else
23
- @que.push obj
54
+ store_connection obj, options
24
55
  end
25
56
 
26
57
  @resource.broadcast
@@ -28,16 +59,28 @@ class ConnectionPool::TimedStack
28
59
  end
29
60
  alias_method :<<, :push
30
61
 
31
- def pop(timeout=0.5)
62
+ ##
63
+ # Retrieves a connection from the stack. If a connection is available it is
64
+ # immediately returned. If no connection is available within the given
65
+ # timeout a Timeout::Error is raised.
66
+ #
67
+ # +:timeout+ is the only checked entry in +options+ and is preferred over
68
+ # the +timeout+ argument (which will be removed in a future release). Other
69
+ # options may be used by subclasses that extend TimedStack.
70
+
71
+ def pop(timeout = 0.5, options = {})
72
+ options, timeout = timeout, 0.5 if Hash === timeout
73
+ timeout = options.fetch :timeout, timeout
74
+
32
75
  deadline = Time.now + timeout
33
76
  @mutex.synchronize do
34
77
  loop do
35
78
  raise ConnectionPool::PoolShuttingDownError if @shutdown_block
36
- return @que.pop unless @que.empty?
37
- unless @created == @max
38
- @created += 1
39
- return @create_block.call
40
- end
79
+ return fetch_connection(options) if connection_stored?(options)
80
+
81
+ connection = try_create(options)
82
+ return connection if connection
83
+
41
84
  to_wait = deadline - Time.now
42
85
  raise Timeout::Error, "Waited #{timeout} sec" if to_wait <= 0
43
86
  @resource.wait(@mutex, to_wait)
@@ -45,6 +88,10 @@ class ConnectionPool::TimedStack
45
88
  end
46
89
  end
47
90
 
91
+ ##
92
+ # Shuts down the TimedStack which prevents connections from being checked
93
+ # out. The +block+ is called once for each connection on the stack.
94
+
48
95
  def shutdown(&block)
49
96
  raise ArgumentError, "shutdown must receive a block" unless block_given?
50
97
 
@@ -52,18 +99,75 @@ class ConnectionPool::TimedStack
52
99
  @shutdown_block = block
53
100
  @resource.broadcast
54
101
 
55
- @que.size.times do
56
- conn = @que.pop
57
- block.call(conn)
58
- end
102
+ shutdown_connections
59
103
  end
60
104
  end
61
105
 
106
+ ##
107
+ # Returns +true+ if there are no available connections.
108
+
62
109
  def empty?
63
110
  (@created - @que.length) >= @max
64
111
  end
65
112
 
113
+ ##
114
+ # The number of connections available on the stack.
115
+
66
116
  def length
67
117
  @max - @created + @que.length
68
118
  end
119
+
120
+ private
121
+
122
+ ##
123
+ # This is an extension point for TimedStack and is called with a mutex.
124
+ #
125
+ # This method must returns true if a connection is available on the stack.
126
+
127
+ def connection_stored?(options = nil)
128
+ !@que.empty?
129
+ end
130
+
131
+ ##
132
+ # This is an extension point for TimedStack and is called with a mutex.
133
+ #
134
+ # This method must return a connection from the stack.
135
+
136
+ def fetch_connection(options = nil)
137
+ @que.pop
138
+ end
139
+
140
+ ##
141
+ # This is an extension point for TimedStack and is called with a mutex.
142
+ #
143
+ # This method must shut down all connections on the stack.
144
+
145
+ def shutdown_connections(options = nil)
146
+ while connection_stored?(options)
147
+ conn = fetch_connection(options)
148
+ @shutdown_block.call(conn)
149
+ end
150
+ end
151
+
152
+ ##
153
+ # This is an extension point for TimedStack and is called with a mutex.
154
+ #
155
+ # This method must return +obj+ to the stack.
156
+
157
+ def store_connection(obj, options = nil)
158
+ @que.push obj
159
+ end
160
+
161
+ ##
162
+ # This is an extension point for TimedStack and is called with a mutex.
163
+ #
164
+ # This method must create a connection if and only if the total number of
165
+ # connections allowed has not been met.
166
+
167
+ def try_create(options = nil)
168
+ unless @created == @max
169
+ @created += 1
170
+ @create_block.call
171
+ end
172
+ end
69
173
  end
@@ -1,3 +1,3 @@
1
1
  class ConnectionPool
2
- VERSION = "2.0.0"
2
+ VERSION = "2.1.0"
3
3
  end
@@ -147,6 +147,11 @@ class TestConnectionPool < Minitest::Test
147
147
  assert_same conn, t2.value
148
148
  end
149
149
 
150
+ def test_returns_value
151
+ pool = ConnectionPool.new(:timeout => 0, :size => 1) { Object.new }
152
+ assert_equal 1, pool.with {|o| 1 }
153
+ end
154
+
150
155
  def test_checkin_never_checkout
151
156
  pool = ConnectionPool.new(:timeout => 0, :size => 1) { Object.new }
152
157
 
@@ -44,6 +44,14 @@ class TestConnectionPoolTimedStack < Minitest::Test
44
44
  end
45
45
 
46
46
  def test_pop_empty
47
+ e = assert_raises Timeout::Error do
48
+ @stack.pop timeout: 0
49
+ end
50
+
51
+ assert_equal 'Waited 0 sec', e.message
52
+ end
53
+
54
+ def test_pop_empty_2_0_compatibility
47
55
  e = assert_raises Timeout::Error do
48
56
  @stack.pop 0
49
57
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: connection_pool
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Perham
@@ -9,34 +9,34 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-03-14 00:00:00.000000000 Z
12
+ date: 2014-11-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - '>='
18
+ - - ">="
19
19
  - !ruby/object:Gem::Version
20
20
  version: 5.0.0
21
21
  type: :development
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - '>='
25
+ - - ">="
26
26
  - !ruby/object:Gem::Version
27
27
  version: 5.0.0
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: rake
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - '>='
32
+ - - ">="
33
33
  - !ruby/object:Gem::Version
34
34
  version: '0'
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - '>='
39
+ - - ">="
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
42
  description: Generic connection pool for Ruby
@@ -47,8 +47,8 @@ executables: []
47
47
  extensions: []
48
48
  extra_rdoc_files: []
49
49
  files:
50
- - .gitignore
51
- - .travis.yml
50
+ - ".gitignore"
51
+ - ".travis.yml"
52
52
  - Changes.md
53
53
  - Gemfile
54
54
  - LICENSE
@@ -71,17 +71,17 @@ require_paths:
71
71
  - lib
72
72
  required_ruby_version: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - '>='
74
+ - - ">="
75
75
  - !ruby/object:Gem::Version
76
76
  version: '0'
77
77
  required_rubygems_version: !ruby/object:Gem::Requirement
78
78
  requirements:
79
- - - '>='
79
+ - - ">="
80
80
  - !ruby/object:Gem::Version
81
81
  version: '0'
82
82
  requirements: []
83
83
  rubyforge_project:
84
- rubygems_version: 2.0.14
84
+ rubygems_version: 2.4.1
85
85
  signing_key:
86
86
  specification_version: 4
87
87
  summary: Generic connection pool for Ruby