pgtk 0.30.9 → 0.31.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/pgtk/pool.rb +16 -4
- data/lib/pgtk/retry.rb +13 -10
- data/lib/pgtk/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5bce43b422e6baef8427e57d0635f613f2af93eea4a2f783b2fa62c85520b565
|
|
4
|
+
data.tar.gz: ea73771e5ea9c4f17919d257316d548280cf623e77f50266f6283e8f0ed71d8b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 908b1a4e77e794a5d91aae82169969bac770d3638771356f65b7f5ac7b2b490b14a99f5cc7caba4e63e99e09678d423f51944faf52f6c368040a6f4d55eb9b78
|
|
7
|
+
data.tar.gz: 5a15b9c10cb8f238b00888d761436633d8381e7b52c731af3c8fa67c5c4c48cd27274dc3975d9b3eaf612f189ffa871c026eca758991924b4d0aa3b3a4b9099a
|
data/lib/pgtk/pool.rb
CHANGED
|
@@ -49,16 +49,22 @@ require_relative 'wire'
|
|
|
49
49
|
# Copyright:: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
50
50
|
# License:: MIT
|
|
51
51
|
class Pgtk::Pool
|
|
52
|
+
# Raised when no connection becomes available from the pool within
|
|
53
|
+
# the configured timeout. Indicates that all connections are currently
|
|
54
|
+
# taken by other threads and none was returned in time.
|
|
55
|
+
class Busy < StandardError; end
|
|
56
|
+
|
|
52
57
|
# Constructor.
|
|
53
58
|
#
|
|
54
59
|
# @param [Pgtk::Wire] wire The wire
|
|
55
60
|
# @param [Integer] max Total amount of PostgreSQL connections in the pool
|
|
61
|
+
# @param [Numeric] timeout Max seconds to wait for a free connection
|
|
56
62
|
# @param [Object] log The log
|
|
57
|
-
def initialize(wire, max: 8, log: Loog::NULL)
|
|
63
|
+
def initialize(wire, max: 8, timeout: 1, log: Loog::NULL)
|
|
58
64
|
@wire = wire
|
|
59
65
|
@max = max
|
|
60
66
|
@log = log
|
|
61
|
-
@pool = IterableQueue.new(max)
|
|
67
|
+
@pool = IterableQueue.new(max, timeout)
|
|
62
68
|
@started = false
|
|
63
69
|
end
|
|
64
70
|
|
|
@@ -231,8 +237,9 @@ class Pgtk::Pool
|
|
|
231
237
|
# the internal array but is marked as "taken". When returned, it's placed
|
|
232
238
|
# back in its original slot and marked as available.
|
|
233
239
|
class IterableQueue
|
|
234
|
-
def initialize(size)
|
|
240
|
+
def initialize(size, timeout)
|
|
235
241
|
@size = size
|
|
242
|
+
@timeout = timeout
|
|
236
243
|
@items = []
|
|
237
244
|
@taken = []
|
|
238
245
|
@mutex = Mutex.new
|
|
@@ -259,7 +266,12 @@ class Pgtk::Pool
|
|
|
259
266
|
|
|
260
267
|
def pop
|
|
261
268
|
@mutex.synchronize do
|
|
262
|
-
|
|
269
|
+
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + @timeout
|
|
270
|
+
while @taken.all? || @items.empty?
|
|
271
|
+
remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
272
|
+
raise(Busy, "No free connection appeared in the pool after #{@timeout}s of waiting") if remaining <= 0
|
|
273
|
+
@condition.wait(@mutex, remaining)
|
|
274
|
+
end
|
|
263
275
|
index = @taken.index(false)
|
|
264
276
|
@taken[index] = true
|
|
265
277
|
@items[index]
|
data/lib/pgtk/retry.rb
CHANGED
|
@@ -49,11 +49,17 @@ require_relative 'impatient'
|
|
|
49
49
|
# Copyright:: Copyright (c) 2019-2026 Yegor Bugayenko
|
|
50
50
|
# License:: MIT
|
|
51
51
|
class Pgtk::Retry
|
|
52
|
+
# Raised when all retry attempts have been exhausted. The original
|
|
53
|
+
# exception that caused the last failure is available via #cause,
|
|
54
|
+
# so its message and stack trace are preserved for debugging.
|
|
55
|
+
class Exhausted < StandardError; end
|
|
56
|
+
|
|
52
57
|
# Constructor.
|
|
53
58
|
#
|
|
54
59
|
# @param [Pgtk::Pool] pool The pool to decorate
|
|
55
60
|
# @param [Integer] attempts Number of attempts to make (default: 3)
|
|
56
61
|
def initialize(pool, attempts: 3)
|
|
62
|
+
raise(ArgumentError, "Attempts must be at least 2, while #{attempts} provided") if attempts < 2
|
|
57
63
|
@pool = pool
|
|
58
64
|
@attempts = attempts
|
|
59
65
|
end
|
|
@@ -79,10 +85,11 @@ class Pgtk::Retry
|
|
|
79
85
|
].join("\n")
|
|
80
86
|
end
|
|
81
87
|
|
|
82
|
-
# Execute a SQL query with automatic retry for SELECT queries.
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
#
|
|
88
|
+
# Execute a SQL query with automatic retry for SELECT queries only.
|
|
89
|
+
# Non-SELECT queries fail on the first error, since a failure may occur
|
|
90
|
+
# after the server received the query but before the acknowledgement
|
|
91
|
+
# reached the client, and retrying a non-idempotent write could duplicate
|
|
92
|
+
# it.
|
|
86
93
|
#
|
|
87
94
|
# @param [String] sql The SQL query with params inside (possibly)
|
|
88
95
|
# @return [Array] Result rows
|
|
@@ -91,14 +98,10 @@ class Pgtk::Retry
|
|
|
91
98
|
attempt = 0
|
|
92
99
|
begin
|
|
93
100
|
@pool.exec(sql, *)
|
|
94
|
-
rescue
|
|
95
|
-
attempt += 1
|
|
96
|
-
raise(e) if attempt >= @attempts
|
|
97
|
-
retry
|
|
98
|
-
rescue StandardError => e
|
|
101
|
+
rescue StandardError, Pgtk::Impatient::TooSlow => e
|
|
99
102
|
raise(e) unless query.strip.upcase.start_with?('SELECT')
|
|
100
103
|
attempt += 1
|
|
101
|
-
raise(e) if attempt >= @attempts
|
|
104
|
+
raise(Exhausted, "Retry gave up after #{@attempts} attempts: #{e.message}") if attempt >= @attempts
|
|
102
105
|
retry
|
|
103
106
|
end
|
|
104
107
|
end
|
data/lib/pgtk/version.rb
CHANGED