pgtk 0.31.3 → 0.31.5

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pgtk/pool.rb +70 -56
  3. data/lib/pgtk/version.rb +1 -1
  4. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ce069bed0f29101349d2617ad2ae7c51f4f03e6b6a4b800d717bf4ac75bb533f
4
- data.tar.gz: 81e34a18fdf26fea4545e33f5c554af8b17f74f75e0a8efe450dea16fa13df49
3
+ metadata.gz: 9986e9d0fb260d182d823661b28c2782b7cbc066348431c59f18a2541e53018f
4
+ data.tar.gz: 50c04ad428b737284568c3cc134c7b5f0cff4d8cdf9b1a02430213a31e819701
5
5
  SHA512:
6
- metadata.gz: fea29eaaef7f045eec87fd114d5ba55782d50332333169ab30012bbf9e221dd2c3ef1be57af808f4aa1986b5356e27a8b25ce144c52bcaad3ad8329772eb81a2
7
- data.tar.gz: c84f1647c650b98ff6e34e752184a922ec74c285c55dcfa26714c50280a09bb5cf6bf3ff6e40dee0c5f03a39aa0aa30396ad7ffd30b05859d981eb67c2697437
6
+ metadata.gz: 0f6bf39b221fcedfc9ffd9843ef1d6ca43834d695c9a980139f60dd4915c9582f3174c5047710ecad954f62e9fad42b0fac540b9efcf5946885b7cde7da6b747
7
+ data.tar.gz: 64bd40eaa16ad9ee3684adc204d442b3ec8a19fe699c0cfc8323b19c098fcbf61ed3bf225d961bbb02cf1f16ee69b976035aaa5dd3661873ab4c3fbf00defd57
data/lib/pgtk/pool.rb CHANGED
@@ -4,6 +4,7 @@ require 'loog'
4
4
  # SPDX-FileCopyrightText: Copyright (c) 2019-2026 Yegor Bugayenko
5
5
  # SPDX-License-Identifier: MIT
6
6
 
7
+ require 'ellipsized'
7
8
  require 'pg'
8
9
  require 'tago'
9
10
  require_relative '../pgtk'
@@ -84,46 +85,7 @@ class Pgtk::Pool
84
85
  " Pgtk version: #{Pgtk::VERSION}",
85
86
  " PgSQL version: #{version}",
86
87
  " #{@pool.size} connections:",
87
- @pool.map do |c|
88
- [
89
- ' ',
90
- "##{c.backend_pid}",
91
- case c.pipeline_status
92
- when PG::Constants::PQ_PIPELINE_ON
93
- 'ON'
94
- when PG::Constants::PQ_PIPELINE_OFF
95
- 'OFF'
96
- when PG::Constants::PQ_PIPELINE_ABORTED
97
- 'ABORTED'
98
- else
99
- "pipeline_status=#{c.pipeline_status}"
100
- end,
101
- case c.status
102
- when PG::Constants::CONNECTION_OK
103
- 'OK'
104
- when PG::Constants::CONNECTION_BAD
105
- 'BAD'
106
- else
107
- "status=#{c.status}"
108
- end,
109
- case c.transaction_status
110
- when PG::Constants::PQTRANS_IDLE
111
- 'IDLE'
112
- when PG::Constants::PQTRANS_ACTIVE
113
- 'ACTIVE'
114
- when PG::Constants::PQTRANS_INTRANS
115
- 'INTRANS'
116
- when PG::Constants::PQTRANS_INERROR
117
- 'INERROR'
118
- when PG::Constants::PQTRANS_UNKNOWN
119
- 'UNKNOWN'
120
- else
121
- "transaction_status=#{c.transaction_status}"
122
- end
123
- ].join(' ')
124
- rescue PG::ConnectionBad => e
125
- e.message
126
- end
88
+ @pool.map { |conn| info(conn) }
127
89
  ].flatten.join("\n")
128
90
  end
129
91
 
@@ -219,9 +181,14 @@ class Pgtk::Pool
219
181
  r = yield(t)
220
182
  t.exec('COMMIT')
221
183
  r
222
- rescue StandardError => e
223
- t.exec('ROLLBACK')
224
- raise(e)
184
+ ensure
185
+ if c.transaction_status != PG::Constants::PQTRANS_IDLE
186
+ begin
187
+ t.exec('ROLLBACK')
188
+ rescue StandardError => e
189
+ @log.warn("Failed to rollback transaction: #{e.message}")
190
+ end
191
+ end
225
192
  end
226
193
  end
227
194
  end
@@ -306,6 +273,7 @@ class Pgtk::Pool
306
273
  def exec(query, args = [], result = 0)
307
274
  start = Time.now
308
275
  sql = query.is_a?(Array) ? query.join(' ') : query
276
+ @conn.instance_variable_set(:@pgtk_last_query, sql)
309
277
  begin
310
278
  out =
311
279
  if args.empty?
@@ -343,30 +311,76 @@ class Pgtk::Pool
343
311
 
344
312
  def connect
345
313
  conn = @pool.pop
346
- conn = renew(conn) if dead?(conn)
347
314
  begin
348
- yield(conn)
349
- rescue StandardError => e
315
+ reason = cause(conn)
316
+ if reason
317
+ begin
318
+ conn = renew(conn, reason)
319
+ rescue StandardError => e
320
+ @log.warn("Failed to renew dead connection (#{reason}): #{e.message}")
321
+ end
322
+ end
350
323
  begin
351
- conn = renew(conn)
352
- rescue StandardError => re
353
- @log.warn("Failed to renew connection after #{e.message}: #{re.message}")
324
+ yield(conn)
325
+ rescue StandardError => e
326
+ begin
327
+ conn = renew(conn, "query failed: #{e.message.strip}")
328
+ rescue StandardError => re
329
+ @log.warn("Failed to renew connection after #{e.message}: #{re.message}")
330
+ end
331
+ raise(e)
354
332
  end
355
- raise(e)
356
333
  ensure
357
334
  @pool.push(conn)
358
335
  end
359
336
  end
360
337
 
361
- def dead?(conn)
362
- conn.finished? || conn.status == PG::Constants::CONNECTION_BAD
363
- rescue StandardError
364
- true
338
+ def cause(conn)
339
+ return 'finished' if conn.finished?
340
+ return 'status BAD' if conn.status == PG::Constants::CONNECTION_BAD
341
+ return "transaction status #{conn.transaction_status}" if conn.transaction_status != PG::Constants::PQTRANS_IDLE
342
+ nil
343
+ rescue StandardError => e
344
+ "inspection failed: #{e.message.strip}"
365
345
  end
366
346
 
367
- def renew(conn)
347
+ def info(conn)
348
+ pipelines = { PG::Constants::PQ_PIPELINE_ON => 'ON', PG::Constants::PQ_PIPELINE_OFF => 'OFF',
349
+ PG::Constants::PQ_PIPELINE_ABORTED => 'ABORTED' }
350
+ statuses = { PG::Constants::CONNECTION_OK => 'OK', PG::Constants::CONNECTION_BAD => 'BAD' }
351
+ transactions = { PG::Constants::PQTRANS_IDLE => 'IDLE', PG::Constants::PQTRANS_ACTIVE => 'ACTIVE',
352
+ PG::Constants::PQTRANS_INTRANS => 'INTRANS', PG::Constants::PQTRANS_INERROR => 'INERROR',
353
+ PG::Constants::PQTRANS_UNKNOWN => 'UNKNOWN' }
354
+ parts = [
355
+ ' ',
356
+ "##{conn.backend_pid}",
357
+ pipelines.fetch(conn.pipeline_status, "pipeline_status=#{conn.pipeline_status}"),
358
+ statuses.fetch(conn.status, "status=#{conn.status}"),
359
+ transactions.fetch(conn.transaction_status, "transaction_status=#{conn.transaction_status}")
360
+ ]
361
+ if conn.transaction_status == PG::Constants::PQTRANS_ACTIVE
362
+ running = conn.instance_variable_get(:@pgtk_last_query)
363
+ parts << "running: #{running.gsub(/\s+/, ' ').strip.ellipsized(60)}" if running
364
+ end
365
+ parts.join(' ')
366
+ rescue PG::ConnectionBad => e
367
+ parts = [e.message.strip]
368
+ closed = conn.instance_variable_get(:@pgtk_closed_at)
369
+ parts << "#{closed.ago} ago" if closed
370
+ reason = conn.instance_variable_get(:@pgtk_closed_reason)
371
+ parts << "because: #{reason}" if reason
372
+ last = conn.instance_variable_get(:@pgtk_last_query)
373
+ parts << "last query: #{last.gsub(/\s+/, ' ').strip.ellipsized(60)}" if last
374
+ parts.join(', ')
375
+ end
376
+
377
+ def renew(conn, reason)
368
378
  begin
369
- conn.close unless conn.finished?
379
+ unless conn.finished?
380
+ conn.instance_variable_set(:@pgtk_closed_at, Time.now)
381
+ conn.instance_variable_set(:@pgtk_closed_reason, reason)
382
+ conn.close
383
+ end
370
384
  rescue StandardError => e
371
385
  @log.warn("Failed to close connection: #{e.message}")
372
386
  end
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.31.3' unless defined?(VERSION)
13
+ VERSION = '0.31.5' 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.31.3
4
+ version: 0.31.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko