pgtk 0.32.6 → 0.32.7

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: bff4002fc7f88a973b99757aa0b8be3b82b6631b87f94c8ade93b30983b21761
4
- data.tar.gz: 707d5ec1bf05047d60a0f25103b7210751c4731f79caa8b08c3021e7e3810e6c
3
+ metadata.gz: 54a200f1f191d63b73c0137b1a1ace4aa34667f041d141365b47d9c90d96f191
4
+ data.tar.gz: 1518e5031b71a69e3955cabe77397d05917398fb87a12b94ee5c3aa57ab107eb
5
5
  SHA512:
6
- metadata.gz: 210230feda441fdee55cb3c3b6ccf1e2335efcdef77e95996afe89d3a4caf4f21bd8aa4fb9fd19f9b636d1336cc821345aa7454ec474d1693dff21990f2a1b40
7
- data.tar.gz: ab98c8f9cf29405c495bd4808855e1107889ccdc2ee9011f4abe431b561f05d033564dc587f5a3084f64f0842e935d4bee6b9c8265cc729fe762a0f99bab4eb9
6
+ metadata.gz: 28bbce0d3b2cfcbe2347f376738938e0e714f22b89fd2696052c56ecf7be83c242e9f0a87c76c235f109ec2008a45a1471ea157fc78f3ac9a8b8b71641ac2556
7
+ data.tar.gz: e94795ee7e4de524c77b5fddefb7a0d2ea9e85ec05beb09ebf81000919afec9a7b54d8a0fb480d9e24c16990fed7b7b142769caefddaefdd32d504f8086f5f46
data/README.md CHANGED
@@ -243,6 +243,18 @@ You can exclude specific queries from timeout enforcement using regex patterns:
243
243
  impatient = Pgtk::Impatient.new(pool, 2, /^SELECT/, /^VACUUM/)
244
244
  ```
245
245
 
246
+ Excluded queries are never wrapped in a transaction, because statements such as
247
+ `VACUUM`, `REINDEX`, or `CREATE INDEX CONCURRENTLY` cannot run inside a
248
+ transaction block. Instead, a longer fallback timeout (300 seconds by default,
249
+ configurable via the `default:` argument) is applied at the session level with
250
+ `SET statement_timeout` before the query runs, and reset afterwards. Pass
251
+ `default: 0` to run excluded queries with no timeout at all:
252
+
253
+ ```ruby
254
+ # Give excluded queries a 60-second fallback timeout
255
+ impatient = Pgtk::Impatient.new(pool, 2, /^VACUUM/, default: 60)
256
+ ```
257
+
246
258
  The timeout is enforced on the server side: each query is wrapped in a tiny
247
259
  transaction that issues `SET LOCAL statement_timeout`, and PostgreSQL itself
248
260
  terminates the query at the deadline. This guarantees the server-side
@@ -20,6 +20,14 @@ require_relative '../pgtk'
20
20
  # transaction-pool PgBouncer that does not forward client disconnects to in-flight
21
21
  # server queries). On timeout, +TooSlow+ is raised.
22
22
  #
23
+ # Queries that match one of the +off+ regular expressions are excluded from
24
+ # this checking. They are never wrapped in a transaction, because some
25
+ # statements (such as +VACUUM+, +REINDEX+, or +CREATE INDEX CONCURRENTLY+)
26
+ # cannot run inside a transaction block. Instead, a session-level
27
+ # +SET statement_timeout+ is applied on the same connection before the query
28
+ # runs (and reset afterwards), using the +default+ fallback timeout. Pass
29
+ # +default: 0+ to run excluded queries with no timeout at all.
30
+ #
23
31
  # Basic usage:
24
32
  #
25
33
  # # Create and configure a regular pool
@@ -102,6 +110,13 @@ class Pgtk::Impatient
102
110
  # behind a transaction-pool PgBouncer). When the deadline fires, the
103
111
  # underlying +PG::QueryCanceled+ is translated to +TooSlow+.
104
112
  #
113
+ # Queries matching one of the +off+ regular expressions bypass this
114
+ # transaction. They run on a single connection without a transaction block,
115
+ # guarded by a session-level +SET statement_timeout+ (the +default+ fallback,
116
+ # reset afterwards) or by no timeout at all when +default+ is zero. This keeps
117
+ # statements that cannot run inside a transaction, such as +VACUUM+ or
118
+ # +REINDEX+, working as expected.
119
+ #
105
120
  # @param [String, Array] query The SQL query with params inside (possibly)
106
121
  # @param [Array] args List of arguments
107
122
  # @return [Array] Result rows
@@ -110,9 +125,10 @@ class Pgtk::Impatient
110
125
  sql = query.is_a?(Array) ? query.join(' ') : query
111
126
  if @off.any? { |re| re.match?(sql) }
112
127
  ms = Integer(@default * 1000)
113
- return @pool.transaction do |t|
114
- t.exec("SET LOCAL statement_timeout = #{ms}") unless ms.zero?
115
- t.exec(sql, *args)
128
+ return @pool.exec(sql, *args) if ms.zero?
129
+ return @pool.session do |t|
130
+ t.exec("SET statement_timeout = #{ms}")
131
+ t.exec(sql, *args).tap { t.exec('RESET statement_timeout') }
116
132
  end
117
133
  end
118
134
  start = Time.now
data/lib/pgtk/pool.rb CHANGED
@@ -214,6 +214,29 @@ class Pgtk::Pool
214
214
  end
215
215
  end
216
216
 
217
+ # Grab a single connection from the pool and yield an executor bound to it,
218
+ # WITHOUT starting a transaction. Unlike +transaction+, no +START TRANSACTION+
219
+ # is issued, which makes this suitable for statements that PostgreSQL refuses
220
+ # to run inside a transaction block, such as +VACUUM+, +REINDEX+, or
221
+ # +CREATE INDEX CONCURRENTLY+. All statements executed through the yielded
222
+ # object run on the same connection, so a session-level setting (for example
223
+ # +SET statement_timeout+) made earlier in the block stays in effect for the
224
+ # statements that follow:
225
+ #
226
+ # pgsql.session do |s|
227
+ # s.exec('SET statement_timeout = 5000')
228
+ # s.exec('VACUUM book')
229
+ # s.exec('RESET statement_timeout')
230
+ # end
231
+ #
232
+ # @yield [Object] Yields an executor that responds to +exec+
233
+ # @return [Object] Result of the block
234
+ def session
235
+ connect do |c|
236
+ yield(Txn.new(c, @log))
237
+ end
238
+ end
239
+
217
240
  private
218
241
 
219
242
  def connect
data/lib/pgtk/spy.rb CHANGED
@@ -97,4 +97,15 @@ class Pgtk::Spy
97
97
  yield(Pgtk::Spy.new(t, &@block))
98
98
  end
99
99
  end
100
+
101
+ # Run statements on a single connection (no transaction) with spying on
102
+ # each SQL query.
103
+ #
104
+ # @yield [Pgtk::Spy] Yields a spy bound to one connection
105
+ # @return [Object] Result of the block
106
+ def session
107
+ @pool.session do |t|
108
+ yield(Pgtk::Spy.new(t, &@block))
109
+ end
110
+ end
100
111
  end
data/lib/pgtk/stash.rb CHANGED
@@ -149,6 +149,16 @@ class Pgtk::Stash
149
149
  end
150
150
  end
151
151
 
152
+ # Run statements on a single connection, without a transaction.
153
+ #
154
+ # @yield [Pgtk::Stash] A stash bound to the connection
155
+ # @return [Object] The result of the block
156
+ def session
157
+ @pool.session do |t|
158
+ yield(Pgtk::Stash.new(t, stash: @stash, loog: @loog, entrance: @entrance))
159
+ end
160
+ end
161
+
152
162
  private
153
163
 
154
164
  def queries
data/lib/pgtk/version.rb CHANGED
@@ -10,5 +10,5 @@ require_relative '../pgtk'
10
10
  # Copyright:: Copyright (c) 2019-2026 Yegor Bugayenko
11
11
  # License:: MIT
12
12
  module Pgtk
13
- VERSION = '0.32.6' unless defined?(VERSION)
13
+ VERSION = '0.32.7' unless defined?(VERSION)
14
14
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pgtk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.32.6
4
+ version: 0.32.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko