module ActiveRecordShards::ConnectionSwitcher
Constants
- MasterSlaveProxy
- SHARD_NAMES_CONFIG_KEY
Public Class Methods
extended(base)
click to toggle source
# 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
Public Instance Methods
connection_specification_name()
click to toggle source
# 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()
click to toggle source
# File lib/active_record_shards/connection_switcher.rb, line 151 def current_shard_id current_shard_selection.shard end
current_shard_selection()
click to toggle source
# 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)
click to toggle source
# 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() { |shard| ... }
click to toggle source
# File lib/active_record_shards/connection_switcher.rb, line 48 def on_all_shards old_options = current_shard_selection.options if supports_sharding? shard_names.map do |shard| switch_connection(shard: shard) yield(shard) end else [yield] end ensure switch_connection(old_options) end
on_cx_switch_block(which, force: false, construct_ro_scope: nil) { || ... }
click to toggle source
# 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? old_options = current_shard_selection.options 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 yield else readonly.scoping(&block) end ensure @disallow_replica -= 1 if [:primary, :master].include?(which) switch_connection(old_options) if old_options end
on_first_shard(&block)
click to toggle source
# 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)
click to toggle source
# File lib/active_record_shards/connection_switcher.rb, line 105 def on_primary(&block) on_primary_or_replica(:primary, &block) end
Also aliased as: on_master
on_primary_db(&block)
click to toggle source
# File lib/active_record_shards/connection_switcher.rb, line 27 def on_primary_db(&block) on_shard(nil, &block) end
on_primary_if(condition) { || ... }
click to toggle source
# File lib/active_record_shards/connection_switcher.rb, line 72 def on_primary_if(condition, &block) condition ? on_primary(&block) : yield end
Also aliased as: on_master_if
on_primary_or_replica(which, &block)
click to toggle source
# 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
Also aliased as: on_master_or_slave
on_primary_unless(condition, &block)
click to toggle source
# File lib/active_record_shards/connection_switcher.rb, line 77 def on_primary_unless(condition, &block) on_primary_if(!condition, &block) end
Also aliased as: on_master_unless
on_replica(&block)
click to toggle source
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
# File lib/active_record_shards/connection_switcher.rb, line 100 def on_replica(&block) on_primary_or_replica(:replica, &block) end
Also aliased as: on_slave, with_slave
on_replica?()
click to toggle source
# File lib/active_record_shards/connection_switcher.rb, line 142 def on_replica? current_shard_selection.on_replica? end
Also aliased as: on_slave?
on_replica_if(condition) { || ... }
click to toggle source
# File lib/active_record_shards/connection_switcher.rb, line 62 def on_replica_if(condition, &block) condition ? on_replica(&block) : yield end
Also aliased as: on_slave_if, with_slave_if
on_replica_unless(condition, &block)
click to toggle source
# File lib/active_record_shards/connection_switcher.rb, line 67 def on_replica_unless(condition, &block) on_replica_if(!condition, &block) end
Also aliased as: on_slave_unless, with_slave_unless
on_shard(shard) { || ... }
click to toggle source
# File lib/active_record_shards/connection_switcher.rb, line 31 def on_shard(shard) old_options = current_shard_selection.options switch_connection(shard: shard) if supports_sharding? yield ensure switch_connection(old_options) end
shard_names()
click to toggle source
# 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()
click to toggle source
# File lib/active_record_shards/connection_switcher.rb, line 44 def shards ShardSupport.new(self == ActiveRecord::Base ? nil : where(nil)) end
supports_sharding?()
click to toggle source
# File lib/active_record_shards/connection_switcher.rb, line 138 def supports_sharding? shard_names.any? end
with_slave(&block)
just to ease the transition from replica to active_record_shards
Alias for: on_replica
Private Instance Methods
clear_specification_cache()
click to toggle source
Helper method to clear global state when testing.
# File lib/active_record_shards/connection_switcher-4-2.rb, line 42 def clear_specification_cache @@specification_cache = {} end
columns_with_default_shard()
click to toggle source
# File lib/active_record_shards/connection_switcher.rb, line 212 def columns_with_default_shard with_default_shard { columns_without_default_shard } end
config_for_env()
click to toggle source
# File lib/active_record_shards/connection_switcher.rb, line 165 def config_for_env @_ars_config_for_env ||= {} @_ars_config_for_env[shard_env] ||= begin 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.to_h.keys.inspect})" end config end end
Also aliased as: check_config_for_env
connected_to_shard?()
click to toggle source
# File lib/active_record_shards/connection_switcher-4-2.rb, line 50 def connected_to_shard? specs_to_pools = Hash[connection_handler.connection_pool_list.map { |pool| [pool.spec, pool] }] specs_to_pools.key?(connection_pool_key) end
connection_pool_key()
click to toggle source
# File lib/active_record_shards/connection_switcher-4-2.rb, line 46 def connection_pool_key specification_cache[connection_pool_name] end
ensure_shard_connection()
click to toggle source
# File lib/active_record_shards/connection_switcher-4-2.rb, line 17 def ensure_shard_connection establish_shard_connection unless connected_to_shard? end
establish_shard_connection()
click to toggle source
# File lib/active_record_shards/connection_switcher-4-2.rb, line 21 def establish_shard_connection name = connection_pool_name spec = configurations[name] if spec.nil? raise ActiveRecord::AdapterNotSpecified, "No database defined by #{name} in your database config. (configurations: #{configurations.keys.inspect})" end specification_cache[name] ||= begin resolver = ActiveRecordShards::ConnectionSpecification::Resolver.new configurations resolver.spec(spec) end connection_handler.establish_connection(self, specification_cache[name]) end
load_schema_with_default_shard!()
click to toggle source
# File lib/active_record_shards/connection_switcher.rb, line 208 def load_schema_with_default_shard! with_default_shard { load_schema_without_default_shard! } end
shard_env()
click to toggle source
# File lib/active_record_shards/connection_switcher.rb, line 193 def shard_env ActiveRecordShards.rails_env end
specification_cache()
click to toggle source
# File lib/active_record_shards/connection_switcher-4-2.rb, line 37 def specification_cache @@specification_cache ||= {} end
switch_connection(options)
click to toggle source
# File lib/active_record_shards/connection_switcher.rb, line 177 def switch_connection(options) if options.any? if options.key?(:replica) current_shard_selection.on_replica = options[:replica] end if options.key?(:shard) check_config_for_env current_shard_selection.shard = options[:shard] end ensure_shard_connection end end
table_exists_with_default_shard?()
click to toggle source
# File lib/active_record_shards/connection_switcher.rb, line 217 def table_exists_with_default_shard? with_default_shard { table_exists_without_default_shard? } end
with_default_shard() { || ... }
click to toggle source
Make these few schema related methods available before having switched to a shard.
# File lib/active_record_shards/connection_switcher.rb, line 199 def with_default_shard(&block) if is_sharded? && current_shard_id.nil? && table_name != ActiveRecord::SchemaMigration.table_name on_first_shard(&block) else yield end end