I followed the multiple databases with ActiveRecord guide to configure my development environment. I have 3 databases, 2 databases are primary and one is supposed to be a read-only replica.
My issue is that the read replica database is not being populated I have verified that data is correctly split among the 2 primary databases, I have 2 database schema files, and I do not have any errors in the application when doing get requests. The read replica database is empty however.
My thought was maybe something was wrong with my config for the automatic connection switching between read and write databases? The guide says that you need to setup the read-only replica database manually but doesn't give any instructions. I'm using Postgresql and Rails 7.0.3.
I had previously assumed that Rails would copy the data from the primary database to the replica but now that I'm typing this I'm wondering if that data replication is to be manually setup in Postgres somehow?
I'm not sure if both the primary_abstract_class and self.abstract_class = true are needed in application_record? Rails 7 adds the primary_abstract_class by default and the multi-database guide tells you to add self.abstract_class = true
app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
primary_abstract_class
self.abstract_class = true
connects_to database: { writing: :primary, reading: :primary }
end
app/models/offices_record.rb
class OfficesRecord < ApplicationRecord
self.abstract_class = true
# this isn't the name of the actual databases, but rather the primary/replica key in database.yml
connects_to database: { writing: :offices, reading: :offices_replica }
end
config/database.yml
development:
primary:
<<: *default
database: myapp_development
migrations_paths: db/migrate
offices:
<<: *default
database: myapp_offices_development
migrations_paths: db/offices_migrate
# replica user's database permissions should be set to read-only.
offices_replica:
<<: *default
database: myapp_offices_replica_development
username: read_only_user
password: R34dOnlyUs3rP@ssw0rd
replica: true
config/initializers/multi_db.rb
Rails.application.configure do
config.active_record.database_selector = { delay: 2.seconds }
config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
end
The office class inherits from OfficesRecord instead of ApplicationRecord because it is in the 2nd primary database. app/models/office.rb
class Office < OfficesRecord
end
How I configured Postgres
In Postgres a database backup of the myapp_offices_development database was taken (with no data) and restored over a new database to create the replica called myapp_offices_replica_development. I then ran the below to create a read-only user to access the read-only replica.
CREATE ROLE readaccess;
GRANT CONNECT ON DATABASE myapp_offices_replica_development TO readaccess;
GRANT USAGE ON SCHEMA public TO readaccess;
CREATE USER read_only_user WITH PASSWORD ‘R34dOnlyUs3rP@ssw0rd';
GRANT readaccess TO read_only_user;
I'm trying to figure out how to populate the database myapp_offices_replica_development with data from myapp_offices_development. Does Rails auto-magically handle this?