connection_pool 2.5.4 → 3.0.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
  SHA256:
3
- metadata.gz: e6266fe91b9d1e5285e6e4cd873b0721b18b2c49140fff54b43c9df4d5acd7b1
4
- data.tar.gz: cc95e0178a26a01d9fc3933d8b65468d203c7fb6ed415312f86e392551659db8
3
+ metadata.gz: 60f53f4a83f6a13be41059753aeff5fad1518a45946aa13ab29111f1612c5119
4
+ data.tar.gz: 7edefa375ea7f3852eee9d7644f2aae955119e0cd96049697b7f38bfc54e5c87
5
5
  SHA512:
6
- metadata.gz: 9641879d84cc20db729d1780283fca3a0328e957502369bd22dbbdd0f6601974204acdd8dcd1929e79da505402b73f3fe5eaf2842cfe64d542640ab1e70ad21c
7
- data.tar.gz: 34afe9f57cbaff9b08066725964d776e81e1e0e484eccd54c361cc2a77fe24fbda181c9576754367515799f24f8095504ce2b4c8718f37a90b75c559782be0b4
6
+ metadata.gz: 3007eb8a2cf804da6b3850162098b221a5a613244ba20506fed109e3a47e0046099ba56c48ccd8a260a3afc13362552ddd9040a512ca1b512cfae1f18937c32b
7
+ data.tar.gz: 4cdb681918cefe624b3c00e6d7580330f120c6c53cc414e694d6568eee7f24ed109d69ec150c7a7ccbf5dec17ffb1cfdc8422e78bcb9d1b436240bb81c5464a6
data/Changes.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # connection_pool Changelog
2
2
 
3
+ 3.0.0
4
+ ------
5
+
6
+ - **BREAKING CHANGES** `ConnectionPool` and `ConnectionPool::TimedStack` now
7
+ use keyword arguments rather than positional arguments everywhere. Expected impact is minimal as most people use the `with` API, which is unchanged.
8
+ ```ruby
9
+ pool = ConnectionPool.new(size: 5, timeout: 5)
10
+ pool.checkout(1) # 2.x
11
+ pool.reap(30) # 2.x
12
+ pool.checkout(timeout: 1) # 3.x
13
+ pool.reap(idle_seconds: 30) # 3.x
14
+ ```
15
+ - Dropped support for Ruby <3.2.0
16
+
17
+ 2.5.5
18
+ ------
19
+
20
+ - Support `ConnectionPool::TimedStack#pop(exception: false)` [#207]
21
+ to avoid using exceptions as control flow.
22
+
3
23
  2.5.4
4
24
  ------
5
25
 
data/README.md CHANGED
@@ -38,7 +38,7 @@ connection pool and a raw client.
38
38
  $redis.then { |r| r.set 'foo' 'bar' }
39
39
  ```
40
40
 
41
- Optionally, you can specify a timeout override using the with-block semantics:
41
+ Optionally, you can specify a timeout override:
42
42
 
43
43
  ``` ruby
44
44
  $memcached.with(timeout: 2.0) do |conn|
@@ -46,11 +46,9 @@ $memcached.with(timeout: 2.0) do |conn|
46
46
  end
47
47
  ```
48
48
 
49
- This will only modify the resource-get timeout for this particular
50
- invocation.
49
+ This will only modify the timeout for this particular invocation.
51
50
  This is useful if you want to fail-fast on certain non-critical
52
51
  sections when a resource is not available, or conversely if you are comfortable blocking longer on a particular resource.
53
- This is not implemented in the `ConnectionPool::Wrapper` class.
54
52
 
55
53
  ## Migrating to a Connection Pool
56
54
 
@@ -72,7 +70,7 @@ $redis.with do |conn|
72
70
  end
73
71
  ```
74
72
 
75
- Once you've ported your entire system to use `with`, you can simply remove `Wrapper` and use the simpler and faster `ConnectionPool`.
73
+ Once you've ported your entire system to use `with`, you can remove `::Wrapper` and use `ConnectionPool` directly.
76
74
 
77
75
 
78
76
  ## Shutdown
@@ -90,64 +88,52 @@ Shutting down a connection pool will block until all connections are checked in
90
88
 
91
89
  ## Reload
92
90
 
93
- You can reload a ConnectionPool instance in the case it is desired to close all connections to the pool and, unlike `shutdown`, afterwards recreate connections so the pool may continue to be used.
94
- Reloading may be useful after forking the process.
91
+ You can reload a ConnectionPool instance if it is necessary to close all existing connections and continue to use the pool.
92
+ ConnectionPool will automatically reload if the process is forked.
93
+ Use `auto_reload_after_fork: false` if you don't want this behavior.
95
94
 
96
95
  ```ruby
97
- cp = ConnectionPool.new { Redis.new }
98
- cp.reload { |conn| conn.quit }
96
+ cp = ConnectionPool.new(auto_reload_after_fork: false) { Redis.new }
97
+ cp.reload { |conn| conn.quit } # reload manually
99
98
  cp.with { |conn| conn.get('some-count') }
100
99
  ```
101
100
 
102
- Like `shutdown`, this will block until all connections are checked in and closed.
101
+ Like `shutdown`, `reload` will block until all connections are checked in and closed.
103
102
 
104
103
  ## Reap
105
104
 
106
- You can reap idle connections in the ConnectionPool instance to close connections that were created but have not been used for a certain amount of time. This can be useful to run periodically in a separate thread especially if keeping the connection open is resource intensive.
105
+ You can call `reap` periodically on the ConnectionPool instance to close connections that were created but have not been used for a certain amount of time. This can be useful in environments where connections are expensive.
107
106
 
108
- You can specify how many seconds the connections have to be idle for them to be reaped.
109
- Defaults to 60 seconds.
107
+ You can specify how many seconds the connections have to be idle for them to be reaped, defaulting to 60 seconds.
110
108
 
111
109
  ```ruby
112
110
  cp = ConnectionPool.new { Redis.new }
113
- cp.reap(300) { |conn| conn.close } # Reaps connections that have been idle for 300 seconds (5 minutes).
114
- ```
115
-
116
- ### Reaper Thread
117
111
 
118
- You can start your own reaper thread to reap idle connections in the ConnectionPool instance on a regular interval.
119
-
120
- ```ruby
121
- cp = ConnectionPool.new { Redis.new }
122
-
123
- # Start a reaper thread to reap connections that have been idle for 300 seconds (5 minutes).
112
+ # Start a reaper thread to reap connections that have been
113
+ # idle more than 300 seconds (5 minutes)
124
114
  Thread.new do
125
115
  loop do
126
- cp.reap(300) { |conn| conn.close }
127
- sleep 300
116
+ cp.reap(idle_seconds: 300, &:close)
117
+ sleep 30
128
118
  end
129
119
  end
130
120
  ```
131
121
 
132
122
  ## Discarding Connections
133
123
 
134
- You can discard connections in the ConnectionPool instance to remove connections that are broken and can't be restarted.
135
-
136
- NOTE: the connection is not closed. It will just be removed from the pool so it won't be selected again.
137
-
138
- It can only be done inside the block passed to `with` or `with_timeout`.
139
-
124
+ You can discard connections in the ConnectionPool instance to remove connections that are broken and can't be repaired.
125
+ It can only be done inside the block passed to `with`.
140
126
  Takes an optional block that will be executed with the connection.
141
127
 
142
128
  ```ruby
143
- pool.with do |conn|
144
- begin
145
- conn.execute("SELECT 1")
146
- rescue SomeConnectionError
147
- pool.discard_current_connection # remove the connection from the pool
148
- raise
149
- end
150
- end
129
+ pool.with do |conn|
130
+ begin
131
+ conn.execute("SELECT 1")
132
+ rescue SomeConnectionError
133
+ pool.discard_current_connection(&:close) # remove the connection from the pool
134
+ raise
135
+ end
136
+ end
151
137
  ```
152
138
 
153
139
  ## Current State
@@ -169,20 +155,28 @@ end
169
155
  cp.idle # => 1
170
156
  ```
171
157
 
172
- Notes
173
- -----
158
+ ## Upgrading from ConnectionPool 2
159
+
160
+ * Support for Ruby <3.2 has been removed.
161
+ * ConnectionPool's APIs now consistently use keyword arguments everywhere.
162
+ Positional arguments must be converted to keywords:
163
+ ```ruby
164
+ pool = ConnectionPool.new(size: 5, timeout: 5)
165
+ pool.checkout(1) # 2.x
166
+ pool.reap(30) # 2.x
167
+ pool.checkout(timeout: 1) # 3.x
168
+ pool.reap(idle_seconds: 30) # 3.x
169
+ ```
170
+
171
+ ## Notes
174
172
 
175
173
  - Connections are lazily created as needed.
176
- - There is no provision for repairing or checking the health of a connection;
177
- connections should be self-repairing. This is true of the Dalli and Redis
178
- clients.
179
- - **WARNING**: Don't ever use `Timeout.timeout` in your Ruby code or you will see
174
+ - **WARNING**: Avoid `Timeout.timeout` in your Ruby code or you can see
180
175
  occasional silent corruption and mysterious errors. The Timeout API is unsafe
181
- and cannot be used correctly, ever. Use proper socket timeout options as
182
- exposed by Net::HTTP, Redis, Dalli, etc.
176
+ and dangerous to use. Use proper socket timeout options as exposed by
177
+ Net::HTTP, Redis, Dalli, etc.
183
178
 
184
179
 
185
- Author
186
- ------
180
+ ## Author
187
181
 
188
- Mike Perham, [@getajobmike](https://twitter.com/getajobmike), <https://www.mikeperham.com>
182
+ Mike Perham, [@getajobmike](https://ruby.social/@getajobmike), <https://www.mikeperham.com>
@@ -15,10 +15,18 @@ Gem::Specification.new do |s|
15
15
  s.executables = []
16
16
  s.require_paths = ["lib"]
17
17
  s.license = "MIT"
18
+
19
+ s.required_ruby_version = ">= 3.2.0"
18
20
  s.add_development_dependency "bundler"
19
- s.add_development_dependency "minitest", ">= 5.0.0"
21
+ s.add_development_dependency "maxitest"
20
22
  s.add_development_dependency "rake"
21
- s.required_ruby_version = ">= 2.5.0"
22
23
 
23
- s.metadata = {"changelog_uri" => "https://github.com/mperham/connection_pool/blob/main/Changes.md", "rubygems_mfa_required" => "true"}
24
+ s.metadata = {
25
+ "bug_tracker_uri" => "https://github.com/mperham/connection_pool/issues",
26
+ "documentation_uri" => "https://github.com/mperham/connection_pool/wiki",
27
+ "changelog_uri" => "https://github.com/mperham/connection_pool/blob/main/Changes.md",
28
+ "source_code_uri" => "https://github.com/mperham/connection_pool",
29
+ "homepage_uri" => "https://github.com/mperham/connection_pool",
30
+ "rubygems_mfa_required" => "true"
31
+ }
24
32
  end
@@ -5,7 +5,7 @@
5
5
  #
6
6
  # Examples:
7
7
  #
8
- # ts = TimedStack.new(1) { MyConnection.new }
8
+ # ts = TimedStack.new(size: 1) { MyConnection.new }
9
9
  #
10
10
  # # fetch a connection
11
11
  # conn = ts.pop
@@ -22,7 +22,7 @@ class ConnectionPool::TimedStack
22
22
  ##
23
23
  # Creates a new pool with +size+ connections that are created from the given
24
24
  # +block+.
25
- def initialize(size = 0, &block)
25
+ def initialize(size: 0, &block)
26
26
  @create_block = block
27
27
  @created = 0
28
28
  @que = []
@@ -33,15 +33,15 @@ class ConnectionPool::TimedStack
33
33
  end
34
34
 
35
35
  ##
36
- # Returns +obj+ to the stack. +options+ is ignored in TimedStack but may be
36
+ # Returns +obj+ to the stack. Additional kwargs are ignored in TimedStack but may be
37
37
  # used by subclasses that extend TimedStack.
38
- def push(obj, options = {})
38
+ def push(obj, **)
39
39
  @mutex.synchronize do
40
40
  if @shutdown_block
41
41
  @created -= 1 unless @created == 0
42
42
  @shutdown_block.call(obj)
43
43
  else
44
- store_connection obj, options
44
+ store_connection obj, **
45
45
  end
46
46
 
47
47
  @resource.broadcast
@@ -54,26 +54,31 @@ class ConnectionPool::TimedStack
54
54
  # immediately returned. If no connection is available within the given
55
55
  # timeout a ConnectionPool::TimeoutError is raised.
56
56
  #
57
- # +:timeout+ is the only checked entry in +options+ and is preferred over
58
- # the +timeout+ argument (which will be removed in a future release). Other
59
- # options may be used by subclasses that extend TimedStack.
60
- def pop(timeout = 0.5, options = {})
61
- options, timeout = timeout, 0.5 if Hash === timeout
62
- timeout = options.fetch :timeout, timeout
63
-
57
+ # @option options [Float] :timeout (0.5) Wait this many seconds for an available entry
58
+ # @option options [Class] :exception (ConnectionPool::TimeoutError) Exception class to raise
59
+ # if an entry was not available within the timeout period. Use `exception: false` to return nil.
60
+ #
61
+ # Other options may be used by subclasses that extend TimedStack.
62
+ def pop(timeout: 0.5, exception: ConnectionPool::TimeoutError, **)
64
63
  deadline = current_time + timeout
65
64
  @mutex.synchronize do
66
65
  loop do
67
66
  raise ConnectionPool::PoolShuttingDownError if @shutdown_block
68
- if (conn = try_fetch_connection(options))
67
+ if (conn = try_fetch_connection(**))
69
68
  return conn
70
69
  end
71
70
 
72
- connection = try_create(options)
71
+ connection = try_create(**)
73
72
  return connection if connection
74
73
 
75
74
  to_wait = deadline - current_time
76
- raise ConnectionPool::TimeoutError, "Waited #{timeout} sec, #{length}/#{@max} available" if to_wait <= 0
75
+ if to_wait <= 0
76
+ if exception
77
+ raise exception, "Waited #{timeout} sec, #{length}/#{@max} available"
78
+ else
79
+ return nil
80
+ end
81
+ end
77
82
  @resource.wait(@mutex, to_wait)
78
83
  end
79
84
  end
@@ -98,21 +103,20 @@ class ConnectionPool::TimedStack
98
103
 
99
104
  ##
100
105
  # Reaps connections that were checked in more than +idle_seconds+ ago.
101
- def reap(idle_seconds, &block)
102
- raise ArgumentError, "reap must receive a block" unless block
106
+ def reap(idle_seconds:)
107
+ raise ArgumentError, "reap must receive a block" unless block_given?
103
108
  raise ArgumentError, "idle_seconds must be a number" unless idle_seconds.is_a?(Numeric)
104
109
  raise ConnectionPool::PoolShuttingDownError if @shutdown_block
105
110
 
106
- idle.times do
107
- conn =
108
- @mutex.synchronize do
109
- raise ConnectionPool::PoolShuttingDownError if @shutdown_block
110
-
111
- reserve_idle_connection(idle_seconds)
112
- end
111
+ count = idle
112
+ count.times do
113
+ conn = @mutex.synchronize do
114
+ raise ConnectionPool::PoolShuttingDownError if @shutdown_block
115
+ reserve_idle_connection(idle_seconds)
116
+ end
113
117
  break unless conn
114
118
 
115
- block.call(conn)
119
+ yield conn
116
120
  end
117
121
  end
118
122
 
@@ -152,15 +156,15 @@ class ConnectionPool::TimedStack
152
156
  # This method must returns a connection from the stack if one exists. Allows
153
157
  # subclasses with expensive match/search algorithms to avoid double-handling
154
158
  # their stack.
155
- def try_fetch_connection(options = nil)
156
- connection_stored?(options) && fetch_connection(options)
159
+ def try_fetch_connection(**)
160
+ connection_stored?(**) && fetch_connection(**)
157
161
  end
158
162
 
159
163
  ##
160
164
  # This is an extension point for TimedStack and is called with a mutex.
161
165
  #
162
166
  # This method must returns true if a connection is available on the stack.
163
- def connection_stored?(options = nil)
167
+ def connection_stored?(**)
164
168
  !@que.empty?
165
169
  end
166
170
 
@@ -168,7 +172,7 @@ class ConnectionPool::TimedStack
168
172
  # This is an extension point for TimedStack and is called with a mutex.
169
173
  #
170
174
  # This method must return a connection from the stack.
171
- def fetch_connection(options = nil)
175
+ def fetch_connection(**)
172
176
  @que.pop&.first
173
177
  end
174
178
 
@@ -176,8 +180,8 @@ class ConnectionPool::TimedStack
176
180
  # This is an extension point for TimedStack and is called with a mutex.
177
181
  #
178
182
  # This method must shut down all connections on the stack.
179
- def shutdown_connections(options = nil)
180
- while (conn = try_fetch_connection(options))
183
+ def shutdown_connections(**)
184
+ while (conn = try_fetch_connection(**))
181
185
  @created -= 1 unless @created == 0
182
186
  @shutdown_block.call(conn)
183
187
  end
@@ -193,6 +197,8 @@ class ConnectionPool::TimedStack
193
197
 
194
198
  @created -= 1 unless @created == 0
195
199
 
200
+ # Most active elements are at the tail of the array.
201
+ # Most idle will be at the head so `shift` rather than `pop`.
196
202
  @que.shift.first
197
203
  end
198
204
 
@@ -201,14 +207,17 @@ class ConnectionPool::TimedStack
201
207
  #
202
208
  # Returns true if the first connection in the stack has been idle for more than idle_seconds
203
209
  def idle_connections?(idle_seconds)
204
- connection_stored? && (current_time - @que.first.last > idle_seconds)
210
+ return unless connection_stored?
211
+ # Most idle will be at the head so `first`
212
+ age = (current_time - @que.first.last)
213
+ age > idle_seconds
205
214
  end
206
215
 
207
216
  ##
208
217
  # This is an extension point for TimedStack and is called with a mutex.
209
218
  #
210
219
  # This method must return +obj+ to the stack.
211
- def store_connection(obj, options = nil)
220
+ def store_connection(obj, **)
212
221
  @que.push [obj, current_time]
213
222
  end
214
223
 
@@ -217,7 +226,7 @@ class ConnectionPool::TimedStack
217
226
  #
218
227
  # This method must create a connection if and only if the total number of
219
228
  # connections allowed has not been met.
220
- def try_create(options = nil)
229
+ def try_create(**)
221
230
  unless @created == @max
222
231
  object = @create_block.call
223
232
  @created += 1
@@ -1,3 +1,3 @@
1
1
  class ConnectionPool
2
- VERSION = "2.5.4"
2
+ VERSION = "3.0.0"
3
3
  end
@@ -2,20 +2,20 @@ class ConnectionPool
2
2
  class Wrapper < ::BasicObject
3
3
  METHODS = [:with, :pool_shutdown, :wrapped_pool]
4
4
 
5
- def initialize(options = {}, &block)
6
- @pool = options.fetch(:pool) { ::ConnectionPool.new(options, &block) }
5
+ def initialize(**options, &)
6
+ @pool = options.fetch(:pool) { ::ConnectionPool.new(**options, &) }
7
7
  end
8
8
 
9
9
  def wrapped_pool
10
10
  @pool
11
11
  end
12
12
 
13
- def with(&block)
14
- @pool.with(&block)
13
+ def with(**, &)
14
+ @pool.with(**, &)
15
15
  end
16
16
 
17
- def pool_shutdown(&block)
18
- @pool.shutdown(&block)
17
+ def pool_shutdown(&)
18
+ @pool.shutdown(&)
19
19
  end
20
20
 
21
21
  def pool_size
@@ -26,31 +26,18 @@ class ConnectionPool
26
26
  @pool.available
27
27
  end
28
28
 
29
- def respond_to?(id, *args)
30
- METHODS.include?(id) || with { |c| c.respond_to?(id, *args) }
29
+ def respond_to?(id, *, **)
30
+ METHODS.include?(id) || with { |c| c.respond_to?(id, *, **) }
31
31
  end
32
32
 
33
- # rubocop:disable Style/MissingRespondToMissing
34
- if ::RUBY_VERSION >= "3.0.0"
35
- def method_missing(name, *args, **kwargs, &block)
36
- with do |connection|
37
- connection.send(name, *args, **kwargs, &block)
38
- end
39
- end
40
- elsif ::RUBY_VERSION >= "2.7.0"
41
- ruby2_keywords def method_missing(name, *args, &block)
42
- with do |connection|
43
- connection.send(name, *args, &block)
44
- end
45
- end
46
- else
47
- def method_missing(name, *args, &block)
48
- with do |connection|
49
- connection.send(name, *args, &block)
50
- end
33
+ def respond_to_missing?(id, *, **)
34
+ with { |c| c.respond_to?(id, *, **) }
35
+ end
36
+
37
+ def method_missing(name, *, **, &)
38
+ with do |connection|
39
+ connection.send(name, *, **, &)
51
40
  end
52
41
  end
53
- # rubocop:enable Style/MethodMissingSuper
54
- # rubocop:enable Style/MissingRespondToMissing
55
42
  end
56
43
  end
@@ -39,73 +39,30 @@ end
39
39
  # - :auto_reload_after_fork - automatically drop all connections after fork, defaults to true
40
40
  #
41
41
  class ConnectionPool
42
- DEFAULTS = {size: 5, timeout: 5, auto_reload_after_fork: true}.freeze
43
-
44
- def self.wrap(options, &block)
45
- Wrapper.new(options, &block)
42
+ def self.wrap(**, &)
43
+ Wrapper.new(**, &)
46
44
  end
47
45
 
48
- if Process.respond_to?(:fork)
49
- INSTANCES = ObjectSpace::WeakMap.new
50
- private_constant :INSTANCES
51
-
52
- def self.after_fork
53
- INSTANCES.values.each do |pool|
54
- next unless pool.auto_reload_after_fork
55
-
56
- # We're on after fork, so we know all other threads are dead.
57
- # All we need to do is to ensure the main thread doesn't have a
58
- # checked out connection
59
- pool.checkin(force: true)
60
- pool.reload do |connection|
61
- # Unfortunately we don't know what method to call to close the connection,
62
- # so we try the most common one.
63
- connection.close if connection.respond_to?(:close)
64
- end
65
- end
66
- nil
67
- end
68
-
69
- if ::Process.respond_to?(:_fork) # MRI 3.1+
70
- module ForkTracker
71
- def _fork
72
- pid = super
73
- if pid == 0
74
- ConnectionPool.after_fork
75
- end
76
- pid
77
- end
78
- end
79
- Process.singleton_class.prepend(ForkTracker)
80
- end
81
- else
82
- INSTANCES = nil
83
- private_constant :INSTANCES
84
-
85
- def self.after_fork
86
- # noop
87
- end
88
- end
89
-
90
- def initialize(options = {}, &block)
91
- raise ArgumentError, "Connection pool requires a block" unless block
92
-
93
- options = DEFAULTS.merge(options)
46
+ attr_reader :size
94
47
 
95
- @size = Integer(options.fetch(:size))
96
- @timeout = options.fetch(:timeout)
97
- @auto_reload_after_fork = options.fetch(:auto_reload_after_fork)
48
+ def initialize(timeout: 5, size: 5, auto_reload_after_fork: true, &)
49
+ raise ArgumentError, "Connection pool requires a block" unless block_given?
98
50
 
99
- @available = TimedStack.new(@size, &block)
51
+ @size = Integer(size)
52
+ @timeout = Float(timeout)
53
+ @available = TimedStack.new(size: @size, &)
100
54
  @key = :"pool-#{@available.object_id}"
101
55
  @key_count = :"pool-#{@available.object_id}-count"
102
56
  @discard_key = :"pool-#{@available.object_id}-discard"
103
- INSTANCES[self] = self if @auto_reload_after_fork && INSTANCES
57
+ INSTANCES[self] = self if auto_reload_after_fork && INSTANCES
104
58
  end
105
59
 
106
- def with(options = {})
60
+ def with(**)
61
+ # We need to manage exception handling manually here in order
62
+ # to work correctly with `Timeout.timeout` and `Thread#raise`.
63
+ # Otherwise an interrupted Thread can leak connections.
107
64
  Thread.handle_interrupt(Exception => :never) do
108
- conn = checkout(options)
65
+ conn = checkout(**)
109
66
  begin
110
67
  Thread.handle_interrupt(Exception => :immediate) do
111
68
  yield conn
@@ -151,13 +108,15 @@ class ConnectionPool
151
108
  ::Thread.current[@discard_key] = block || proc { |conn| conn }
152
109
  end
153
110
 
154
- def checkout(options = {})
111
+ def checkout(timeout: @timeout, **)
155
112
  if ::Thread.current[@key]
156
113
  ::Thread.current[@key_count] += 1
157
114
  ::Thread.current[@key]
158
115
  else
116
+ conn = @available.pop(timeout:, **)
117
+ ::Thread.current[@key] = conn
159
118
  ::Thread.current[@key_count] = 1
160
- ::Thread.current[@key] = @available.pop(options[:timeout] || @timeout, options)
119
+ conn
161
120
  end
162
121
  end
163
122
 
@@ -192,29 +151,24 @@ class ConnectionPool
192
151
  # Shuts down the ConnectionPool by passing each connection to +block+ and
193
152
  # then removing it from the pool. Attempting to checkout a connection after
194
153
  # shutdown will raise +ConnectionPool::PoolShuttingDownError+.
195
- def shutdown(&block)
196
- @available.shutdown(&block)
154
+ def shutdown(&)
155
+ @available.shutdown(&)
197
156
  end
198
157
 
199
158
  ##
200
159
  # Reloads the ConnectionPool by passing each connection to +block+ and then
201
160
  # removing it the pool. Subsequent checkouts will create new connections as
202
161
  # needed.
203
- def reload(&block)
204
- @available.shutdown(reload: true, &block)
162
+ def reload(&)
163
+ @available.shutdown(reload: true, &)
205
164
  end
206
165
 
207
166
  ## Reaps idle connections that have been idle for over +idle_seconds+.
208
167
  # +idle_seconds+ defaults to 60.
209
- def reap(idle_seconds = 60, &block)
210
- @available.reap(idle_seconds, &block)
168
+ def reap(idle_seconds: 60, &)
169
+ @available.reap(idle_seconds:, &)
211
170
  end
212
171
 
213
- # Size of this connection pool
214
- attr_reader :size
215
- # Automatically drop all connections after fork
216
- attr_reader :auto_reload_after_fork
217
-
218
172
  # Number of pool entries available for checkout at this instant.
219
173
  def available
220
174
  @available.length
@@ -228,3 +182,4 @@ end
228
182
 
229
183
  require_relative "connection_pool/timed_stack"
230
184
  require_relative "connection_pool/wrapper"
185
+ require_relative "connection_pool/fork"
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.5.4
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Perham
@@ -25,19 +25,19 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: minitest
28
+ name: maxitest
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 5.0.0
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 5.0.0
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -72,7 +72,11 @@ homepage: https://github.com/mperham/connection_pool
72
72
  licenses:
73
73
  - MIT
74
74
  metadata:
75
+ bug_tracker_uri: https://github.com/mperham/connection_pool/issues
76
+ documentation_uri: https://github.com/mperham/connection_pool/wiki
75
77
  changelog_uri: https://github.com/mperham/connection_pool/blob/main/Changes.md
78
+ source_code_uri: https://github.com/mperham/connection_pool
79
+ homepage_uri: https://github.com/mperham/connection_pool
76
80
  rubygems_mfa_required: 'true'
77
81
  rdoc_options: []
78
82
  require_paths:
@@ -81,7 +85,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
81
85
  requirements:
82
86
  - - ">="
83
87
  - !ruby/object:Gem::Version
84
- version: 2.5.0
88
+ version: 3.2.0
85
89
  required_rubygems_version: !ruby/object:Gem::Requirement
86
90
  requirements:
87
91
  - - ">="