1
0
Fork 0
mirror of https://github.com/mperham/connection_pool synced 2023-03-27 23:22:21 -04:00

Allow restarting pool (#140)

* Allow restarting pool

The implementation of shutdown from
https://github.com/mperham/connection_pool/issues/27 does not actually
provide for a way for the pool to re-create connections, only render the
pool unusable. This implements such a behavior. A new method is added so
as to not change the existing behavior of `shutdown`.
This commit is contained in:
Andrew Marshall 2021-01-28 13:29:18 -05:00 committed by GitHub
parent 52b882f2c6
commit 3eaba661b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 48 additions and 3 deletions

View file

@ -3,6 +3,7 @@
HEAD HEAD
------ ------
- Add `reload` to close all connections, recreating them afterwards [Andrew Marshall, #140]
- Add `then` as a way to use a pool or a bare connection with the - Add `then` as a way to use a pool or a bare connection with the
same code path [#138] same code path [#138]

View file

@ -95,6 +95,22 @@ Shutting down a connection pool will block until all connections are checked in
**Note that shutting down is completely optional**; Ruby's garbage collector will reclaim **Note that shutting down is completely optional**; Ruby's garbage collector will reclaim
unreferenced pools under normal circumstances. unreferenced pools under normal circumstances.
## Reload
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. Reloading may be useful after forking the
process.
```ruby
cp = ConnectionPool.new { Redis.new }
cp.reload { |conn| conn.quit }
cp.with { |conn| conn.get('some-count') }
```
Like `shutdown`, this will block until all connections are checked in and
closed.
## Current State ## Current State
There are several methods that return information about a pool. There are several methods that return information about a pool.

View file

@ -95,10 +95,24 @@ class ConnectionPool
nil nil
end end
##
# Shuts down the ConnectionPool by passing each connection to +block+ and
# then removing it from the pool. Attempting to checkout a connection after
# shutdown will raise +ConnectionPool::PoolShuttingDownError+.
def shutdown(&block) def shutdown(&block)
@available.shutdown(&block) @available.shutdown(&block)
end end
##
# Reloads the ConnectionPool by passing each connection to +block+ and then
# removing it the pool. Subsequent checkouts will create new connections as
# needed.
def reload(&block)
@available.shutdown(reload: true, &block)
end
# Size of this connection pool # Size of this connection pool
attr_reader :size attr_reader :size

View file

@ -81,10 +81,12 @@ class ConnectionPool::TimedStack
end end
## ##
# Shuts down the TimedStack which prevents connections from being checked # Shuts down the TimedStack by passing each connection to +block+ and then
# out. The +block+ is called once for each connection on the stack. # removing it from the pool. Attempting to checkout a connection after
# shutdown will raise +ConnectionPool::PoolShuttingDownError+ unless
# +:reload+ is +true+.
def shutdown(&block) def shutdown(reload: false, &block)
raise ArgumentError, "shutdown must receive a block" unless block_given? raise ArgumentError, "shutdown must receive a block" unless block_given?
@mutex.synchronize do @mutex.synchronize do
@ -92,6 +94,7 @@ class ConnectionPool::TimedStack
@resource.broadcast @resource.broadcast
shutdown_connections shutdown_connections
@shutdown_block = nil if reload
end end
end end
@ -143,6 +146,7 @@ class ConnectionPool::TimedStack
conn = fetch_connection(options) conn = fetch_connection(options)
@shutdown_block.call(conn) @shutdown_block.call(conn)
end end
@created = 0
end end
## ##

View file

@ -102,6 +102,16 @@ class TestConnectionPoolTimedStack < Minitest::Test
end end
end end
def test_pop_shutdown_reload
stack = ConnectionPool::TimedStack.new(1) { Object.new }
object = stack.pop
stack.push(object)
stack.shutdown(reload: true) {}
refute_equal object, stack.pop
end
def test_push def test_push
stack = ConnectionPool::TimedStack.new(1) { Object.new } stack = ConnectionPool::TimedStack.new(1) { Object.new }