sequel 5.101.0 → 5.102.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/lib/sequel/connection_pool/sharded_timed_queue.rb +23 -4
- data/lib/sequel/connection_pool/timed_queue.rb +16 -3
- data/lib/sequel/connection_pool.rb +6 -0
- data/lib/sequel/extensions/connection_checkout_event_callback.rb +151 -0
- data/lib/sequel/extensions/connection_expiration.rb +1 -1
- data/lib/sequel/extensions/connection_validator.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 92eed5c337b361dfde5b948323fb6a0a22ad89ecb2473c284d9e5b70a5eed8e2
|
|
4
|
+
data.tar.gz: dd07fefb9f3d2821479be092a12b87c6e7b92f5d8d8c314ff656741d31e75531
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ea53c48308a031896491a59e57ca3902a9a3478b8d09d12de6548a927991419054fa8698463c18c18cef9801a9c4629dc299b27df03245272bb2296f79ccdc1c
|
|
7
|
+
data.tar.gz: adfd92660e225f0d67948dfdc4aa57c2c61c1118265908f8b6a26fe23179573aff4195aec759575abea984e46fa5d1b62701b75caa8ce7e78838f6434e208527
|
|
@@ -71,7 +71,7 @@ class Sequel::ShardedTimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
71
71
|
while true
|
|
72
72
|
conn = nil
|
|
73
73
|
begin
|
|
74
|
-
break unless (conn = queue
|
|
74
|
+
break unless (conn = available(queue, server)) && !conns[conn]
|
|
75
75
|
conns[conn] = true
|
|
76
76
|
yield conn
|
|
77
77
|
ensure
|
|
@@ -95,7 +95,7 @@ class Sequel::ShardedTimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
95
95
|
def disconnect(opts=OPTS)
|
|
96
96
|
(opts[:server] ? Array(opts[:server]) : sync{@servers.keys}).each do |server|
|
|
97
97
|
raise Sequel::Error, "invalid server" unless queue = sync{@queues[server]}
|
|
98
|
-
while conn = queue
|
|
98
|
+
while conn = available(queue, server)
|
|
99
99
|
disconnect_pool_connection(conn, server)
|
|
100
100
|
end
|
|
101
101
|
fill_queue(server)
|
|
@@ -167,7 +167,7 @@ class Sequel::ShardedTimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
167
167
|
|
|
168
168
|
queue = @queues[server]
|
|
169
169
|
|
|
170
|
-
while conn = queue
|
|
170
|
+
while conn = available(queue, server)
|
|
171
171
|
@sizes[server] -= 1
|
|
172
172
|
conns << conn
|
|
173
173
|
end
|
|
@@ -225,6 +225,12 @@ class Sequel::ShardedTimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
225
225
|
conns.each{|conn| disconnect_connection(conn)}
|
|
226
226
|
end
|
|
227
227
|
|
|
228
|
+
# Only for use by extension that need to disconnect a connection inside acquire.
|
|
229
|
+
# Takes the connection and any arguments accepted by acquire.
|
|
230
|
+
def disconnect_acquired_connection(conn, _, server)
|
|
231
|
+
disconnect_pool_connection(conn, server)
|
|
232
|
+
end
|
|
233
|
+
|
|
228
234
|
# Decrement the current size of the pool for the server when disconnecting connections.
|
|
229
235
|
#
|
|
230
236
|
# Calling code should not have the mutex when calling this.
|
|
@@ -311,7 +317,7 @@ class Sequel::ShardedTimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
311
317
|
# Calling code should not have the mutex when calling this.
|
|
312
318
|
def acquire(thread, server)
|
|
313
319
|
queue = sync{@queues[server]}
|
|
314
|
-
if conn = queue
|
|
320
|
+
if conn = available(queue, server) || try_make_new(server) || wait_until_available(queue, server)
|
|
315
321
|
sync{@allocated[server][thread] = conn}
|
|
316
322
|
else
|
|
317
323
|
name = db.opts[:name]
|
|
@@ -319,6 +325,19 @@ class Sequel::ShardedTimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
319
325
|
end
|
|
320
326
|
end
|
|
321
327
|
|
|
328
|
+
# Return the next connection in the pool if there is one available. Returns nil
|
|
329
|
+
# if no connection is currently available.
|
|
330
|
+
def available(queue, _server)
|
|
331
|
+
queue.pop(timeout: 0)
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
# Return the next connection in the pool if there is one available. If not, wait
|
|
335
|
+
# until the timeout for a connection to become available. If there is still no
|
|
336
|
+
# available connection, return nil.
|
|
337
|
+
def wait_until_available(queue, _server)
|
|
338
|
+
queue.pop(timeout: @timeout)
|
|
339
|
+
end
|
|
340
|
+
|
|
322
341
|
# Returns the connection owned by the supplied thread for the given server,
|
|
323
342
|
# if any. The calling code should NOT already have the mutex before calling this.
|
|
324
343
|
def owned_connection(thread, server)
|
|
@@ -42,7 +42,7 @@ class Sequel::TimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
42
42
|
while true
|
|
43
43
|
conn = nil
|
|
44
44
|
begin
|
|
45
|
-
break unless (conn =
|
|
45
|
+
break unless (conn = available) && !conns[conn]
|
|
46
46
|
conns[conn] = true
|
|
47
47
|
yield conn
|
|
48
48
|
ensure
|
|
@@ -59,7 +59,7 @@ class Sequel::TimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
59
59
|
# Once a connection is requested using #hold, the connection pool
|
|
60
60
|
# creates new connections to the database.
|
|
61
61
|
def disconnect(opts=OPTS)
|
|
62
|
-
while conn =
|
|
62
|
+
while conn = available
|
|
63
63
|
disconnect_connection(conn)
|
|
64
64
|
end
|
|
65
65
|
fill_queue
|
|
@@ -220,7 +220,7 @@ class Sequel::TimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
220
220
|
#
|
|
221
221
|
# Calling code should not have the mutex when calling this.
|
|
222
222
|
def acquire(thread)
|
|
223
|
-
if conn =
|
|
223
|
+
if conn = available || try_make_new || wait_until_available
|
|
224
224
|
sync{@allocated[thread] = conn}
|
|
225
225
|
else
|
|
226
226
|
name = db.opts[:name]
|
|
@@ -228,6 +228,19 @@ class Sequel::TimedQueueConnectionPool < Sequel::ConnectionPool
|
|
|
228
228
|
end
|
|
229
229
|
end
|
|
230
230
|
|
|
231
|
+
# Return the next connection in the pool if there is one available. Returns nil
|
|
232
|
+
# if no connection is currently available.
|
|
233
|
+
def available
|
|
234
|
+
@queue.pop(timeout: 0)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# Return the next connection in the pool if there is one available. If not, wait
|
|
238
|
+
# until the timeout for a connection to become available. If there is still no
|
|
239
|
+
# available connection, return nil.
|
|
240
|
+
def wait_until_available
|
|
241
|
+
@queue.pop(timeout: @timeout)
|
|
242
|
+
end
|
|
243
|
+
|
|
231
244
|
# Returns the connection owned by the supplied thread,
|
|
232
245
|
# if any. The calling code should NOT already have the mutex before calling this.
|
|
233
246
|
def owned_connection(thread)
|
|
@@ -131,6 +131,12 @@ class Sequel::ConnectionPool
|
|
|
131
131
|
db.disconnect_connection(conn)
|
|
132
132
|
end
|
|
133
133
|
|
|
134
|
+
# Only for use by extension that need to disconnect a connection inside acquire.
|
|
135
|
+
# Takes the connection and any arguments accepted by acquire.
|
|
136
|
+
def disconnect_acquired_connection(conn, *)
|
|
137
|
+
disconnect_connection(conn)
|
|
138
|
+
end
|
|
139
|
+
|
|
134
140
|
# Whether the given exception is a disconnect exception.
|
|
135
141
|
def disconnect_error?(exception)
|
|
136
142
|
exception.is_a?(Sequel::DatabaseDisconnectError) || db.send(:disconnect_error?, exception, OPTS)
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
#
|
|
3
|
+
# The connection_checkout_event_callback extension modifies a database's
|
|
4
|
+
# connection pool to allow for a checkout event callback. This callback is
|
|
5
|
+
# called with the following arguments:
|
|
6
|
+
#
|
|
7
|
+
# :immediately_available :: Connection immediately available and returned
|
|
8
|
+
# :not_immediately_available :: Connection not immediately available
|
|
9
|
+
# :new_connection :: New connection created and returned
|
|
10
|
+
# Float :: Number of seconds waiting to acquire a connection
|
|
11
|
+
#
|
|
12
|
+
# This is a low-level extension that allows for building telemetry
|
|
13
|
+
# information. It doesn't implement any telemetry reporting itself. The
|
|
14
|
+
# main reason for recording this information is to use it to determine the
|
|
15
|
+
# appropriate size for the connection pool. Having too large a connection
|
|
16
|
+
# pool can waste resources, while having too small a connection pool can
|
|
17
|
+
# result in substantial time to check out a connection. In general, you
|
|
18
|
+
# want to use as small a pool as possible while keeping the time to
|
|
19
|
+
# checkout a connection low.
|
|
20
|
+
#
|
|
21
|
+
# To use the connection checkout event callback, you must first load the
|
|
22
|
+
# extension:
|
|
23
|
+
#
|
|
24
|
+
# DB.extension(:connection_checkout_event_callback)
|
|
25
|
+
#
|
|
26
|
+
# By default, an empty proc is used as the callback so that loading the
|
|
27
|
+
# support doesn't break anything. If you are using the extension, you
|
|
28
|
+
# should set the callback at some point during application startup:
|
|
29
|
+
#
|
|
30
|
+
# DB.pool.on_checkout_event = proc do |event|
|
|
31
|
+
# # ...
|
|
32
|
+
# end
|
|
33
|
+
#
|
|
34
|
+
# When using the sharded connection pool, the callback is also
|
|
35
|
+
# passed a second argument, the requested server shard (generally a
|
|
36
|
+
# symbol), allowing for collection of per-shard telemetry:
|
|
37
|
+
#
|
|
38
|
+
# DB.pool.on_checkout_event = proc do |event, server|
|
|
39
|
+
# # ...
|
|
40
|
+
# end
|
|
41
|
+
#
|
|
42
|
+
# Note that the callback may be called currently by multiple threads.
|
|
43
|
+
# You should use some form of concurrency control inside the callback,
|
|
44
|
+
# such as a mutex or queue.
|
|
45
|
+
#
|
|
46
|
+
# Below is a brief example of usage to determine the percentage of
|
|
47
|
+
# connection requests where a connection was immediately available:
|
|
48
|
+
#
|
|
49
|
+
# mutex = Mutex.new
|
|
50
|
+
# total = immediates = 0
|
|
51
|
+
#
|
|
52
|
+
# DB.pool.on_checkout_event = proc do |event|
|
|
53
|
+
# case event
|
|
54
|
+
# when :immediately_available
|
|
55
|
+
# mutex.synchronize do
|
|
56
|
+
# total += 1
|
|
57
|
+
# immediates += 1
|
|
58
|
+
# end
|
|
59
|
+
# when :not_immediately_available
|
|
60
|
+
# mutex.synchronize do
|
|
61
|
+
# total += 1
|
|
62
|
+
# end
|
|
63
|
+
# end
|
|
64
|
+
# end
|
|
65
|
+
#
|
|
66
|
+
# immediate_percentage = lambda do
|
|
67
|
+
# mutex.synchronize do
|
|
68
|
+
# 100.0 * immediates / total
|
|
69
|
+
# end
|
|
70
|
+
# end
|
|
71
|
+
#
|
|
72
|
+
# Note that this extension only works with the timed_queue
|
|
73
|
+
# and sharded_timed_queue connection pools (the default
|
|
74
|
+
# connection pools when using Ruby 3.2+).
|
|
75
|
+
#
|
|
76
|
+
# Related modules: Sequel::ConnectionCheckoutEventCallbacks::TimedQueue,
|
|
77
|
+
# Sequel::ConnectionCheckoutEventCallbacks::ShardedTimedQueue
|
|
78
|
+
|
|
79
|
+
#
|
|
80
|
+
module Sequel
|
|
81
|
+
module ConnectionCheckoutEventCallbacks
|
|
82
|
+
module TimedQueue
|
|
83
|
+
# The callback that is called with connection checkout events.
|
|
84
|
+
attr_accessor :on_checkout_event
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def available
|
|
89
|
+
conn = super
|
|
90
|
+
@on_checkout_event.call(conn ? :immediately_available : :not_immediately_available)
|
|
91
|
+
conn
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def try_make_new
|
|
95
|
+
conn = super
|
|
96
|
+
@on_checkout_event.call(:new_connection) if conn
|
|
97
|
+
conn
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def wait_until_available
|
|
101
|
+
timer = Sequel.start_timer
|
|
102
|
+
conn = super
|
|
103
|
+
@on_checkout_event.call(Sequel.elapsed_seconds_since(timer))
|
|
104
|
+
conn
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
module ShardedTimedQueue
|
|
109
|
+
# The callback that is called with connection checkout events.
|
|
110
|
+
attr_accessor :on_checkout_event
|
|
111
|
+
|
|
112
|
+
private
|
|
113
|
+
|
|
114
|
+
def available(queue, server)
|
|
115
|
+
conn = super
|
|
116
|
+
@on_checkout_event.call(conn ? :immediately_available : :not_immediately_available, server)
|
|
117
|
+
conn
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def try_make_new(server)
|
|
121
|
+
conn = super
|
|
122
|
+
@on_checkout_event.call(:new_connection, server) if conn
|
|
123
|
+
conn
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def wait_until_available(queue, server)
|
|
127
|
+
timer = Sequel.start_timer
|
|
128
|
+
conn = super
|
|
129
|
+
@on_checkout_event.call(Sequel.elapsed_seconds_since(timer), server)
|
|
130
|
+
conn
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
default_callback = proc{}
|
|
136
|
+
|
|
137
|
+
Database.register_extension(:connection_checkout_event_callback) do |db|
|
|
138
|
+
pool = db.pool
|
|
139
|
+
|
|
140
|
+
case pool.pool_type
|
|
141
|
+
when :timed_queue
|
|
142
|
+
db.pool.extend(ConnectionCheckoutEventCallbacks::TimedQueue)
|
|
143
|
+
when :sharded_timed_queue
|
|
144
|
+
db.pool.extend(ConnectionCheckoutEventCallbacks::ShardedTimedQueue)
|
|
145
|
+
else
|
|
146
|
+
raise Error, "the connection_checkout_event_callback extension is only supported when using a timed_queue connection pool"
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
pool.on_checkout_event ||= default_callback
|
|
150
|
+
end
|
|
151
|
+
end
|
data/lib/sequel/version.rb
CHANGED
|
@@ -6,7 +6,7 @@ module Sequel
|
|
|
6
6
|
|
|
7
7
|
# The minor version of Sequel. Bumped for every non-patch level
|
|
8
8
|
# release, generally around once a month.
|
|
9
|
-
MINOR =
|
|
9
|
+
MINOR = 102
|
|
10
10
|
|
|
11
11
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
|
12
12
|
# releases that fix regressions from previous versions.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sequel
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.
|
|
4
|
+
version: 5.102.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jeremy Evans
|
|
@@ -212,6 +212,7 @@ files:
|
|
|
212
212
|
- lib/sequel/extensions/blank.rb
|
|
213
213
|
- lib/sequel/extensions/caller_logging.rb
|
|
214
214
|
- lib/sequel/extensions/columns_introspection.rb
|
|
215
|
+
- lib/sequel/extensions/connection_checkout_event_callback.rb
|
|
215
216
|
- lib/sequel/extensions/connection_expiration.rb
|
|
216
217
|
- lib/sequel/extensions/connection_validator.rb
|
|
217
218
|
- lib/sequel/extensions/constant_sql_override.rb
|