connection_pool 2.0.0 → 2.1.0

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 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