class Makara::Proxy
Constants
- METHOD_MISSING_SKIP
Attributes
config_parser[R]
control[R]
error_handler[R]
sticky[R]
Public Class Methods
control_method(*method_names)
click to toggle source
# File lib/makara/proxy.rb, line 46 def control_method(*method_names) self.control_methods = self.control_methods || [] self.control_methods |= method_names method_names.each do |method_name| define_method(method_name) do |*args, &block| control&.send(method_name, *args, &block) end ruby2_keywords method_name if Module.private_method_defined?(:ruby2_keywords) end end
hijack_method(*method_names)
click to toggle source
# File lib/makara/proxy.rb, line 21 def hijack_method(*method_names) self.hijack_methods = self.hijack_methods || [] self.hijack_methods |= method_names method_names.each do |method_name| define_method(method_name) do |*args, &block| appropriate_connection(method_name, args) do |con| con.send(method_name, *args, &block) end end ruby2_keywords method_name if Module.private_method_defined?(:ruby2_keywords) end end
new(config)
click to toggle source
Calls superclass method
# File lib/makara/proxy.rb, line 65 def initialize(config) @config = config.symbolize_keys @config_parser = Makara::ConfigParser.new(@config) @id = @config_parser.id @ttl = @config_parser.makara_config[:master_ttl] @sticky = @config_parser.makara_config[:sticky] @hijacked = false @error_handler ||= ::Makara::ErrorHandler.new @skip_sticking = false instantiate_connections super(config) end
send_to_all(*method_names)
click to toggle source
# File lib/makara/proxy.rb, line 36 def send_to_all(*method_names) method_names.each do |method_name| define_method(method_name) do |*args| send_to_all(method_name, *args) end ruby2_keywords method_name if Module.private_method_defined?(:ruby2_keywords) end end
Public Instance Methods
default_shard_for(role)
click to toggle source
# File lib/makara/proxy.rb, line 108 def default_shard_for(role) @config_parser.makara_config["#{role}_default_shard".to_sym] end
disconnect!()
click to toggle source
# File lib/makara/proxy.rb, line 156 def disconnect! send_to_all(:disconnect!) rescue ::Makara::Errors::AllConnectionsBlacklisted, ::Makara::Errors::NoConnectionsAvailable # all connections are already down, nothing to do here end
graceful_connection_for(config)
click to toggle source
# File lib/makara/proxy.rb, line 145 def graceful_connection_for(config) fake_wrapper = Makara::ConnectionWrapper.new(self, nil, config) @error_handler.handle(fake_wrapper) do connection_for(config) end rescue Makara::Errors::BlacklistConnection => e fake_wrapper.initial_error = e.original_error fake_wrapper end
hijacked?()
click to toggle source
# File lib/makara/proxy.rb, line 85 def hijacked? @hijacked end
method_missing(m, *args, &block)
click to toggle source
Calls superclass method
# File lib/makara/proxy.rb, line 123 def method_missing(m, *args, &block) if METHOD_MISSING_SKIP.include?(m) return super end any_connection do |con| if con.respond_to?(m, true) con.send(m, *args, &block) else super end end end
respond_to_missing?(m, include_private = false)
click to toggle source
# File lib/makara/proxy.rb, line 139 def respond_to_missing?(m, include_private = false) any_connection do |con| con._makara_connection.respond_to?(m, true) end end
shard_aware_for(role)
click to toggle source
# File lib/makara/proxy.rb, line 104 def shard_aware_for(role) @config_parser.makara_config["#{role}_shard_aware".to_sym] end
stick_to_master!(persist = true)
click to toggle source
If persist is true, we stick the proxy to master for subsequent requests up to master_ttl duration. Otherwise we just stick it for the current request
# File lib/makara/proxy.rb, line 91 def stick_to_master!(persist = true) stickiness_duration = persist ? @ttl : 0 Makara::Context.stick(@id, stickiness_duration) end
strategy_class_for(strategy_name)
click to toggle source
# File lib/makara/proxy.rb, line 112 def strategy_class_for(strategy_name) case strategy_name when 'round_robin', 'roundrobin', nil, '' ::Makara::Strategies::RoundRobin when 'failover' ::Makara::Strategies::PriorityFailover else strategy_name.constantize end end
strategy_for(role)
click to toggle source
# File lib/makara/proxy.rb, line 96 def strategy_for(role) strategy_class_for(strategy_name_for(role)).new(self) end
strategy_name_for(role)
click to toggle source
# File lib/makara/proxy.rb, line 100 def strategy_name_for(role) @config_parser.makara_config["#{role}_strategy".to_sym] end
without_sticking() { || ... }
click to toggle source
# File lib/makara/proxy.rb, line 78 def without_sticking @skip_sticking = true yield ensure @skip_sticking = false end
Protected Instance Methods
_appropriate_pool(method_name, args)
click to toggle source
# File lib/makara/proxy.rb, line 224 def _appropriate_pool(method_name, args) # the args provided absolutely need master if needs_master?(method_name, args) stick_to_master(method_name, args) @master_pool elsif stuck_to_master? # we're on master because we already stuck this proxy in this # request or because we got stuck in previous requests and the # stickiness is still valid @master_pool # all slaves are down (or empty) elsif @slave_pool.completely_blacklisted? stick_to_master(method_name, args) @master_pool elsif in_transaction? @master_pool # yay! use a slave else @slave_pool end end
any_connection() { |con| ... }
click to toggle source
# File lib/makara/proxy.rb, line 174 def any_connection if @master_pool.disabled @slave_pool.provide do |con| yield con end else @master_pool.provide do |con| yield con end end rescue ::Makara::Errors::AllConnectionsBlacklisted, ::Makara::Errors::NoConnectionsAvailable begin @master_pool.disabled = true @slave_pool.provide do |con| yield con end ensure @master_pool.disabled = false end end
appropriate_connection(method_name, args) { |connection| ... }
click to toggle source
based on the method_name and args, provide the appropriate connection mark this proxy as hijacked so the underlying connection does not attempt to check with back with this proxy.
# File lib/makara/proxy.rb, line 198 def appropriate_connection(method_name, args) appropriate_pool(method_name, args) do |pool| pool.provide do |connection| hijacked do yield connection end end end end
appropriate_pool(method_name, args) { |pool| ... }
click to toggle source
master or slave
# File lib/makara/proxy.rb, line 209 def appropriate_pool(method_name, args) # for testing purposes pool = _appropriate_pool(method_name, args) yield pool rescue ::Makara::Errors::AllConnectionsBlacklisted, ::Makara::Errors::NoConnectionsAvailable => e if pool == @master_pool @master_pool.connections.each(&:_makara_whitelist!) @slave_pool.connections.each(&:_makara_whitelist!) Kernel.raise e else @master_pool.blacklist_errors << e retry end end
connection_for(config)
click to toggle source
# File lib/makara/proxy.rb, line 325 def connection_for(config) Kernel.raise NotImplementedError end
handling_an_all_execution(method_name) { || ... }
click to toggle source
# File lib/makara/proxy.rb, line 311 def handling_an_all_execution(method_name) yield rescue ::Makara::Errors::NoConnectionsAvailable => e if e.role == 'master' # this means slave connections are good. return end @slave_pool.disabled = true yield ensure @slave_pool.disabled = false end
hijacked() { || ... }
click to toggle source
# File lib/makara/proxy.rb, line 264 def hijacked @hijacked = true yield ensure @hijacked = false end
in_transaction?()
click to toggle source
# File lib/makara/proxy.rb, line 256 def in_transaction? if respond_to?(:open_transactions) self.open_transactions > 0 else false end end
instantiate_connections()
click to toggle source
use the config parser to generate a master and slave pool
# File lib/makara/proxy.rb, line 295 def instantiate_connections @master_pool = Makara::Pool.new('master', self) @config_parser.master_configs.each do |master_config| @master_pool.add master_config do graceful_connection_for(master_config) end end @slave_pool = Makara::Pool.new('slave', self) @config_parser.slave_configs.each do |slave_config| @slave_pool.add slave_config do graceful_connection_for(slave_config) end end end
needs_master?(method_name, args)
click to toggle source
do these args require a master connection
# File lib/makara/proxy.rb, line 252 def needs_master?(method_name, args) true end
send_to_all(method_name, *args)
click to toggle source
# File lib/makara/proxy.rb, line 164 def send_to_all(method_name, *args) # slave pool must run first to allow for slave-->master failover without running operations on master twice. handling_an_all_execution(method_name) do @slave_pool.send_to_all(method_name, *args) @master_pool.send_to_all(method_name, *args) end end
should_stick?(method_name, args)
click to toggle source
For the generic proxy implementation, we stick if we are sticky, method and args don't matter
# File lib/makara/proxy.rb, line 285 def should_stick?(method_name, args) sticky? end
stick_to_master(method_name, args)
click to toggle source
# File lib/makara/proxy.rb, line 275 def stick_to_master(method_name, args) # check to see if we're configured, bypassed, or some custom implementation has input return unless should_stick?(method_name, args) # do the sticking stick_to_master! end
sticky?()
click to toggle source
If we are configured to be sticky and we aren't bypassing stickiness,
# File lib/makara/proxy.rb, line 290 def sticky? @sticky && !@skip_sticking end
stuck_to_master?()
click to toggle source
# File lib/makara/proxy.rb, line 271 def stuck_to_master? sticky? && Makara::Context.stuck?(@id) end