Class: Pgtk::Retry
- Inherits:
-
Object
- Object
- Pgtk::Retry
- Defined in:
- lib/pgtk/retry.rb
Overview
Retry is a decorator for Pool that automatically retries failed SELECT queries. It provides fault tolerance for transient database errors by retrying read-only operations a configurable number of times before giving up.
This class implements the same interface as Pool but adds retry logic specifically for SELECT queries. Non-SELECT queries are executed without retry to maintain data integrity and avoid unintended side effects from duplicate writes.
Basic usage:
# Create and configure a regular pool
pool = Pgtk::Pool.new(wire, max: 4)
pool.start!
# Wrap the pool in a retry decorator with 3 attempts
retry_pool = Pgtk::Retry.new(pool, attempts: 3)
# SELECT queries are automatically retried on failure
begin
retry_pool.exec('SELECT * FROM users WHERE id = $1', [42])
rescue PG::Error => e
puts "Query failed after 3 attempts: #{e.}"
end
# Non-SELECT queries are not retried
retry_pool.exec('UPDATE users SET active = true WHERE id = $1', [42])
# Transactions pass through without retry logic
retry_pool.transaction do |t|
t.exec('SELECT * FROM accounts') # No retry within transaction
t.exec('UPDATE accounts SET balance = balance + 100')
end
# Combining with other decorators
impatient = Pgtk::Impatient.new(retry_pool, 5)
spy = Pgtk::Spy.new(impatient) do |sql, duration|
puts "Query: #{sql} (#{duration}s)"
end
- Author
-
Yegor Bugayenko (yegor256@gmail.com)
- Copyright
-
Copyright © 2019-2026 Yegor Bugayenko
- License
-
MIT
Instance Method Summary collapse
-
#dump ⇒ Object
Convert internal state into text.
-
#exec(sql) ⇒ Array
Execute a SQL query with automatic retry for SELECT queries.
-
#initialize(pool, attempts: 3) ⇒ Retry
constructor
Constructor.
-
#start! ⇒ Object
Start a new connection pool with the given arguments.
-
#transaction {|Object| ... } ⇒ Object
Run a transaction without retry logic.
-
#version ⇒ String
Get the version of PostgreSQL server.
Constructor Details
#initialize(pool, attempts: 3) ⇒ Retry
Constructor.
55 56 57 58 |
# File 'lib/pgtk/retry.rb', line 55 def initialize(pool, attempts: 3) @pool = pool @attempts = attempts end |
Instance Method Details
#dump ⇒ Object
Convert internal state into text.
73 74 75 76 77 78 79 |
# File 'lib/pgtk/retry.rb', line 73 def dump [ @pool.dump, '', "Pgtk::Retry (attempts=#{@attempts})" ].join("\n") end |
#exec(sql) ⇒ Array
Execute a SQL query with automatic retry for SELECT queries. Also retries PG::ConnectionBad errors for all query types, since connection errors indicate the query never reached PostgreSQL.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/pgtk/retry.rb', line 87 def exec(sql, *) query = sql.is_a?(Array) ? sql.join(' ') : sql attempt = 0 begin @pool.exec(sql, *) rescue PG::ConnectionBad => e attempt += 1 raise(e) if attempt >= @attempts retry rescue StandardError => e raise(e) unless query.strip.upcase.start_with?('SELECT') attempt += 1 raise(e) if attempt >= @attempts retry end end |
#start! ⇒ Object
Start a new connection pool with the given arguments.
61 62 63 |
# File 'lib/pgtk/retry.rb', line 61 def start! @pool.start! end |
#transaction {|Object| ... } ⇒ Object
Run a transaction without retry logic.
108 109 110 |
# File 'lib/pgtk/retry.rb', line 108 def transaction(&) @pool.transaction(&) end |
#version ⇒ String
Get the version of PostgreSQL server.
68 69 70 |
# File 'lib/pgtk/retry.rb', line 68 def version @pool.version end |