### Installing ActiveRecordProxyAdapters Gem Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md Instructions for adding the 'active_record_proxy_adapters' gem to a Ruby project using Bundler or installing it directly via the command line. ```Shell $ bundle add 'active_record_proxy_adapters' ``` ```Shell $ gem install active_record_proxy_adapters ``` -------------------------------- ### Configuring Trilogy Proxy Adapter in Rails Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md Example configuration for `config/database.yml` in a Rails application, demonstrating how to set up the `trilogy_proxy` adapter for the primary database and a standard `trilogy` adapter for the replica. ```YAML # config/database.yml development: primary: adapter: trilogy_proxy # your primary credentials here primary_replica: adapter: trilogy replica: true # your replica credentials here ``` -------------------------------- ### Configuring PostgreSQL Proxy Adapter in Rails Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md Example configuration for `config/database.yml` in a Rails application, demonstrating how to set up the `postgresql_proxy` adapter for the primary database and a standard `postgresql` adapter for the replica. ```YAML # config/database.yml development: primary: adapter: postgresql_proxy # your primary credentials here primary_replica: adapter: postgresql replica: true # your replica credentials here ``` -------------------------------- ### Example Log Output for ActiveRecord Proxy Adapters Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md This snippet displays the debug log output generated by ActiveRecordProxyAdapters, illustrating how different SQL queries are routed to either the primary or replica database. It highlights the custom log prefixes and demonstrates the "read-your-own-writes" behavior where subsequent reads after a write are temporarily routed to the primary. ```log D, [2024-12-24T17:18:49.151235 #328] DEBUG -- : [My replica tag] User Count (0.5ms) SELECT COUNT(*) FROM "users" D, [2024-12-24T17:18:49.156633 #328] DEBUG -- : [My primary tag] TRANSACTION (0.1ms) BEGIN D, [2024-12-24T17:18:49.157323 #328] DEBUG -- : [My primary tag] User Create (0.4ms) INSERT INTO "users" ("name", "email", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["name", "John Doe"], ["email", "john.doe@example.com"], ["created_at", "2024-12-24 17:18:49.156063"], ["updated_at", "2024-12-24 17:18:49.156063"]] D, [2024-12-24T17:18:49.158305 #328] DEBUG -- : [My primary tag] TRANSACTION (0.7ms) COMMIT D, [2024-12-24T17:18:49.159079 #328] DEBUG -- : [My primary tag] User Count (0.3ms) SELECT COUNT(*) FROM "users" D, [2024-12-24T17:18:50.166105 #328] DEBUG -- : [My primary tag] User Count (1.9ms) SELECT COUNT(*) FROM "users" D, [2024-12-24T17:18:51.169911 #328] DEBUG -- : [My replica tag] User Count (0.9ms) SELECT COUNT(*) FROM "users" => 3 ``` -------------------------------- ### Establishing Connections Off Rails with Proxy Adapters Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md Provides an example of how to manually establish connections for writing and reading roles using the proxy adapters outside of a Rails application, requiring explicit `require` statements for the gem. ```Ruby # In your application setup require "active_record_proxy_adapters" require "active_record_proxy_adapters/connection_handling" # in your base model class ApplicationRecord << ActiveRecord::Base establish_connection( { adapter: 'postgresql_proxy', # or any of the following: mysql2_proxy, trilogy_proxy, sqlite3_proxy # your primary credentials here }, role: :writing ) establish_connection( { adapter: 'postgresql', # or any of the following: mysql2, trilogy, sqlite3 # your replica credentials here }, role: :reading ) end ``` -------------------------------- ### Configuring MySQL Proxy Adapter in Rails Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md Example configuration for `config/database.yml` in a Rails application, demonstrating how to set up the `mysql2_proxy` adapter for the primary database and a standard `mysql2` adapter for the replica. ```YAML # config/database.yml development: primary: adapter: mysql2_proxy # your primary credentials here primary_replica: adapter: mysql2 replica: true # your replica credentials here ``` -------------------------------- ### Configuring ActiveRecord for Read/Write Splitting and Multi-threaded Queries in Ruby Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md This comprehensive example configures ActiveRecord models (`ApplicationRecord`, `Portal`) for database read/write splitting, directing writes to the primary and reads to a replica. It includes helper methods (`read_your_own_writes`, `use_replica`) and a test function (`test_multithread_queries`) to demonstrate concurrent database operations, showcasing how 'read-your-own-writes' consistency is handled and how queries can be explicitly routed to the replica in a multi-threaded Rails console environment. ```Ruby # app/models/application_record.rb class ApplicationRecord < ActiveRecord::Base self.abstract_class = true connects_to database: { writing: :primary, reading: :primary_replica } end # app/models/portal.rb class Portal < ApplicationRecord validates :name, uniqueness: true end # in rails console -e test ActiveRecord::Base.logger.formatter = proc do |_severity, _time, _progname, msg| "[#{Time.current.iso8601} THREAD #{Thread.current[:name]}] #{msg}\n" end ActiveRecordProxyAdapters.configure do |config| config.proxy_delay = 2.seconds end def read_your_own_writes proc do Portal.all.count # should go to the replica Portal.create(name: 'Read your own write') 5.times do Portal.all.count # first one goes the primary, last 4 should go to the replica sleep(3) end end end def use_replica proc do 5.times do Portal.all.count # should always go the replica sleep(1.5) end end end def executor Rails.application.executor end def test_multithread_queries ActiveRecordProxyAdapters.configure do |config| config.proxy_delay = 2.seconds config.checkout_timeout = 2.seconds end t1 = Thread.new do Thread.current[:name] = "USE REPLICA" executor.wrap { ActiveRecord::Base.uncached { use_replica.call } } end t2 = Thread.new do Thread.current[:name] = "READ YOUR OWN WRITES" executor.wrap { ActiveRecord::Base.uncached { read_your_own_writes.call } } end [t1, t2].each(&:join) end ``` -------------------------------- ### Configuring SQLite Proxy Adapter in Rails Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md Example configuration for `config/database.yml` in a Rails application, demonstrating how to set up the `sqlite3_proxy` adapter for the primary database and a standard `sqlite3` adapter for the replica. ```YAML # config/database.yml development: primary: adapter: sqlite3_proxy # your primary credentials here primary_replica: adapter: sqlite3 replica: true # your replica credentials here ``` -------------------------------- ### Connecting ApplicationRecord to Proxy Adapters in Rails Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md Demonstrates how to configure `ApplicationRecord` in a Rails application to use the `primary` database for writing and `primary_replica` for reading, leveraging Rails' native multiple database setup. ```Ruby # app/models/application_record.rb class ApplicationRecord < ActiveRecord::Base self.abstract_class = true connects_to database: { writing: :primary, reading: :primary_replica } end ``` -------------------------------- ### Demonstrating ActiveRecord Proxy Adapters in IRB (Ruby) Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md This Ruby IRB command sequence demonstrates the ActiveRecordProxyAdapters in action. It performs a User.count (initially routed to replica), creates a new user (routed to primary), and then performs three more User.count operations with delays, showcasing how the proxy handles read-your-own-writes consistency by temporarily routing reads to the primary. ```ruby irb(main):001> User.count ; User.create(name: 'John Doe', email: 'john.doe@example.com') ; 3.times { User.count ; sleep(1) } ``` -------------------------------- ### Setting up ActiveRecord Model for Read/Write Connections (Ruby) Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md This Ruby code demonstrates how to configure `ApplicationRecord` to use separate connections for writing and reading operations. It sets `ApplicationRecord` as an abstract class and uses `connects_to` to direct write operations to the `:primary` database and read operations to the `:primary_replica` database, leveraging the previously defined connection. ```Ruby class ApplicationRecord < ActiveRecord::Base self.abstract_class = true connects_to database: { writing: :primary, reading: :primary_replica } end ``` -------------------------------- ### Customizing ActiveRecordProxyAdapters Configuration Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md Shows how to customize the gem's default behavior, such as `proxy_delay` (how long reads are routed to primary after a write) and `checkout_timeout` (how long to wait for replica connection), using a `configure` block in an initializer. ```Ruby # config/initializers/active_record_proxy_adapters.rb ActiveRecordProxyAdapters.configure do |config| # How long proxy should reroute all read requests to primary after a write config.proxy_delay = 5.seconds # defaults to 2.seconds # How long proxy should wait for replica to connect. config.checkout_timeout = 5.seconds # defaults to 2.seconds end ``` -------------------------------- ### Configuring database.yml for FoobarProxyAdapter in YAML Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md This YAML configuration demonstrates how to set up `database.yml` to use the newly created `foobar_proxy` adapter. The `adapter` key should be set to `foobar_proxy`, and the rest of the configuration should specify the details for the primary database connection. ```YAML development: primary: adapter: foobar_proxy # primary database configuration ``` -------------------------------- ### Configuring ActiveRecord Multiple Databases and Callbacks in Ruby Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md This Ruby snippet defines ApplicationRecord to configure multiple database connections for writing (:primary) and reading (:primary_replica). It also shows a User model with validations and an after_commit callback that schedules a background job. The comment highlights a common challenge with replication delay, where a newly created record might not yet be available on the replica for the background job. ```ruby # app/models/application_record.rb class ApplicationRecord < ActiveRecord::Base self.abstract_class = true connects_to database: { writing: :primary, reading: :primary_replica } end # app/models/user.rb class User < ApplicationRecord validates :name, :email, presence: true after_commit :say_hello, on: :create private def say_hello SayHelloJob.perform_later(id) # new row may not be replicated yet end end ``` -------------------------------- ### Multi-threaded Query Execution Log Output in Bash Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md This snippet displays the console output from executing the `test_multithread_queries` function. It illustrates the routing of database queries to either the PostgreSQL Replica or Primary, demonstrating the 'read-your-own-writes' behavior where initial reads after a write go to the primary, while subsequent reads and replica-only queries are directed to the replica, along with transaction boundaries. ```Bash irb(main):051:0> test_multithread_queries [2024-12-24T13:52:40-05:00 THREAD USE REPLICA] [PostgreSQL Replica] Portal Count (1.4ms) SELECT COUNT(*) FROM "portals" [2024-12-24T13:52:40-05:00 THREAD READ YOUR OWN WRITES] [PostgreSQL Replica] Portal Count (0.4ms) SELECT COUNT(*) FROM "portals" [2024-12-24T13:52:40-05:00 THREAD READ YOUR OWN WRITES] [PostgreSQLProxy Primary] TRANSACTION (0.5ms) BEGIN [2024-12-24T13:52:40-05:00 THREAD READ YOUR OWN WRITES] [PostgreSQLProxy Primary] Portal Exists? (0.4ms) SELECT 1 AS one FROM "portals" WHERE "portals"."name" = $1 LIMIT $2 [["name", "Read your own write"], ["LIMIT", 1]] [2024-12-24T13:52:40-05:00 THREAD READ YOUR OWN WRITES] [PostgreSQLProxy Primary] Portal Create (0.8ms) INSERT INTO "portals" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["name", "Read your own write"], ["created_at", "2024-12-24 18:52:40.428383"], ["updated_at", "2024-12-24 18:52:40.428383"]] [2024-12-24T13:52:40-05:00 THREAD READ YOUR OWN WRITES] [PostgreSQLProxy Primary] TRANSACTION (0.7ms) COMMIT [2024-12-24T13:52:40-05:00 THREAD READ YOUR OWN WRITES] [PostgreSQLProxy Primary] Portal Count (0.6ms) SELECT COUNT(*) FROM "portals" [2024-12-24T13:52:41-05:00 THREAD USE REPLICA] [PostgreSQL Replica] Portal Count (4.4ms) SELECT COUNT(*) FROM "portals" [2024-12-24T13:52:43-05:00 THREAD USE REPLICA] [PostgreSQL Replica] Portal Count (3.3ms) SELECT COUNT(*) FROM "portals" [2024-12-24T13:52:43-05:00 THREAD READ YOUR OWN WRITES] [PostgreSQL Replica] Portal Count (2.8ms) SELECT COUNT(*) FROM "portals" [2024-12-24T13:52:44-05:00 THREAD USE REPLICA] [PostgreSQL Replica] Portal Count (18.0ms) SELECT COUNT(*) FROM "portals" [2024-12-24T13:52:46-05:00 THREAD USE REPLICA] [PostgreSQL Replica] Portal Count (0.9ms) SELECT COUNT(*) FROM "portals" [2024-12-24T13:52:46-05:00 THREAD READ YOUR OWN WRITES] [PostgreSQL Replica] Portal Count (2.3ms) SELECT COUNT(*) FROM "portals" [2024-12-24T13:52:49-05:00 THREAD READ YOUR OWN WRITES] [PostgreSQL Replica] Portal Count (7.2ms) SELECT COUNT(*) FROM "portals" [2024-12-24T13:52:52-05:00 THREAD READ YOUR OWN WRITES] [PostgreSQL Replica] Portal Count (3.7ms) SELECT COUNT(*) FROM "portals" => [#, #] ``` -------------------------------- ### Creating Database Tasks for FoobarProxyAdapter in Ruby Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md This Ruby snippet defines `FoobarProxyDatabaseTasks` to integrate the proxy adapter with Rails database tasks like `db:create` and `db:migrate`. It includes `ActiveRecordProxyAdapters::DatabaseTasks` and registers the new task class with `ActiveRecord::Tasks::DatabaseTasks` for `foobar_proxy` adapters. ```Ruby # lib/active_record/tasks/foobar_proxy_database_tasks.rb require "active_record_proxy_adapters/database_tasks" module ActiveRecord module Tasks class FoobarProxyDatabaseTasks < FoobarDatabaseTasks include ActiveRecordProxyAdapters::DatabaseTasks end end end ActiveRecord::Tasks::DatabaseTasks.register_task( /foobar_proxy/, "ActiveRecord::Tasks::FoobarProxyDatabaseTasks" ) ``` -------------------------------- ### Loading Custom Proxy Adapter in Rails Initializer (Ruby) Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md This Ruby snippet, placed in a Rails initializer, ensures the custom `foobar_proxy` adapter's connection handling is loaded only after the parent `foobaradapter` is fully loaded. This prevents load order issues and ensures all necessary dependencies are available before the proxy adapter is initialized. ```Ruby # config/initializers/active_record_proxy_adapters.rb # The parent adapter should have a load hook already. If not, you might need to monkey patch it. ActiveSupport.on_load(:active_record_foobaradapter) do require "active_record_proxy_adapters/connection_handling/foobar" end ``` -------------------------------- ### Creating Connection Handling for FoobarProxyAdapter in Ruby Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md This Ruby module, `ActiveRecordProxyAdapters::Foobar::ConnectionHandling`, provides methods for ActiveRecord to establish connections using the `foobar_proxy` adapter. It defines `foobar_proxy_adapter_class` and `foobar_proxy_connection`, which should adapt the original `foobar_connection` logic to use the new proxy adapter. This is primarily for Rails 7.0 or earlier. ```Ruby # lib/active_record_proxy_adapters/connection_handling/foobar.rb begin require "active_record/connection_adapters/foobar_proxy_adapter" rescue LoadError # foobar not available return end # This is only required for Rails 7.0 or earlier. module ActiveRecordProxyAdapters module Foobar module ConnectionHandling def foobar_proxy_adapter_class ActiveRecord::ConnectionAdapters::FoobarProxyAdapter end def foobar_proxy_connection(config) # copy and paste the contents of the original method foobar_connection here. # If the contents contain a hardcoded FooBarAdapter.new instance, # replace it with foobar_proxy_adapter_class.new end end end end ActiveSupport.on_load(:active_record) do ActiveRecord::Base.extend(ActiveRecordProxyAdapters::Foobar::ConnectionHandling) end ``` -------------------------------- ### Configuring a Replica Database Connection (YAML) Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md This YAML snippet defines a `primary_replica` database connection, specifying `foobar` as its adapter and marking it as a replica. This configuration is typically part of a larger `database.yml` file used by ActiveRecord to manage multiple database connections, enabling read operations to be directed to a replica. ```YAML primary_replica: adapter: foobar replica: true # replica database configuration ``` -------------------------------- ### Configuring ActiveRecord Proxy Adapters Logging in Ruby Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md This snippet configures the ActiveRecordProxyAdapters gem, setting custom prefixes for primary and replica database log messages. It also detaches the default ActiveRecord::LogSubscriber to prevent duplicate logging, ensuring cleaner output when the proxy adapter is active. ```ruby require "active_record_proxy_adapters/log_subscriber" ActiveRecordProxyAdapters.configure do |config| config.log_subscriber_primary_prefix = "My primary tag" # defaults to "#{adapter_name} Primary", i.e "PostgreSQL Primary" config.log_subscriber_replica_prefix = "My replica tag" # defaults to "#{adapter_name} Replica", i.e "PostgreSQL Replica" end # You may want to remove duplicate logs ActiveRecord::LogSubscriber.detach_from :active_record ``` -------------------------------- ### Configuring Database Adapters for Proxy Control in YAML Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md This YAML snippet from config/database.yml shows how to configure database connections to allow dynamic switching of the primary adapter. By using an environment variable PRIMARY_DATABASE_ADAPTER, the application can be configured to use either a standard PostgreSQL adapter or the postgresql_proxy adapter, enabling or disabling the proxy without code changes. ```yaml # config/database.yml production: primary: adapter: <%= ENV.fetch("PRIMARY_DATABASE_ADAPTER", "postgresql") %> primary_replica: adapter: postgresql replica: true ``` -------------------------------- ### Performing Background Job with Primary Connection in Ruby Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md This snippet demonstrates how a background job (`SayHelloJob`) explicitly uses `ApplicationRecord.connected_to(role: :writing)` to ensure that a user record is fetched from the primary database. This is crucial for maintaining 'read-your-own-writes' consistency, especially when a user might have just been created and the replica might not yet be synchronized. ```Ruby class SayHelloJob < ApplicationJob def perform(user_id) # so we manually reroute it to the primary user = ApplicationRecord.connected_to(role: :writing) { User.find(user_id) } UserMailer.welcome(user).deliver_now end } ``` -------------------------------- ### Defining the FoobarProxyAdapter Class in Ruby Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md This Ruby snippet creates `FoobarProxyAdapter`, inheriting from the original `FoobarAdapter` and including the `Hijackable` concern. It delegates methods to an instance of `FoobarProxy` and registers the adapter with ActiveRecord, especially for Rails 7.2+. This class acts as the main interface for the proxy connection. ```Ruby # lib/active_record/connection_adapters/foobar_proxy_adapter.rb require "active_record/tasks/foobar_proxy_database_tasks" require "active_record/connection_adapters/foobar_adapter" require "active_record_proxy_adapters/active_record_context" require "active_record_proxy_adapters/hijackable" require "active_record_proxy_adapters/foobar_proxy" module ActiveRecord module ConnectionAdapters class FoobarProxyAdapter < FoobarAdapter include ActiveRecordProxyAdapters::Hijackable ADAPTER_NAME = "FoobarProxy" # This is only an ActiveRecord convention and is not required to work delegate_to_proxy(*ActiveRecordProxyAdapters::ActiveRecordContext.hijackable_methods) def initialize(...) @proxy = ActiveRecordProxyAdapters::FoobarProxy.new(self) super end private attr_reader :proxy end end end # This is only required for Rails 7.2 or greater. if ActiveRecordProxyAdapters::ActiveRecordContext.active_record_v7_2_or_greater? ActiveRecord::ConnectionAdapters.register( "foobar_proxy", "ActiveRecord::ConnectionAdapters::FoobarProxyAdapter", "active_record/connection_adapters/foobar_proxy_adapter" ) end ActiveSupport.run_load_hooks(:active_record_foobarproxyadapter, ActiveRecord::ConnectionAdapters::FoobarProxyAdapter) ``` -------------------------------- ### Adding Zeitwerk Inflection Rule for FoobarProxyAdapter in Ruby Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md This Ruby code adds a custom Zeitwerk inflection rule for `foobar_proxy_adapter` to `FoobarProxyAdapter`. This is necessary if the file path does not conform to Rails' default naming conventions, ensuring the autoloader correctly maps the filename to its corresponding class name. ```Ruby # config/initializers/active_record_proxy_adapters.rb Rails.autoloaders.each do |autoloader| autoloader.inflector.inflect( "foobar_proxy_adapter" => "FoobarProxyAdapter" ) end ``` -------------------------------- ### Implementing the FoobarProxy Routing Class in Ruby Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md This Ruby code defines the `FoobarProxy` class, which inherits from `PrimaryReplicaProxy`. This class is responsible for handling the routing logic for the proxy adapter. It can be extended to override or hijack specific methods for custom behavior, though default behavior often suffices. ```Ruby # lib/active_record_proxy_adapters/foobar_proxy.rb require "active_record_proxy_adapters/primary_replica_proxy" module ActiveRecordProxyAdapters class FoobarProxy < PrimaryReplicaProxy # Override or hijack extra methods here if you need custom behavior # For most adapters, the default behavior works fine end end ``` -------------------------------- ### Manually Forcing Database Connection Role in Ruby Source: https://github.com/nasdaq/active_record_proxy_adapters/blob/main/README.md This Ruby snippet demonstrates how to manually control the database connection role using ApplicationRecord.connected_to. While a User.last call after a User.create would typically go to the primary for consistency, this method allows explicitly forcing the connection to the :reading role (replica), bypassing the proxy's automatic routing for specific operations. ```ruby User.create(name: 'John Doe', email: 'john.doe@example.com') last_user = User.last # This would normally go to the primary to adhere to read-your-own-writes consistency last_user = ApplicationRecord.connected_to(role: :reading) { User.last } # but I can override it with this block ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.