class ReplicaPools::ConnectionProxy

Attributes

current[RW]
current_pool[RW]
leader[RW]
leader_depth[RW]
replica_pools[RW]

Public Class Methods

generate_safe_delegations() click to toggle source
# File lib/replica_pools/connection_proxy.rb, line 12
def generate_safe_delegations
  ReplicaPools.config.safe_methods.each do |method|
    generate_safe_delegation(method) unless instance_methods.include?(method)
  end
end
new(leader, pools) click to toggle source
# File lib/replica_pools/connection_proxy.rb, line 29
def initialize(leader, pools)
  @leader       = leader
  @replica_pools  = pools
  @leader_depth = 0
  @current_pool = default_pool

  if ReplicaPools.config.defaults_to_leader
    @current = leader
  else
    @current = current_replica
  end

  # this ivar is for ConnectionAdapter compatibility
  # some gems (e.g. newrelic_rpm) will actually use
  # instance_variable_get(:@config) to find it.
  @config = current.connection_config
end

Protected Class Methods

generate_safe_delegation(method) click to toggle source
# File lib/replica_pools/connection_proxy.rb, line 20
      def generate_safe_delegation(method)
        class_eval <<-END, __FILE__, __LINE__ + 1
          def #{method}(*args, &block)
            route_to(current, :#{method}, *args, &block)
          end
        END
      end

Public Instance Methods

current_replica() click to toggle source
# File lib/replica_pools/connection_proxy.rb, line 80
def current_replica
  current_pool.current
end
next_replica!() click to toggle source
# File lib/replica_pools/connection_proxy.rb, line 75
def next_replica!
  return if within_leader_block?
  self.current = current_pool.next
end
transaction(*args, &block) click to toggle source
# File lib/replica_pools/connection_proxy.rb, line 71
def transaction(*args, &block)
  with_leader { leader.transaction(*args, &block) }
end
with_leader() { || ... } click to toggle source
# File lib/replica_pools/connection_proxy.rb, line 57
def with_leader
  raise LeaderDisabled.new if ReplicaPools.config.disable_leader

  last_conn = self.current
  self.current = leader
  self.leader_depth += 1
  yield
ensure
  if last_conn
    self.leader_depth = [leader_depth - 1, 0].max
    self.current = last_conn
  end
end
with_pool(pool_name = 'default') { || ... } click to toggle source
# File lib/replica_pools/connection_proxy.rb, line 47
def with_pool(pool_name = 'default')
  last_conn, last_pool = self.current, self.current_pool
  self.current_pool = replica_pools[pool_name.to_sym] || default_pool
  self.current = current_replica unless within_leader_block?
  yield
ensure
  self.current_pool = last_pool
  self.current      = last_conn
end

Protected Instance Methods

default_pool() click to toggle source
# File lib/replica_pools/connection_proxy.rb, line 86
def default_pool
  replica_pools[:default] || replica_pools.values.first
end
generate_unsafe_delegation(method) click to toggle source
# File lib/replica_pools/connection_proxy.rb, line 102
    def generate_unsafe_delegation(method)
      self.class_eval <<-END, __FILE__, __LINE__ + 1
        def #{method}(*args, &block)
          route_to(leader, :#{method}, *args, &block)
        end
      END
    end
method_missing(method, *args, &block) click to toggle source

Proxies any unknown methods to leader. Safe methods have been generated during `setup!`. Creates a method to speed up subsequent calls.

# File lib/replica_pools/connection_proxy.rb, line 93
def method_missing(method, *args, &block)
  generate_unsafe_delegation(method)
  send(method, *args, &block)
end
route_to(conn, method, *args, &block) click to toggle source
# File lib/replica_pools/connection_proxy.rb, line 110
def route_to(conn, method, *args, &block)
  raise ReplicaPools::LeaderDisabled.new if ReplicaPools.config.disable_leader && conn == leader
  conn.retrieve_connection.send(method, *args, &block)
rescue => e
  ReplicaPools.log :error, "Error during ##{method}: #{e}"
  log_proxy_state
  raise e
end
within_leader_block?() click to toggle source
# File lib/replica_pools/connection_proxy.rb, line 98
def within_leader_block?
  leader_depth > 0
end

Private Instance Methods

log_proxy_state() click to toggle source
# File lib/replica_pools/connection_proxy.rb, line 121
def log_proxy_state
  ReplicaPools.log :error, "Current Connection: #{current}"
  ReplicaPools.log :error, "Current Pool Name: #{current_pool.name}"
  ReplicaPools.log :error, "Current Pool Members: #{current_pool.replicas}"
  ReplicaPools.log :error, "Leader Depth: #{leader_depth}"
end