ankane / distribute_reads

Scale database reads to replicas in Rails

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Specifying the name of the replica with the distribute_reads method

fabienpiette opened this issue · comments

Hello,

With the configuration below, is it possible to specify the name of the replica used when calling the distribute_reads method? The idea is to be able to choose on which replica I want to make SELECT queries.

Something like this:

distribute_reads(replica1: true) do
  # ...
end

or

distribute_reads(name: 'replica1') do
  # ...
end
default: &default
  url: postgresql-makara:///
  makara:
    sticky: true
    connections:
      - role: master
        name: primary
        url: <%= ENV["DATABASE_URL"] %>
      - name: replica1
        url: <%= ENV["REPLICA1_DATABASE_URL"] %>
      - name: replica2
        url: <%= ENV["REPLICA2_DATABASE_URL"] %>

development:
  <<: *default

production:
  <<: *default

Thank you in advance for your answers.

Hey @fabienpiette, there's not currently an option for it, but happy to consider it if someone finds a simple way to implement it. Do you have a specific use case in mind?

Okay no problem, I'll try to see if it can be set up easily.
For specific use case, in my case, I would like to be able to use several read replicas and to dedicate one for the administration part of the site, another one for background tasks and large calculations (for example).

With ActiveAdmin I could do something like that:

# in config/active_admin_extensions.rb
ActiveAdmin::BaseController.send(:include, ActiveAdmin::ReadReplica)
# in lib/active_admin/read_replica.rb
module ActiveAdmin
  module ReadReplica
    extend ActiveSupport::Concern

    included do
      around_action :request_on_read_replica
    end

    private

      def request_on_read_replica
        distribute_reads(replica: :admin_replica) do
          yield if block_given?
        end
      end
  end
end

And something along the same lines for jobs.

class TestJob < ApplicationJob
  distribute_reads replica: :jobs_replica

  def perform
    # ...
  end
end

One way I've seen work well is having a single replica in database.yml and setting a different REPLICA_DATABASE_URL in the environment for different sets of servers.

Just wanted to say that this feature would be awesome! For my use case, we're transitioning from a larger, more expensive DB instance to a smaller one. Being able to specify which read replica a specific piece of code should hit would be huge as it makes our performance monitoring/benchmarking super straightforward.