Module: ActiveRecordShards::ConnectionSwitcher
- Included in:
- ActiveRecord::Base
- Defined in:
- lib/active_record_shards/connection_switcher.rb,
lib/active_record_shards/connection_switcher-4-0.rb,
lib/active_record_shards/connection_switcher-5-0.rb,
lib/active_record_shards/connection_switcher-5-1.rb
Defined Under Namespace
Classes: MasterSlaveProxy
Constant Summary collapse
- SHARD_NAMES_CONFIG_KEY =
'shard_names'.freeze
Class Method Summary collapse
Instance Method Summary collapse
-
#connection_pool_name ⇒ Object
Name of the connection pool.
- #connection_specification_name ⇒ Object
- #current_shard_id ⇒ Object
- #current_shard_selection ⇒ Object
- #default_shard=(new_default_shard) ⇒ Object
- #on_all_shards ⇒ Object
- #on_cx_switch_block(which, force: false, construct_ro_scope: nil, &block) ⇒ Object
- #on_first_shard ⇒ Object
- #on_master(&block) ⇒ Object
- #on_master_if(condition, &block) ⇒ Object
- #on_master_or_slave(which, &block) ⇒ Object
- #on_master_unless(condition, &block) ⇒ Object
- #on_shard(shard) ⇒ Object
-
#on_slave(&block) ⇒ Object
(also: #with_slave)
Executes queries using the slave database.
- #on_slave? ⇒ Boolean
- #on_slave_if(condition, &block) ⇒ Object (also: #with_slave_if)
- #on_slave_unless(condition, &block) ⇒ Object (also: #with_slave_unless)
- #shard_names ⇒ Object
- #shards ⇒ Object
- #supports_sharding? ⇒ Boolean
Class Method Details
.extended(base) ⇒ Object
8 9 10 11 12 13 14 15 16 17 18 19 |
# File 'lib/active_record_shards/connection_switcher.rb', line 8 def self.extended(base) if ActiveRecord::VERSION::MAJOR >= 5 base.singleton_class.send(:alias_method, :load_schema_without_default_shard!, :load_schema!) base.singleton_class.send(:alias_method, :load_schema!, :load_schema_with_default_shard!) else base.singleton_class.send(:alias_method, :columns_without_default_shard, :columns) base.singleton_class.send(:alias_method, :columns, :columns_with_default_shard) end base.singleton_class.send(:alias_method, :table_exists_without_default_shard?, :table_exists?) base.singleton_class.send(:alias_method, :table_exists?, :table_exists_with_default_shard?) end |
Instance Method Details
#connection_pool_name ⇒ Object
Name of the connection pool. Used by ConnectionHandler to retrieve the current connection pool.
4 5 6 7 8 9 10 11 12 |
# File 'lib/active_record_shards/connection_switcher-4-0.rb', line 4 def connection_pool_name # :nodoc: name = current_shard_selection.shard_name(self) if configurations[name].nil? && on_slave? current_shard_selection.shard_name(self, false) else name end end |
#connection_specification_name ⇒ Object
3 4 5 6 7 8 9 10 11 |
# File 'lib/active_record_shards/connection_switcher-5-0.rb', line 3 def connection_specification_name name = current_shard_selection.resolve_connection_name(sharded: is_sharded?, configurations: configurations) unless configurations[name] || name == "primary" raise ActiveRecord::AdapterNotSpecified, "No database defined by #{name} in your database config. (configurations: #{configurations.keys.inspect})" end name end |
#current_shard_id ⇒ Object
136 137 138 |
# File 'lib/active_record_shards/connection_switcher.rb', line 136 def current_shard_id current_shard_selection.shard end |
#current_shard_selection ⇒ Object
132 133 134 |
# File 'lib/active_record_shards/connection_switcher.rb', line 132 def current_shard_selection Thread.current[:shard_selection] ||= ShardSelection.new end |
#default_shard=(new_default_shard) ⇒ Object
21 22 23 24 |
# File 'lib/active_record_shards/connection_switcher.rb', line 21 def default_shard=(new_default_shard) ActiveRecordShards::ShardSelection.default_shard = new_default_shard switch_connection(shard: new_default_shard) end |
#on_all_shards ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/active_record_shards/connection_switcher.rb', line 43 def on_all_shards = current_shard_selection. if supports_sharding? shard_names.map do |shard| switch_connection(shard: shard) yield(shard) end else [yield] end ensure switch_connection() end |
#on_cx_switch_block(which, force: false, construct_ro_scope: nil, &block) ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/active_record_shards/connection_switcher.rb', line 103 def on_cx_switch_block(which, force: false, construct_ro_scope: nil, &block) @disallow_slave ||= 0 @disallow_slave += 1 if which == :master switch_to_slave = force || @disallow_slave.zero? = current_shard_selection. switch_connection(slave: switch_to_slave) # we avoid_readonly_scope to prevent some stack overflow problems, like when # .columns calls .with_scope which calls .columns and onward, endlessly. if self == ActiveRecord::Base || !switch_to_slave || construct_ro_scope == false yield else readonly.scoping(&block) end ensure @disallow_slave -= 1 if which == :master switch_connection() if end |
#on_first_shard ⇒ Object
34 35 36 37 |
# File 'lib/active_record_shards/connection_switcher.rb', line 34 def on_first_shard shard_name = shard_names.first on_shard(shard_name) { yield } end |
#on_master(&block) ⇒ Object
94 95 96 |
# File 'lib/active_record_shards/connection_switcher.rb', line 94 def on_master(&block) on_master_or_slave(:master, &block) end |
#on_master_if(condition, &block) ⇒ Object
65 66 67 |
# File 'lib/active_record_shards/connection_switcher.rb', line 65 def on_master_if(condition, &block) condition ? on_master(&block) : yield end |
#on_master_or_slave(which, &block) ⇒ Object
73 74 75 76 77 78 79 |
# File 'lib/active_record_shards/connection_switcher.rb', line 73 def on_master_or_slave(which, &block) if block_given? on_cx_switch_block(which, &block) else MasterSlaveProxy.new(self, which) end end |
#on_master_unless(condition, &block) ⇒ Object
69 70 71 |
# File 'lib/active_record_shards/connection_switcher.rb', line 69 def on_master_unless(condition, &block) on_master_if(!condition, &block) end |
#on_shard(shard) ⇒ Object
26 27 28 29 30 31 32 |
# File 'lib/active_record_shards/connection_switcher.rb', line 26 def on_shard(shard) = current_shard_selection. switch_connection(shard: shard) if supports_sharding? yield ensure switch_connection() end |
#on_slave(&block) ⇒ Object Also known as: with_slave
Executes queries using the slave database. Fails over to master if no slave is found. if you want to execute a block of code on the slave you can go:
Account.on_slave do
Account.first
end
the first account will be found on the slave DB
For one-liners you can simply do
Account.on_slave.first
90 91 92 |
# File 'lib/active_record_shards/connection_switcher.rb', line 90 def on_slave(&block) on_master_or_slave(:slave, &block) end |
#on_slave? ⇒ Boolean
128 129 130 |
# File 'lib/active_record_shards/connection_switcher.rb', line 128 def on_slave? current_shard_selection.on_slave? end |
#on_slave_if(condition, &block) ⇒ Object Also known as: with_slave_if
57 58 59 |
# File 'lib/active_record_shards/connection_switcher.rb', line 57 def on_slave_if(condition, &block) condition ? on_slave(&block) : yield end |
#on_slave_unless(condition, &block) ⇒ Object Also known as: with_slave_unless
61 62 63 |
# File 'lib/active_record_shards/connection_switcher.rb', line 61 def on_slave_unless(condition, &block) on_slave_if(!condition, &block) end |
#shard_names ⇒ Object
140 141 142 143 144 145 146 147 148 |
# File 'lib/active_record_shards/connection_switcher.rb', line 140 def shard_names unless config = configurations[shard_env] raise "Did not find #{shard_env} in configurations, did you forget to add it to your database config? (configurations: #{configurations.keys.inspect})" end unless config.fetch(SHARD_NAMES_CONFIG_KEY, []).all? { |shard_name| shard_name.is_a?(Integer) } raise "All shard names must be integers: #{config[SHARD_NAMES_CONFIG_KEY].inspect}." end config[SHARD_NAMES_CONFIG_KEY] || [] end |
#shards ⇒ Object
39 40 41 |
# File 'lib/active_record_shards/connection_switcher.rb', line 39 def shards ShardSupport.new(self == ActiveRecord::Base ? nil : where(nil)) end |
#supports_sharding? ⇒ Boolean
124 125 126 |
# File 'lib/active_record_shards/connection_switcher.rb', line 124 def supports_sharding? shard_names.any? end |