connection_pool 2.4.0 → 2.5.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 +4 -4
- data/Changes.md +16 -0
- data/README.md +32 -0
- data/connection_pool.gemspec +2 -0
- data/lib/connection_pool/timed_stack.rb +53 -3
- data/lib/connection_pool/version.rb +1 -1
- data/lib/connection_pool.rb +18 -2
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 299b38ab20df15319b32d1a947b291137a5ab0f569d6ebf7153402f525f978c3
|
4
|
+
data.tar.gz: 300e5f15434761a80e388f5ff3a97e23d0a9d87d373e10703417231d6e14cf50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ecdda6209d316a78ce8509514b4cb9676f5adae3cd07c95c75c9564b77a427d3c417e502aa32af65374f6aa63f8a5808b9ddf42d39ff89e9522adaf4c59dcd0
|
7
|
+
data.tar.gz: b1fb7ab8bc2cbcae36371268b03cdb59c4e25855cacd0d9588bfa012aea84801d4d879dff0a311492e89ba2584626029b85c1c3c9cf7efd51f8efb482c983f94
|
data/Changes.md
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
# connection_pool Changelog
|
2
2
|
|
3
|
+
2.5.0
|
4
|
+
------
|
5
|
+
|
6
|
+
- Reap idle connections [#187]
|
7
|
+
```ruby
|
8
|
+
idle_timeout = 60
|
9
|
+
pool = ConnectionPool.new ...
|
10
|
+
pool.reap(idle_timeout, &:close)
|
11
|
+
```
|
12
|
+
- `ConnectionPool#idle` returns the count of connections not in use [#187]
|
13
|
+
|
14
|
+
2.4.1
|
15
|
+
------
|
16
|
+
|
17
|
+
- New `auto_reload_after_fork` config option to disable auto-drop [#177, shayonj]
|
18
|
+
|
3
19
|
2.4.0
|
4
20
|
------
|
5
21
|
|
data/README.md
CHANGED
@@ -101,6 +101,34 @@ cp.with { |conn| conn.get('some-count') }
|
|
101
101
|
|
102
102
|
Like `shutdown`, this will block until all connections are checked in and closed.
|
103
103
|
|
104
|
+
## Reap
|
105
|
+
|
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.
|
107
|
+
|
108
|
+
You can specify how many seconds the connections have to be idle for them to be reaped.
|
109
|
+
Defaults to 60 seconds.
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
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
|
+
|
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).
|
124
|
+
Thread.new do
|
125
|
+
loop do
|
126
|
+
cp.reap(300) { |conn| conn.close }
|
127
|
+
sleep 300
|
128
|
+
end
|
129
|
+
end
|
130
|
+
```
|
131
|
+
|
104
132
|
## Current State
|
105
133
|
|
106
134
|
There are several methods that return information about a pool.
|
@@ -109,11 +137,15 @@ There are several methods that return information about a pool.
|
|
109
137
|
cp = ConnectionPool.new(size: 10) { Redis.new }
|
110
138
|
cp.size # => 10
|
111
139
|
cp.available # => 10
|
140
|
+
cp.idle # => 0
|
112
141
|
|
113
142
|
cp.with do |conn|
|
114
143
|
cp.size # => 10
|
115
144
|
cp.available # => 9
|
145
|
+
cp.idle # => 0
|
116
146
|
end
|
147
|
+
|
148
|
+
cp.idle # => 1
|
117
149
|
```
|
118
150
|
|
119
151
|
Notes
|
data/connection_pool.gemspec
CHANGED
@@ -19,4 +19,6 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.add_development_dependency "minitest", ">= 5.0.0"
|
20
20
|
s.add_development_dependency "rake"
|
21
21
|
s.required_ruby_version = ">= 2.5.0"
|
22
|
+
|
23
|
+
s.metadata = {"changelog_uri" => "https://github.com/mperham/connection_pool/blob/main/Changes.md", "rubygems_mfa_required" => "true"}
|
22
24
|
end
|
@@ -41,6 +41,7 @@ class ConnectionPool::TimedStack
|
|
41
41
|
def push(obj, options = {})
|
42
42
|
@mutex.synchronize do
|
43
43
|
if @shutdown_block
|
44
|
+
@created -= 1 unless @created == 0
|
44
45
|
@shutdown_block.call(obj)
|
45
46
|
else
|
46
47
|
store_connection obj, options
|
@@ -98,6 +99,26 @@ class ConnectionPool::TimedStack
|
|
98
99
|
end
|
99
100
|
end
|
100
101
|
|
102
|
+
##
|
103
|
+
# Reaps connections that were checked in more than +idle_seconds+ ago.
|
104
|
+
def reap(idle_seconds, &block)
|
105
|
+
raise ArgumentError, "reap must receive a block" unless block
|
106
|
+
raise ArgumentError, "idle_seconds must be a number" unless idle_seconds.is_a?(Numeric)
|
107
|
+
raise ConnectionPool::PoolShuttingDownError if @shutdown_block
|
108
|
+
|
109
|
+
idle.times do
|
110
|
+
conn =
|
111
|
+
@mutex.synchronize do
|
112
|
+
raise ConnectionPool::PoolShuttingDownError if @shutdown_block
|
113
|
+
|
114
|
+
reserve_idle_connection(idle_seconds)
|
115
|
+
end
|
116
|
+
break unless conn
|
117
|
+
|
118
|
+
block.call(conn)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
101
122
|
##
|
102
123
|
# Returns +true+ if there are no available connections.
|
103
124
|
|
@@ -112,6 +133,12 @@ class ConnectionPool::TimedStack
|
|
112
133
|
@max - @created + @que.length
|
113
134
|
end
|
114
135
|
|
136
|
+
##
|
137
|
+
# The number of connections created and available on the stack.
|
138
|
+
def idle
|
139
|
+
@que.length
|
140
|
+
end
|
141
|
+
|
115
142
|
private
|
116
143
|
|
117
144
|
def current_time
|
@@ -133,7 +160,7 @@ class ConnectionPool::TimedStack
|
|
133
160
|
# This method must return a connection from the stack.
|
134
161
|
|
135
162
|
def fetch_connection(options = nil)
|
136
|
-
@que.pop
|
163
|
+
@que.pop&.first
|
137
164
|
end
|
138
165
|
|
139
166
|
##
|
@@ -144,9 +171,32 @@ class ConnectionPool::TimedStack
|
|
144
171
|
def shutdown_connections(options = nil)
|
145
172
|
while connection_stored?(options)
|
146
173
|
conn = fetch_connection(options)
|
174
|
+
@created -= 1 unless @created == 0
|
147
175
|
@shutdown_block.call(conn)
|
148
176
|
end
|
149
|
-
|
177
|
+
end
|
178
|
+
|
179
|
+
##
|
180
|
+
# This is an extension point for TimedStack and is called with a mutex.
|
181
|
+
#
|
182
|
+
# This method returns the oldest idle connection if it has been idle for more than idle_seconds.
|
183
|
+
# This requires that the stack is kept in order of checked in time (oldest first).
|
184
|
+
|
185
|
+
def reserve_idle_connection(idle_seconds)
|
186
|
+
return unless idle_connections?(idle_seconds)
|
187
|
+
|
188
|
+
@created -= 1 unless @created == 0
|
189
|
+
|
190
|
+
@que.shift.first
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
# This is an extension point for TimedStack and is called with a mutex.
|
195
|
+
#
|
196
|
+
# Returns true if the first connection in the stack has been idle for more than idle_seconds
|
197
|
+
|
198
|
+
def idle_connections?(idle_seconds)
|
199
|
+
connection_stored? && (current_time - @que.first.last > idle_seconds)
|
150
200
|
end
|
151
201
|
|
152
202
|
##
|
@@ -155,7 +205,7 @@ class ConnectionPool::TimedStack
|
|
155
205
|
# This method must return +obj+ to the stack.
|
156
206
|
|
157
207
|
def store_connection(obj, options = nil)
|
158
|
-
@que.push obj
|
208
|
+
@que.push [obj, current_time]
|
159
209
|
end
|
160
210
|
|
161
211
|
##
|
data/lib/connection_pool.rb
CHANGED
@@ -36,9 +36,10 @@ end
|
|
36
36
|
# Accepts the following options:
|
37
37
|
# - :size - number of connections to pool, defaults to 5
|
38
38
|
# - :timeout - amount of time to wait for a connection if none currently available, defaults to 5 seconds
|
39
|
+
# - :auto_reload_after_fork - automatically drop all connections after fork, defaults to true
|
39
40
|
#
|
40
41
|
class ConnectionPool
|
41
|
-
DEFAULTS = {size: 5, timeout: 5}
|
42
|
+
DEFAULTS = {size: 5, timeout: 5, auto_reload_after_fork: true}
|
42
43
|
|
43
44
|
def self.wrap(options, &block)
|
44
45
|
Wrapper.new(options, &block)
|
@@ -50,11 +51,12 @@ class ConnectionPool
|
|
50
51
|
|
51
52
|
def self.after_fork
|
52
53
|
INSTANCES.values.each do |pool|
|
54
|
+
next unless pool.auto_reload_after_fork
|
55
|
+
|
53
56
|
# We're on after fork, so we know all other threads are dead.
|
54
57
|
# All we need to do is to ensure the main thread doesn't have a
|
55
58
|
# checked out connection
|
56
59
|
pool.checkin(force: true)
|
57
|
-
|
58
60
|
pool.reload do |connection|
|
59
61
|
# Unfortunately we don't know what method to call to close the connection,
|
60
62
|
# so we try the most common one.
|
@@ -92,6 +94,7 @@ class ConnectionPool
|
|
92
94
|
|
93
95
|
@size = Integer(options.fetch(:size))
|
94
96
|
@timeout = options.fetch(:timeout)
|
97
|
+
@auto_reload_after_fork = options.fetch(:auto_reload_after_fork)
|
95
98
|
|
96
99
|
@available = TimedStack.new(@size, &block)
|
97
100
|
@key = :"pool-#{@available.object_id}"
|
@@ -157,13 +160,26 @@ class ConnectionPool
|
|
157
160
|
@available.shutdown(reload: true, &block)
|
158
161
|
end
|
159
162
|
|
163
|
+
## Reaps idle connections that have been idle for over +idle_seconds+.
|
164
|
+
# +idle_seconds+ defaults to 60.
|
165
|
+
def reap(idle_seconds = 60, &block)
|
166
|
+
@available.reap(idle_seconds, &block)
|
167
|
+
end
|
168
|
+
|
160
169
|
# Size of this connection pool
|
161
170
|
attr_reader :size
|
171
|
+
# Automatically drop all connections after fork
|
172
|
+
attr_reader :auto_reload_after_fork
|
162
173
|
|
163
174
|
# Number of pool entries available for checkout at this instant.
|
164
175
|
def available
|
165
176
|
@available.length
|
166
177
|
end
|
178
|
+
|
179
|
+
# Number of pool entries created and idle in the pool.
|
180
|
+
def idle
|
181
|
+
@available.idle
|
182
|
+
end
|
167
183
|
end
|
168
184
|
|
169
185
|
require_relative "connection_pool/timed_stack"
|
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.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Perham
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2025-01-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -72,7 +72,9 @@ files:
|
|
72
72
|
homepage: https://github.com/mperham/connection_pool
|
73
73
|
licenses:
|
74
74
|
- MIT
|
75
|
-
metadata:
|
75
|
+
metadata:
|
76
|
+
changelog_uri: https://github.com/mperham/connection_pool/blob/main/Changes.md
|
77
|
+
rubygems_mfa_required: 'true'
|
76
78
|
post_install_message:
|
77
79
|
rdoc_options: []
|
78
80
|
require_paths:
|
@@ -88,7 +90,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
90
|
- !ruby/object:Gem::Version
|
89
91
|
version: '0'
|
90
92
|
requirements: []
|
91
|
-
rubygems_version: 3.
|
93
|
+
rubygems_version: 3.5.22
|
92
94
|
signing_key:
|
93
95
|
specification_version: 4
|
94
96
|
summary: Generic connection pool for Ruby
|