class RailsFailover::ActiveRecord::Middleware

Constants

CURRENT_ROLE_HEADER
WRITING_ROLE_HEADER

Attributes

force_reading_role_callback[RW]

Public Class Methods

new(app) click to toggle source
# File lib/rails_failover/active_record/middleware.rb, line 48
def initialize(app)
  @app = app
end

Public Instance Methods

call(env) click to toggle source
# File lib/rails_failover/active_record/middleware.rb, line 52
def call(env)
  current_role = ::ActiveRecord::Base.current_role || ::ActiveRecord::Base.writing_role
  is_writing_role = current_role.to_s.end_with?(::ActiveRecord::Base.writing_role.to_s)
  writing_role = resolve_writing_role(current_role, is_writing_role)

  role =
    if primary_down = self.class.force_reading_role_callback&.call(env) || Handler.instance.primary_down?(writing_role)
      reading_role = resolve_reading_role(current_role, is_writing_role)
      ensure_reading_connection_established!(writing_role: writing_role, reading_role: reading_role)
      reading_role
    else
      writing_role
    end

  ::ActiveRecord::Base.connected_to(role: role) do
    env[CURRENT_ROLE_HEADER] = role
    env[WRITING_ROLE_HEADER] = writing_role
    @app.call(env)
  end
rescue => e
  Interceptor.verify_primary(e, writing_role) if writing_role
  raise e
end

Private Instance Methods

ensure_reading_connection_established!(writing_role:, reading_role:) click to toggle source
# File lib/rails_failover/active_record/middleware.rb, line 78
def ensure_reading_connection_established!(writing_role:, reading_role:)
  ::ActiveRecord::Base.connection_handlers[reading_role] ||= begin
    handler = ::ActiveRecord::ConnectionAdapters::ConnectionHandler.new

    ::ActiveRecord::Base.connection_handlers[writing_role].connection_pools.each do |pool|
      if pool.respond_to?(:db_config)
        config = pool.db_config.configuration_hash
      else
        config = pool.spec.config
      end
      ::RailsFailover::ActiveRecord.establish_reading_connection(handler, config)
    end

    handler
  end
end
resolve_reading_role(current_role, is_writing_role) click to toggle source
# File lib/rails_failover/active_record/middleware.rb, line 106
def resolve_reading_role(current_role, is_writing_role)
  if is_writing_role
    current_role.to_s.sub(
      /#{::ActiveRecord::Base.writing_role}$/,
      ::ActiveRecord::Base.reading_role.to_s
    ).to_sym
  else
    current_role
  end
end
resolve_writing_role(current_role, is_writing_role) click to toggle source
# File lib/rails_failover/active_record/middleware.rb, line 95
def resolve_writing_role(current_role, is_writing_role)
  if is_writing_role
    current_role
  else
    current_role.to_s.sub(
      /#{::ActiveRecord::Base.reading_role}$/,
      ::ActiveRecord::Base.writing_role.to_s
    ).to_sym
  end
end