# EbisuConnection [![Gem Version](https://badge.fury.io/rb/ebisu_connection.svg)](http://badge.fury.io/rb/ebisu_connection) [![Build Status](https://travis-ci.org/tsukasaoishi/ebisu_connection.svg?branch=master)](https://travis-ci.org/tsukasaoishi/ebisu_connection) [![Code Climate](https://codeclimate.com/github/tsukasaoishi/ebisu_connection/badges/gpa.svg)](https://codeclimate.com/github/tsukasaoishi/ebisu_connection) EbisuConnection allows access to replica servers. You could assign a performance weight to each replica server. ``` Rails ------------ Master DB | | +---- Replica1 DB (weight 10) | | +---- Replica2 DB (weight 20) ``` If you could put a load balancer in front of replica servers, should use [FreshConnection](https://github.com/tsukasaoishi/fresh_connection). ## Usage ### Access to Replica Read query goes to the replica server. ```ruby Article.where(:id => 1) ``` ### Access to Master If read query want to access to the master server, use `read_master`. In before version 0.3.1, can use `readonly(false)`. ```ruby Article.where(:id => 1).read_master ``` In transaction, All queries go to the master server. ```ruby Article.transaction do Article.where(:id => 1) end ``` Create, Update and Delete queries go to the master server. ```ruby article = Article.create(...) article.title = "FreshConnection" article.save article.destory ``` ## Support ActiveRecord version EbisuConnection supports ActiveRecord version 5.0 or later. If you are using Rails 4.2, you can use EbisuConnection version 2.4.2 or before. ## Support DB EbisuConnection supports MySQL and PostgreSQL. ## Installation Add this line to your application's Gemfile: ```ruby gem 'ebisu_connection' ``` And then execute: ``` $ bundle ``` Or install it yourself as: ``` $ gem install ebisu_connection ``` ## Config config/database.yml ```yaml default: &default adapter: mysql2 encoding: utf8 pool: <%%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: production: <<: *default database: blog_production username: master_db_user password: <%= ENV['MASTER_DATABASE_PASSWORD'] %> host: master_db replica: username: replica_db_user password: <%= ENV['REPLICA_DATABASE_PASSWORD'] %> ``` `replica` is the configuration used for connecting read-only queries to the database replica. All other connections will use the database master settings. Config of each replica server fill out to `config/replica.yml` ```yaml production: - "replica1, 10" - "replica2, 20" - host: "replica3" weight: 30 ``` ```yaml "hostname, weight" ``` String format is it. You can write config with hash. ### use multiple replica servers group If you may want to user multiple replica group, write multiple replica group to config/database.yml. ```yaml default: &default adapter: mysql2 encoding: utf8 pool: <%%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: production: <<: *default database: blog_production username: master_db_user password: <%= ENV['MASTER_DATABASE_PASSWORD'] %> host: master_db replica: username: replica_db_user password: <%= ENV['REPLICA_DATABASE_PASSWORD'] %> admin_replica: username: admin_replica_db_user password: <%= ENV['ADMIN_REPLICA_DATABASE_PASSWORD'] %> ``` Config of each replica server fill out to `config/replica.yml` ```yaml production: replica: - "replica1, 10" - "replica2, 20" - host: "replica3" weight: 30 admin_replica: - "replica4, 10" - "replica5, 20" ``` The custom replica stanza can then be applied as an argument to the `establish_fresh_connection` method in the models that should use it. For example: ```ruby class AdminUser < ActiveRecord::Base establish_fresh_connection :admin_replica end ``` The child (sub) classes of the configured model will inherit the same access as the parent class. Example: ```ruby class Parent < ActiveRecord::Base establish_fresh_connection :admin_replica end class AdminUser < Parent end class Benefit < Parent end ``` The `AdminUser` and `Benefit` models will access the database configured for the `admin_replica` group. ### Master-only Models It is possible to declare that specific models always use the DB master for all connections, using the `master_db_only!` method: ```ruby class SomethingModel < ActiveRecord::Base master_db_only! end ``` All queries generated by methods on the `CustomerState` model will be directed to the DB master. ### Using EbisuConnection With Unicorn ```ruby before_fork do |server, worker| ... ActiveRecord::Base.clear_all_replica_connections! ... end ``` ## Contributing 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request ## Test I'm glad that you would do test! To run the test suite, you need mysql installed. How to setup your test environment. ```bash ./bin/setup ``` This command run the spec suite for all rails versions supported. ```base ./bin/test ```