Module: ActiveRecordShards::ConnectionSwitcher
- Defined in:
- lib/active_record_shards/connection_switcher.rb,
lib/active_record_shards/connection_switcher-4-2.rb,
lib/active_record_shards/connection_switcher-5-0.rb,
lib/active_record_shards/connection_switcher-5-1.rb,
lib/active_record_shards/connection_switcher-6-0.rb
Defined Under Namespace
Classes: PrimaryReplicaProxy
Constant Summary collapse
- SHARD_NAMES_CONFIG_KEY =
'shard_names'
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(&block) ⇒ Object
- #on_primary(&block) ⇒ Object (also: #on_master)
- #on_primary_db(&block) ⇒ Object
- #on_primary_if(condition, &block) ⇒ Object (also: #on_master_if)
- #on_primary_or_replica(which, &block) ⇒ Object (also: #on_master_or_slave)
- #on_primary_unless(condition, &block) ⇒ Object (also: #on_master_unless)
-
#on_replica(&block) ⇒ Object
(also: #on_slave, #with_slave)
Executes queries using the replica database.
- #on_replica? ⇒ Boolean (also: #on_slave?)
- #on_replica_if(condition, &block) ⇒ Object (also: #on_slave_if, #with_slave_if)
- #on_replica_unless(condition, &block) ⇒ Object (also: #on_slave_unless, #with_slave_unless)
- #on_shard(shard) ⇒ Object
- #shard_names ⇒ Object
- #shards ⇒ Object
- #supports_sharding? ⇒ Boolean
Class Method Details
.extended(base) ⇒ Object
9 10 11 12 13 14 15 16 17 18 19 20 |
# File 'lib/active_record_shards/connection_switcher.rb', line 9 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 13 |
# File 'lib/active_record_shards/connection_switcher-4-2.rb', line 4 def connection_pool_name # :nodoc: name = current_shard_selection.shard_name(self) # e.g. if "production_replica" is not defined in `Configuration`, fall back to "production" if configurations[name].nil? && on_replica? 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.to_h.keys.inspect})" end name end |
#current_shard_id ⇒ Object
151 152 153 |
# File 'lib/active_record_shards/connection_switcher.rb', line 151 def current_shard_id current_shard_selection.shard end |
#current_shard_selection ⇒ Object
147 148 149 |
# File 'lib/active_record_shards/connection_switcher.rb', line 147 def current_shard_selection Thread.current[:shard_selection] ||= ShardSelection.new end |
#default_shard=(new_default_shard) ⇒ Object
22 23 24 25 |
# File 'lib/active_record_shards/connection_switcher.rb', line 22 def default_shard=(new_default_shard) ActiveRecordShards::ShardSelection.default_shard = new_default_shard switch_connection(shard: new_default_shard) end |
#on_all_shards ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/active_record_shards/connection_switcher.rb', line 48 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
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/active_record_shards/connection_switcher.rb', line 115 def on_cx_switch_block(which, force: false, construct_ro_scope: nil, &block) @disallow_replica ||= 0 @disallow_replica += 1 if [:primary, :master].include?(which) ActiveRecordShards::Deprecation.warn('the `:master` option should be replaced with `:primary`!') if which == :master switch_to_replica = force || @disallow_replica.zero? = current_shard_selection. switch_connection(replica: switch_to_replica) # 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_replica || construct_ro_scope == false || ActiveRecordShards.disable_replica_readonly_records == true yield else readonly.scoping(&block) end ensure @disallow_replica -= 1 if [:primary, :master].include?(which) switch_connection() if end |
#on_first_shard(&block) ⇒ Object
39 40 41 42 |
# File 'lib/active_record_shards/connection_switcher.rb', line 39 def on_first_shard(&block) shard_name = shard_names.first on_shard(shard_name, &block) end |
#on_primary(&block) ⇒ Object Also known as: on_master
105 106 107 |
# File 'lib/active_record_shards/connection_switcher.rb', line 105 def on_primary(&block) on_primary_or_replica(:primary, &block) end |
#on_primary_db(&block) ⇒ Object
27 28 29 |
# File 'lib/active_record_shards/connection_switcher.rb', line 27 def on_primary_db(&block) on_shard(nil, &block) end |
#on_primary_if(condition, &block) ⇒ Object Also known as: on_master_if
72 73 74 |
# File 'lib/active_record_shards/connection_switcher.rb', line 72 def on_primary_if(condition, &block) condition ? on_primary(&block) : yield end |
#on_primary_or_replica(which, &block) ⇒ Object Also known as: on_master_or_slave
82 83 84 85 86 87 88 |
# File 'lib/active_record_shards/connection_switcher.rb', line 82 def on_primary_or_replica(which, &block) if block_given? on_cx_switch_block(which, &block) else PrimaryReplicaProxy.new(self, which) end end |
#on_primary_unless(condition, &block) ⇒ Object Also known as: on_master_unless
77 78 79 |
# File 'lib/active_record_shards/connection_switcher.rb', line 77 def on_primary_unless(condition, &block) on_primary_if(!condition, &block) end |
#on_replica(&block) ⇒ Object Also known as: on_slave, with_slave
Executes queries using the replica database. Fails over to primary if no replica is found. if you want to execute a block of code on the replica you can go:
Account.on_replica do
Account.first
end
the first account will be found on the replica DB
For one-liners you can simply do
Account.on_replica.first
100 101 102 |
# File 'lib/active_record_shards/connection_switcher.rb', line 100 def on_replica(&block) on_primary_or_replica(:replica, &block) end |
#on_replica? ⇒ Boolean Also known as: on_slave?
142 143 144 |
# File 'lib/active_record_shards/connection_switcher.rb', line 142 def on_replica? current_shard_selection.on_replica? end |
#on_replica_if(condition, &block) ⇒ Object Also known as: on_slave_if, with_slave_if
62 63 64 |
# File 'lib/active_record_shards/connection_switcher.rb', line 62 def on_replica_if(condition, &block) condition ? on_replica(&block) : yield end |
#on_replica_unless(condition, &block) ⇒ Object Also known as: on_slave_unless, with_slave_unless
67 68 69 |
# File 'lib/active_record_shards/connection_switcher.rb', line 67 def on_replica_unless(condition, &block) on_replica_if(!condition, &block) end |
#on_shard(shard) ⇒ Object
31 32 33 34 35 36 37 |
# File 'lib/active_record_shards/connection_switcher.rb', line 31 def on_shard(shard) = current_shard_selection. switch_connection(shard: shard) if supports_sharding? yield ensure switch_connection() end |
#shard_names ⇒ Object
155 156 157 158 159 160 161 |
# File 'lib/active_record_shards/connection_switcher.rb', line 155 def shard_names unless config_for_env.fetch(SHARD_NAMES_CONFIG_KEY, []).all? { |shard_name| shard_name.is_a?(Integer) } raise "All shard names must be integers: #{config_for_env[SHARD_NAMES_CONFIG_KEY].inspect}." end config_for_env[SHARD_NAMES_CONFIG_KEY] || [] end |
#shards ⇒ Object
44 45 46 |
# File 'lib/active_record_shards/connection_switcher.rb', line 44 def shards ShardSupport.new(self == ActiveRecord::Base ? nil : where(nil)) end |
#supports_sharding? ⇒ Boolean
138 139 140 |
# File 'lib/active_record_shards/connection_switcher.rb', line 138 def supports_sharding? shard_names.any? end |