connection_pool 2.5.3 → 2.5.5

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: ee1b7fff2f766c5941f36e0d62c07dd35c04864a19ecd7348d351e6b287bfb16
4
- data.tar.gz: 3ec78e8d6b4763e26a73c5f865d92d0323ece85b85b858b28dc870da7babd640
3
+ metadata.gz: 24c74a1caa5e04827c47155b75e19805bcda4c329e28793309dfa95b5881c4bd
4
+ data.tar.gz: 23aadf2da494be8c3314039700606cd4e01b58d6cae1f45e3b7cdef57a98e7bd
5
5
  SHA512:
6
- metadata.gz: b656b3fed03027af31fa1b7e80574d8690669143f5a6496e0512d251a7aa8bf67393188e7b2a09855877fcb39f150cf9fad6b94d7b2dd974410af5791be24287
7
- data.tar.gz: f5424045239ee1621049adcc37323ff182cc634303f41b46f150fdbf22ceed85d702bd116b74a8808f818e374bb262577852a5edd9233a1900857692f3ebc64c
6
+ metadata.gz: 0f2385ddf4619ebc1bf9e2f202024b330c170ae2e4e7e63480be0f556242140af75eb3d272f6d262b2fc859625f0861c560af6a58c20bea3d69b005e2d248472
7
+ data.tar.gz: 0ac5103c69aa2e8226d2fa872714f9bd611b24ea171e91ce3d7a3c9be62b9887e24916cf4b6b1e5bc8c407349f87c3ea855c4659dbf5f3f137cd45738301d1a6
data/Changes.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # connection_pool Changelog
2
2
 
3
+ 2.5.5
4
+ ------
5
+
6
+ - Support `ConnectionPool::TimedStack#pop(exception: false)` [#207]
7
+ to avoid using exceptions as control flow.
8
+
9
+ 2.5.4
10
+ ------
11
+
12
+ - Add ability to remove a broken connection from the pool [#204, womblep]
13
+
3
14
  2.5.3
4
15
  ------
5
16
 
data/README.md CHANGED
@@ -129,6 +129,27 @@ Thread.new do
129
129
  end
130
130
  ```
131
131
 
132
+ ## Discarding Connections
133
+
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
+
140
+ Takes an optional block that will be executed with the connection.
141
+
142
+ ```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
151
+ ```
152
+
132
153
  ## Current State
133
154
 
134
155
  There are several methods that return information about a pool.
@@ -54,9 +54,12 @@ 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.
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
+ # The +timeout+ argument will be removed in 3.0.
62
+ # Other options may be used by subclasses that extend TimedStack.
60
63
  def pop(timeout = 0.5, options = {})
61
64
  options, timeout = timeout, 0.5 if Hash === timeout
62
65
  timeout = options.fetch :timeout, timeout
@@ -73,7 +76,14 @@ class ConnectionPool::TimedStack
73
76
  return connection if connection
74
77
 
75
78
  to_wait = deadline - current_time
76
- raise ConnectionPool::TimeoutError, "Waited #{timeout} sec, #{length}/#{@max} available" if to_wait <= 0
79
+ if to_wait <= 0
80
+ exc = options.fetch(:exception, ConnectionPool::TimeoutError)
81
+ if exc
82
+ raise ConnectionPool::TimeoutError, "Waited #{timeout} sec, #{length}/#{@max} available"
83
+ else
84
+ return nil
85
+ end
86
+ end
77
87
  @resource.wait(@mutex, to_wait)
78
88
  end
79
89
  end
@@ -134,6 +144,12 @@ class ConnectionPool::TimedStack
134
144
  @que.length
135
145
  end
136
146
 
147
+ ##
148
+ # Reduce the created count
149
+ def decrement_created
150
+ @created -= 1 unless @created == 0
151
+ end
152
+
137
153
  private
138
154
 
139
155
  def current_time
@@ -1,3 +1,3 @@
1
1
  class ConnectionPool
2
- VERSION = "2.5.3"
2
+ VERSION = "2.5.5"
3
3
  end
@@ -99,10 +99,14 @@ class ConnectionPool
99
99
  @available = TimedStack.new(@size, &block)
100
100
  @key = :"pool-#{@available.object_id}"
101
101
  @key_count = :"pool-#{@available.object_id}-count"
102
+ @discard_key = :"pool-#{@available.object_id}-discard"
102
103
  INSTANCES[self] = self if @auto_reload_after_fork && INSTANCES
103
104
  end
104
105
 
105
106
  def with(options = {})
107
+ # We need to manage exception handling manually here in order
108
+ # to work correctly with `Timeout.timeout` and `Thread#raise`.
109
+ # Otherwise an interrupted Thread can leak connections.
106
110
  Thread.handle_interrupt(Exception => :never) do
107
111
  conn = checkout(options)
108
112
  begin
@@ -116,6 +120,40 @@ class ConnectionPool
116
120
  end
117
121
  alias_method :then, :with
118
122
 
123
+ ##
124
+ # Marks the current thread's checked-out connection for discard.
125
+ #
126
+ # When a connection is marked for discard, it will not be returned to the pool
127
+ # when checked in. Instead, the connection will be discarded.
128
+ # This is useful when a connection has become invalid or corrupted
129
+ # and should not be reused.
130
+ #
131
+ # Takes an optional block that will be called with the connection to be discarded.
132
+ # The block should perform any necessary clean-up on the connection.
133
+ #
134
+ # @yield [conn]
135
+ # @yieldparam conn [Object] The connection to be discarded.
136
+ # @yieldreturn [void]
137
+ #
138
+ #
139
+ # Note: This only affects the connection currently checked out by the calling thread.
140
+ # The connection will be discarded when +checkin+ is called.
141
+ #
142
+ # @return [void]
143
+ #
144
+ # @example
145
+ # pool.with do |conn|
146
+ # begin
147
+ # conn.execute("SELECT 1")
148
+ # rescue SomeConnectionError
149
+ # pool.discard_current_connection # Mark connection as bad
150
+ # raise
151
+ # end
152
+ # end
153
+ def discard_current_connection(&block)
154
+ ::Thread.current[@discard_key] = block || proc { |conn| conn }
155
+ end
156
+
119
157
  def checkout(options = {})
120
158
  if ::Thread.current[@key]
121
159
  ::Thread.current[@key_count] += 1
@@ -129,7 +167,18 @@ class ConnectionPool
129
167
  def checkin(force: false)
130
168
  if ::Thread.current[@key]
131
169
  if ::Thread.current[@key_count] == 1 || force
132
- @available.push(::Thread.current[@key])
170
+ if ::Thread.current[@discard_key]
171
+ begin
172
+ @available.decrement_created
173
+ ::Thread.current[@discard_key].call(::Thread.current[@key])
174
+ rescue
175
+ nil
176
+ ensure
177
+ ::Thread.current[@discard_key] = nil
178
+ end
179
+ else
180
+ @available.push(::Thread.current[@key])
181
+ end
133
182
  ::Thread.current[@key] = nil
134
183
  ::Thread.current[@key_count] = nil
135
184
  else
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: connection_pool
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.3
4
+ version: 2.5.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Perham
8
8
  - Damian Janowski
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-04-28 00:00:00.000000000 Z
11
+ date: 1980-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -88,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  requirements: []
91
- rubygems_version: 3.6.2
91
+ rubygems_version: 3.6.9
92
92
  specification_version: 4
93
93
  summary: Generic connection pool for Ruby
94
94
  test_files: []