Class: SlavePoolsModule::ConnectionProxy
- Inherits:
-
Object
- Object
- SlavePoolsModule::ConnectionProxy
- Includes:
- ActiveRecord::ConnectionAdapters::QueryCache, QueryCacheCompat
- Defined in:
- lib/slave_pools/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.
Set.new([ :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
-
.config ⇒ Object
#setting a config instance variable so that thinking sphinx,and other gems that use the connection.instance_variable_get(:@config), work correctly.
-
.defaults_to_master ⇒ Object
if master should be the default db.
-
.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.
Instance Attribute Summary collapse
-
#current ⇒ Object
Returns the value of attribute current.
-
#current_pool ⇒ Object
Returns the value of attribute current_pool.
-
#master ⇒ Object
Returns the value of attribute master.
-
#master_depth ⇒ Object
Returns the value of attribute master_depth.
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
- #default_pool ⇒ Object
-
#initialize(master, slave_pools) ⇒ ConnectionProxy
constructor
end class << self.
-
#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_slave! ⇒ Object
Switches to the next slave database for read operations.
- #slave ⇒ Object
- #slave_pools ⇒ Object
- #transaction(start_db_transaction = true, &block) ⇒ Object
- #with_master ⇒ Object
- #with_pool(pool_name = 'default') ⇒ Object
- #within_master_block? ⇒ Boolean
Methods included from QueryCacheCompat
#delete, #insert, #query_cache_enabled, #select_all, #update
Constructor Details
#initialize(master, slave_pools) ⇒ ConnectionProxy
end class << self
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/slave_pools/connection_proxy.rb', line 83 def initialize(master, slave_pools) @slave_pools = {} slave_pools.each do |pool_name, slaves| @slave_pools[pool_name.to_sym] = SlavePool.new(pool_name, slaves) end @master = master @reconnect = false @current_pool = default_pool if self.class.defaults_to_master @current = @master @master_depth = 1 @config = master.connection.instance_variable_get(:@config) else @current = slave @master_depth = 0 @config = @current.config_hash #setting this end 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
144 145 146 147 148 |
# File 'lib/slave_pools/connection_proxy.rb', line 144 def method_missing(method, *args, &block) send(target_method(method), method, *args, &block).tap do create_delegation_method!(method) end end |
Class Attribute Details
.config ⇒ Object
#setting a config instance variable so that thinking sphinx,and other gems that use the connection.instance_variable_get(:@config), work correctly
44 45 46 |
# File 'lib/slave_pools/connection_proxy.rb', line 44 def config @config end |
.defaults_to_master ⇒ Object
if master should be the default db
41 42 43 |
# File 'lib/slave_pools/connection_proxy.rb', line 41 def defaults_to_master @defaults_to_master end |
.environment ⇒ Object
defaults to Rails.env if multi_db is used with Rails defaults to ‘development’ when used outside Rails
28 29 30 |
# File 'lib/slave_pools/connection_proxy.rb', line 28 def environment @environment end |
.master_models ⇒ Object
a list of models that should always go directly to the master
Example:
SlavePool::ConnectionProxy.master_models = ['MySessionStore', 'PaymentTransaction']
35 36 37 |
# File 'lib/slave_pools/connection_proxy.rb', line 35 def master_models @master_models end |
Instance Attribute Details
#current ⇒ Object
Returns the value of attribute current.
22 23 24 |
# File 'lib/slave_pools/connection_proxy.rb', line 22 def current @current end |
#current_pool ⇒ Object
Returns the value of attribute current_pool.
22 23 24 |
# File 'lib/slave_pools/connection_proxy.rb', line 22 def current_pool @current_pool end |
#master ⇒ Object
Returns the value of attribute master.
21 22 23 |
# File 'lib/slave_pools/connection_proxy.rb', line 21 def master @master end |
#master_depth ⇒ Object
Returns the value of attribute master_depth.
22 23 24 |
# File 'lib/slave_pools/connection_proxy.rb', line 22 def master_depth @master_depth end |
Class Method Details
.setup! ⇒ Object
Replaces the connection of ActiveRecord::Base with a proxy and establishes the connections to the slaves.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/slave_pools/connection_proxy.rb', line 48 def setup! self.master_models ||= DEFAULT_MASTER_MODELS self.environment ||= (defined?(Rails.env) ? Rails.env : 'development') slave_pools = init_slave_pools # if there are no slave pools, we just want to silently exit and not edit the ActiveRecord::Base.connection if !slave_pools.empty? master = ActiveRecord::Base master.send :include, SlavePoolsModule::ActiveRecordExtensions ActiveRecord::Observer.send :include, SlavePoolsModule::ObserverExtensions master.connection_proxy = new(master, slave_pools) master.logger.info("** slave_pools with master and #{slave_pools.length} slave_pool#{"s" if slave_pools.length > 1} (#{slave_pools.keys}) loaded.") else ActiveRecord::Base.logger.info(" No Slave Pools specified for this environment") #this is currently not logging end end |
Instance Method Details
#default_pool ⇒ Object
103 104 105 |
# File 'lib/slave_pools/connection_proxy.rb', line 103 def default_pool @slave_pools[:default] || @slave_pools.values.first #if there is no default specified, use the first pool found end |
#next_slave! ⇒ Object
Switches to the next slave database for read operations. Fails over to the master database if all slaves are unavailable.
152 153 154 155 156 157 |
# File 'lib/slave_pools/connection_proxy.rb', line 152 def next_slave! return if within_master_block? # don't if in with_master block @current = @current_pool.next rescue @current = @master end |
#slave ⇒ Object
111 112 113 |
# File 'lib/slave_pools/connection_proxy.rb', line 111 def slave @current_pool.current end |
#slave_pools ⇒ Object
107 108 109 |
# File 'lib/slave_pools/connection_proxy.rb', line 107 def slave_pools @slave_pools end |
#transaction(start_db_transaction = true, &block) ⇒ Object
138 139 140 |
# File 'lib/slave_pools/connection_proxy.rb', line 138 def transaction(start_db_transaction = true, &block) with_master { @master.retrieve_connection.transaction(start_db_transaction, &block) } end |
#with_master ⇒ Object
124 125 126 127 128 129 130 131 132 |
# File 'lib/slave_pools/connection_proxy.rb', line 124 def with_master @current = @master @master_depth += 1 yield ensure @master_depth -= 1 @master_depth = 0 if @master_depth < 0 # ensure that master depth never gets below 0 @current = slave if !within_master_block? end |
#with_pool(pool_name = 'default') ⇒ Object
115 116 117 118 119 120 121 122 |
# File 'lib/slave_pools/connection_proxy.rb', line 115 def with_pool(pool_name = 'default') @current_pool = @slave_pools[pool_name.to_sym] || default_pool @current = slave unless within_master_block? yield ensure @current_pool = default_pool @current = slave unless within_master_block? end |
#within_master_block? ⇒ Boolean
134 135 136 |
# File 'lib/slave_pools/connection_proxy.rb', line 134 def within_master_block? @master_depth > 0 end |