Class: MultiDb::ConnectionProxy
- Inherits:
-
Object
- Object
- MultiDb::ConnectionProxy
- Extended by:
- ThreadLocalAccessors
- Includes:
- ActiveRecord::ConnectionAdapters::QueryCache, QueryCacheCompat
- Defined in:
- lib/multi_db/connection_proxy.rb
Constant Summary collapse
- SAFE_METHODS =
Safe methods are those that should either go to the slave ONLY or go to the current active connection.
[ :select_all, :select_one, :select_value, :select_values, :select_rows, :select, :verify!, :raw_connection, :active?, :reconnect!, :disconnect!, :reset_runtime, :log, :log_info ]
- DEFAULT_MASTER_MODELS =
< Rails 2.3
['CGI::Session::ActiveRecordStore::Session']
Class Attribute Summary collapse
-
.environment ⇒ Object
defaults to RAILS_ENV if multi_db is used with Rails defaults to ‘development’ when used outside Rails.
-
.master_models ⇒ Object
a list of models that should always go directly to the master.
-
.sticky_slave ⇒ Object
decides if we should switch to the next reader automatically.
Instance Attribute Summary collapse
-
#master ⇒ Object
Returns the value of attribute master.
Class Method Summary collapse
-
.setup! ⇒ Object
Replaces the connection of ActiveRecord::Base with a proxy and establishes the connections to the slaves.
Instance Method Summary collapse
-
#initialize(master, slaves) ⇒ ConnectionProxy
constructor
A new instance of ConnectionProxy.
-
#method_missing(method, *args, &block) ⇒ Object
Calls the method on master/slave and dynamically creates a new method on success to speed up subsequent calls.
-
#next_reader! ⇒ Object
Switches to the next slave database for read operations.
- #slave ⇒ Object
- #transaction(start_db_transaction = true, &block) ⇒ Object
- #with_master ⇒ Object
Methods included from QueryCacheCompat
#columns, #delete, #insert, #select_all, #update
Constructor Details
#initialize(master, slaves) ⇒ ConnectionProxy
Returns a new instance of ConnectionProxy.
86 87 88 89 90 91 92 93 |
# File 'lib/multi_db/connection_proxy.rb', line 86 def initialize(master, slaves) @slaves = Scheduler.new(slaves) @master = master @reconnect = false @config = master.connection.instance_variable_get(:@config) self.current = @slaves.current self.master_depth = 0 end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object
Calls the method on master/slave and dynamically creates a new method on success to speed up subsequent calls
114 115 116 117 118 |
# File 'lib/multi_db/connection_proxy.rb', line 114 def method_missing(method, *args, &block) returning(send(target_method(method), method, *args, &block)) do create_delegation_method!(method) end end |
Class Attribute Details
.environment ⇒ Object
defaults to RAILS_ENV if multi_db is used with Rails defaults to ‘development’ when used outside Rails
26 27 28 |
# File 'lib/multi_db/connection_proxy.rb', line 26 def environment @environment end |
.master_models ⇒ Object
a list of models that should always go directly to the master
Example:
MultiDb::ConnectionProxy.master_models = ['MySessionStore', 'PaymentTransaction']
33 34 35 |
# File 'lib/multi_db/connection_proxy.rb', line 33 def master_models @master_models end |
.sticky_slave ⇒ Object
decides if we should switch to the next reader automatically. If set to false, an after|before_filter in the ApplicationController has to do this. This will not affect failover if a master is unavailable.
39 40 41 |
# File 'lib/multi_db/connection_proxy.rb', line 39 def sticky_slave @sticky_slave end |
Instance Attribute Details
#master ⇒ Object
Returns the value of attribute master.
19 20 21 |
# File 'lib/multi_db/connection_proxy.rb', line 19 def master @master end |
Class Method Details
.setup! ⇒ Object
Replaces the connection of ActiveRecord::Base with a proxy and establishes the connections to the slaves.
43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/multi_db/connection_proxy.rb', line 43 def setup! self.master_models ||= DEFAULT_MASTER_MODELS self.environment ||= (defined?(RAILS_ENV) ? RAILS_ENV : 'development') self.sticky_slave ||= false master = ActiveRecord::Base slaves = init_slaves raise "No slaves databases defined for environment: #{self.environment}" if slaves.empty? master.send :include, MultiDb::ActiveRecordExtensions ActiveRecord::Observer.send :include, MultiDb::ObserverExtensions master.connection_proxy = new(master, slaves) master.logger.info("** multi_db with master and #{slaves.length} slave#{"s" if slaves.length > 1} loaded.") end |
Instance Method Details
#next_reader! ⇒ Object
Switches to the next slave database for read operations. Fails over to the master database if all slaves are unavailable.
122 123 124 125 126 127 128 |
# File 'lib/multi_db/connection_proxy.rb', line 122 def next_reader! return unless master_depth.zero? # don't if in with_master block self.current = @slaves.next rescue Scheduler::NoMoreItems logger.warn "[MULTIDB] All slaves are blacklisted. Reading from master" self.current = @master end |
#slave ⇒ Object
95 96 97 |
# File 'lib/multi_db/connection_proxy.rb', line 95 def slave @slaves.current end |
#transaction(start_db_transaction = true, &block) ⇒ Object
108 109 110 |
# File 'lib/multi_db/connection_proxy.rb', line 108 def transaction(start_db_transaction = true, &block) with_master { @master.retrieve_connection.transaction(start_db_transaction, &block) } end |
#with_master ⇒ Object
99 100 101 102 103 104 105 106 |
# File 'lib/multi_db/connection_proxy.rb', line 99 def with_master self.current = @master self.master_depth += 1 yield ensure self.master_depth -= 1 self.current = slave if master_depth.zero? end |