Class: PGI::DB
- Inherits:
-
Object
- Object
- PGI::DB
- Defined in:
- lib/pgi/db.rb
Instance Attribute Summary collapse
-
#pool ⇒ Object
readonly
Returns the value of attribute pool.
Class Method Summary collapse
Instance Method Summary collapse
- #exec(sql) ⇒ Object
-
#initialize(pool, logger, max_retries: 30, retry_wait: 2) ⇒ DB
constructor
Create instance.
-
#method_missing(name) ⇒ Object
Pass the remainder of methods on to a PGI::Connection.
- #respond_to_missing?(name, include_private = false) ⇒ Boolean
-
#transaction { ... } ⇒ Object
wrapper around ConnectionPool#with with auto-healing capabilities.
-
#with { ... } ⇒ Object
wrapper around ConnectionPool#with with auto-healing capabilities.
Constructor Details
#initialize(pool, logger, max_retries: 30, retry_wait: 2) ⇒ DB
Create instance
16 17 18 19 20 21 |
# File 'lib/pgi/db.rb', line 16 def initialize(pool, logger, max_retries: 30, retry_wait: 2) @pool = pool @logger = logger @max_retries = max_retries @retry_wait = retry_wait end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name) ⇒ Object
Pass the remainder of methods on to a PGI::Connection
95 96 97 98 99 |
# File 'lib/pgi/db.rb', line 95 def method_missing(name, ...) with do |conn| conn.__send__(name, ...) end end |
Instance Attribute Details
#pool ⇒ Object (readonly)
Returns the value of attribute pool.
7 8 9 |
# File 'lib/pgi/db.rb', line 7 def pool @pool end |
Class Method Details
.configure {|@options| ... } ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/pgi/db.rb', line 23 def self.configure @options = Struct.new( :pool_size, :pool_timeout, :pg_conn_uri, :logger, :max_retries, :retry_wait ).new yield @options pool = ConnectionPool.new(size: @options.pool_size, timeout: @options.pool_timeout) do Connection.new(conn_uri: @options.pg_conn_uri, logger: @options.logger) end = { max_retries: @options.max_retries, retry_wait: @options.retry_wait }.compact new(pool, @options.logger, **) end |
Instance Method Details
#exec(sql) ⇒ Object
86 87 88 89 90 |
# File 'lib/pgi/db.rb', line 86 def exec(sql) with do |conn| conn.exec(sql) end end |
#respond_to_missing?(name, include_private = false) ⇒ Boolean
101 102 103 |
# File 'lib/pgi/db.rb', line 101 def respond_to_missing?(name, include_private = false) PG::Connection.method_defined?(name) || super end |
#transaction { ... } ⇒ Object
wrapper around ConnectionPool#with with auto-healing capabilities
41 42 43 44 45 46 47 48 49 |
# File 'lib/pgi/db.rb', line 41 def transaction raise "Missing block" unless block_given? with do |conn| conn.transaction do |trans_conn| yield Connection.new(conn: trans_conn, logger: @logger) end end end |
#with { ... } ⇒ Object
wrapper around ConnectionPool#with with auto-healing capabilities
Lost connections and pool checkout timeouts share the max_retries budget, so a genuinely stuck pool fails loudly instead of waiting forever.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/pgi/db.rb', line 57 def with raise "Missing block" unless block_given? retries = 0 begin @pool.with do |conn| # rubocop:disable Style/ExplicitBlockArgument yield conn end rescue PG::ConnectionBad, PG::UnableToSend => e retries += 1 if retries > @max_retries @logger&.error("DB connection was lost - unable to reconnect (#{e.class}: #{e.})") raise end @logger&.warn("DB connection was lost - reconnecting(#{retries}/#{@max_retries}) and retrying (#{e.class}: #{e.})") @pool.reload(&:close) sleep @retry_wait retry rescue ConnectionPool::TimeoutError => e retries += 1 if retries > @max_retries @logger&.error("Timeout in checking out DB connection from pool - giving up (#{e.})") raise end @logger&.warn("Timeout in checking out DB connection from pool - retrying(#{retries}/#{@max_retries}) (#{e.})") retry end end |