It is a library that performs extended verification when an error occurs when executing SQL.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

Runtime

 Project Readme

active_record_postgresql_xverify

It is a library to solve Amazon RDS failover problems.

cf. brianmario/mysql2#948

Note

This library does not retry queries. Just reconnect.

Caution

The timing of verify has changed, so it probably won't work properly with Rails 7.1. cf. rails/rails#44576

Gem Version CI

How it works

Installation

Add this line to your application's Gemfile:

gem 'active_record_postgresql_xverify'

And then execute:

$ bundle

Or install it yourself as:

$ gem install active_record_postgresql_xverify

Usage

#!/usr/bin/env ruby
require 'active_record'
require 'active_record_postgresql_xverify'
require 'logger'

ActiveRecord::Base.establish_connection(
  adapter:  'postgresql',
  host:     '127.0.0.1',
  port:      5432,
  username: 'root',
  database: 'bookshelf',
)

ActiveRecord::Base.logger = Logger.new($stdout)
ActiveRecord::Base.logger.formatter = proc {|_, _, _, message| "#{message}\n" }

ActiveRecordPostgresqlXverify.verify = ->(conn) do
  ping = begin
           conn.query ''
           true
         rescue PG::Error
           false
         end

  ping && false # force reconnect
end
# Default: ->(conn) do
#            begin
#              conn.query ''
#              true
#            rescue PG::Error
#              false
#            end

ActiveRecordPostgresqlXverify.handle_if = ->(config) do
  config[:host] == '127.0.0.1'
end
# Default: ->(_) { true }

ActiveRecordPostgresqlXverify.only_on_error = false
# Default: true

# postgres=> CREATE DATABASE bookshelf;
# bookshelf=> CREATE TABLE books (id INT PRIMARY KEY);
class Book < ActiveRecord::Base; end

def pg_backend_pid(model)
  conn = model.connection.instance_variable_get(:@connection) || Book.connection.instance_variable_get(:@raw_connection)
  conn.backend_pid
end

Book.count
prev_process_id = pg_backend_pid(Book)

ActiveRecord::Base.connection_handler.connection_pool_list.each(&:release_connection)

Book.count
curr_process_id = pg_backend_pid(Book)

p curr_process_id == prev_process_id #=> false

Rails configuration

In config/environments/production.rb:

ActiveRecordPostgresqlXverify.verify = ->(conn) do
  ping = begin
           conn.query ''
           true
         rescue PG::Error
           false
         end

  ping && conn.query('show transaction_read_only').getvalue(0, 0) == 'off'
end
# Same as below:
#   ActiveRecordPostgresqlXverify.verify = ActiveRecordPostgresqlXverify::Verifiers::AURORA_MASTER

Test

bundle install
bundle exec appraisal install
docker-compose up -d
bundle exec appraisal ar71 rake

Related links