class Makara::ConnectionWrapper
Constants
- SQL_REPLACE
invalid queries caused by connections switching that needs to be replaced
Attributes
config[RW]
initial_error[RW]
Public Class Methods
new(proxy, connection, config)
click to toggle source
# File lib/makara/connection_wrapper.rb, line 15 def initialize(proxy, connection, config) @config = config.symbolize_keys @connection = connection @proxy = proxy if connection.nil? _makara_blacklist! else _makara_decorate_connection(connection) end end
Public Instance Methods
_makara_blacklist!()
click to toggle source
blacklist this node for @config seconds
# File lib/makara/connection_wrapper.rb, line 51 def _makara_blacklist! @connection.disconnect! if @connection @connection = nil @blacklisted_until = Time.now.to_i + @config[:blacklist_duration] unless @config[:disable_blacklist] end
_makara_blacklisted?()
click to toggle source
has this node been blacklisted?
# File lib/makara/connection_wrapper.rb, line 42 def _makara_blacklisted? @blacklisted_until.present? && @blacklisted_until.to_i > Time.now.to_i end
_makara_connected?()
click to toggle source
# File lib/makara/connection_wrapper.rb, line 67 def _makara_connected? _makara_connection.present? rescue Makara::Errors::BlacklistConnection false end
_makara_connection()
click to toggle source
# File lib/makara/connection_wrapper.rb, line 73 def _makara_connection current = @connection if current current else # blacklisted connection or initial error new_connection = @proxy.graceful_connection_for(@config) # Already wrapped because of initial failure if new_connection.is_a?(Makara::ConnectionWrapper) _makara_blacklist! raise Makara::Errors::BlacklistConnection.new(self, new_connection.initial_error) else @connection = new_connection _makara_decorate_connection(new_connection) new_connection end end end
_makara_custom_error_matchers()
click to toggle source
custom error messages
# File lib/makara/connection_wrapper.rb, line 63 def _makara_custom_error_matchers @custom_error_matchers ||= (@config[:connection_error_matchers] || []) end
_makara_in_transaction?()
click to toggle source
# File lib/makara/connection_wrapper.rb, line 46 def _makara_in_transaction? @connection && @connection.open_transactions > 0 end
_makara_name()
click to toggle source
the name of this node
# File lib/makara/connection_wrapper.rb, line 33 def _makara_name @config[:name] end
_makara_shard_id()
click to toggle source
# File lib/makara/connection_wrapper.rb, line 37 def _makara_shard_id @config[:shard_id] end
_makara_weight()
click to toggle source
the weight of the current node
# File lib/makara/connection_wrapper.rb, line 28 def _makara_weight @config[:weight] || 1 end
_makara_whitelist!()
click to toggle source
release the blacklist
# File lib/makara/connection_wrapper.rb, line 58 def _makara_whitelist! @blacklisted_until = nil end
execute(*args)
click to toggle source
# File lib/makara/connection_wrapper.rb, line 93 def execute(*args) SQL_REPLACE.each do |find, replace| if args[0] == find args[0] = replace end end _makara_connection.execute(*args) end
method_missing(m, *args, &block)
click to toggle source
we want to forward all private methods, since we could have kicked out from a private scenario
# File lib/makara/connection_wrapper.rb, line 104 def method_missing(m, *args, &block) _makara_connection.send(m, *args, &block) end
respond_to_missing?(m, include_private = false)
click to toggle source
# File lib/makara/connection_wrapper.rb, line 110 def respond_to_missing?(m, include_private = false) _makara_connection.respond_to?(m, true) end
Protected Instance Methods
_makara_decorate_connection(con)
click to toggle source
once the underlying connection is present we must evaluate extra functionality into it. all extra functionality is in the format of _makara*
# File lib/makara/connection_wrapper.rb, line 118 def _makara_decorate_connection(con) extension = <<~RUBY # the proxy object controlling this connection def _makara @_makara end def _makara=(m) @_makara = m end # if the proxy has already decided the correct connection to use, yield nil. # if the proxy has yet to decide, yield the proxy def _makara_hijack if _makara.hijacked? yield nil else yield _makara end end # for logging, errors, and debugging def _makara_name #{@config[:name].inspect} end RUBY args = RUBY_VERSION >= "3.0.0" ? "..." : "*args, &block" # Each method the Makara::Proxy needs to hijack should be redefined in the underlying connection. # The new definition should allow for the proxy to intercept the invocation if required. @proxy.class.hijack_methods.each do |meth| method_call = RUBY_VERSION >= "3.0.0" ? "public_send(#{meth.inspect}, ...)" : "#{meth}(*args, &block)" extension << <<~RUBY def #{meth}(#{args}) _makara_hijack do |proxy| if proxy proxy.#{method_call} else super end end end RUBY end # Control methods must always be passed to the # Makara::Proxy control object for handling (typically # related to ActiveRecord connection pool management) @proxy.class.control_methods.each do |meth| method_call = RUBY_VERSION >= "3.0.0" ? "public_send(#{meth.inspect}, ...)" : "#{meth}(*args=args, block)" extension << <<~RUBY def #{meth}(#{args}) proxy = _makara if proxy proxy.control.#{method_call} else super # Only if we are not wrapped any longer end end RUBY end # extend the instance con.instance_eval(extension, __FILE__, __LINE__ + 1) # set the makara context con._makara = @proxy con._makara end