Class: Pgtk::Impatient

Inherits:
Object
  • Object
show all
Defined in:
lib/pgtk/impatient.rb

Overview

Impatient is a decorator for Pool that enforces timeouts on all database operations. It ensures that SQL queries don’t run indefinitely, which helps prevent application hangs and resource exhaustion when database operations are slow or stalled.

This class implements the same interface as Pool but wraps each database operation in a timeout block. If a query exceeds the specified timeout, it raises a Timeout::Error exception, allowing the application to handle slow queries gracefully.

Basic usage:

# Create and configure a regular pool
pool = Pgtk::Pool.new(wire).start(4)

# Wrap the pool in an impatient decorator with a 2-second timeout
impatient = Pgtk::Impatient.new(pool, 2)

# Execute queries with automatic timeout enforcement
begin
  impatient.exec('SELECT * FROM large_table WHERE complex_condition')
rescue Timeout::Error
  puts "Query timed out after 2 seconds"
end

# Transactions also enforce timeouts on each query
begin
  impatient.transaction do |t|
    t.exec('UPDATE large_table SET processed = true')
    t.exec('DELETE FROM queue WHERE processed = true')
  end
rescue Timeout::Error
  puts "Transaction timed out"
end

# Combining with Spy for timeout monitoring
spy = Pgtk::Spy.new(impatient) do |sql, duration|
  puts "Query completed in #{duration} seconds: #{sql}"
end

# Now queries are both timed and monitored
spy.exec('SELECT * FROM users')
Author

Yegor Bugayenko (yegor256@gmail.com)

Copyright

Copyright © 2019-2025 Yegor Bugayenko

License

MIT

Instance Method Summary collapse

Constructor Details

#initialize(pool, timeout = 1) ⇒ Impatient

Constructor.

Parameters:

  • pool (Pgtk::Pool)

    The pool to decorate

  • timeout (Integer) (defaults to: 1)

    Timeout in seconds for each SQL query



58
59
60
61
# File 'lib/pgtk/impatient.rb', line 58

def initialize(pool, timeout = 1)
  @pool = pool
  @timeout = timeout
end

Instance Method Details

#exec(sql, *args) ⇒ Array

Execute a SQL query with a timeout.

Parameters:

  • sql (String)

    The SQL query with params inside (possibly)

  • args (Array)

    List of arguments

Returns:

  • (Array)

    Result rows

Raises:

  • (Timeout::Error)

    If the query takes too long



76
77
78
79
80
# File 'lib/pgtk/impatient.rb', line 76

def exec(sql, *args)
  Timeout.timeout(@timeout) do
    @pool.exec(sql, *args)
  end
end

#transaction {|Pgtk::Impatient| ... } ⇒ Object

Run a transaction with a timeout for each query.

Yields:

Returns:

  • (Object)

    Result of the block



86
87
88
89
90
# File 'lib/pgtk/impatient.rb', line 86

def transaction
  @pool.transaction do |t|
    yield Pgtk::Impatient.new(t, @timeout)
  end
end

#versionString

Get the version of PostgreSQL server.

Returns:

  • (String)

    Version of PostgreSQL server



66
67
68
# File 'lib/pgtk/impatient.rb', line 66

def version
  @pool.version
end