class RedisCluster::Pool

Attributes

global_configs[R]
nodes[R]

Public Class Methods

new(global_configs = {}) click to toggle source
# File lib/redis_cluster/pool.rb, line 6
def initialize(global_configs = {})
  @nodes = []
  @global_configs = global_configs
end

Public Instance Methods

add_node!(node_options, slots) click to toggle source

TODO: type check

# File lib/redis_cluster/pool.rb, line 12
def add_node!(node_options, slots)
  new_node = Node.new(global_configs.merge(node_options))
  node = @nodes.find { |n| n.name == new_node.name } || new_node
  node.slots = slots
  @nodes.push(node).uniq!
end
delete_except!(master_hosts) click to toggle source
# File lib/redis_cluster/pool.rb, line 19
def delete_except!(master_hosts)
  names = master_hosts.map { |host, port| "#{host}:#{port}" }
  @nodes.delete_if { |n| !names.include?(n.name) }
end
execute(method, args, other_options, &block) click to toggle source

other_options:

asking
random_node
# File lib/redis_cluster/pool.rb, line 27
def execute(method, args, other_options, &block)
  return send(method, args, &block) if Configuration::SUPPORT_MULTI_NODE_METHODS.include?(method.to_s)

  key = key_by_command(method, args)
  raise CommandNotSupportedError.new(method.upcase) if key.nil?

  node = other_options[:random_node] ? random_node : node_by(key)
  node.asking if other_options[:asking]
  node.execute(method, args, &block)
end
keys(args, &block) click to toggle source
# File lib/redis_cluster/pool.rb, line 38
def keys(args, &block)
  glob = args.first
  on_each_node(:keys, glob).flatten
end
multi(args, &block) click to toggle source

Now mutli & pipelined conmand must control keys at same slot yourself You can use hash tag: '{foo}1'

# File lib/redis_cluster/pool.rb, line 49
def multi(args, &block)
  random_node.execute :multi, args, &block
end
pipelined(args, &block) click to toggle source
# File lib/redis_cluster/pool.rb, line 53
def pipelined(args, &block)
  random_node.execute :pipelined, args, &block
end
scan(args) click to toggle source

Implements scan across all nodes in the pool. Cursors will behave strangely if the node list changes during iteration.

# File lib/redis_cluster/pool.rb, line 59
def scan(args)
  scan_cursor = args.first
  options = args[1] || {}
  node_cursor, node_index = decode_scan_cursor(scan_cursor)
  next_node_cursor, result = @nodes[node_index].execute("scan", [node_cursor, options])
  [encode_next_scan_cursor(next_node_cursor, node_index), result]
end
script(args, &block) click to toggle source
# File lib/redis_cluster/pool.rb, line 43
def script(args, &block)
  on_each_node(:script, *args).flatten
end

Private Instance Methods

decode_scan_cursor(cursor) click to toggle source
# File lib/redis_cluster/pool.rb, line 80
def decode_scan_cursor(cursor)
  node_cursor, node_index = cursor.to_i.divmod(@nodes.size)
  [node_cursor.to_s, node_index] # Cursors are strings.
end
encode_next_scan_cursor(next_node_cursor, node_index) click to toggle source
# File lib/redis_cluster/pool.rb, line 69
def encode_next_scan_cursor(next_node_cursor, node_index)
  if next_node_cursor == '0'
    # '0' indicates the end of iteration.  Advance the node index and
    # start at the '0' position on the next node.  If this was the last node,
    # loop around and return '0' to indicate iteration is done.
    ((node_index + 1) % @nodes.size)
  else
    ((next_node_cursor.to_i * @nodes.size) + node_index)
  end.to_s # Cursors are strings
end
key_by_command(method, args) click to toggle source
# File lib/redis_cluster/pool.rb, line 94
def key_by_command(method, args)
  case method.to_s.downcase
  when 'info', 'exec', 'slaveof', 'config', 'shutdown'
    nil
  when 'eval', 'evalsha'
    if args[1].nil? || args[1].empty?
      raise KeysNotSpecifiedError.new(method.upcase)
    end

    unless Slot.at_one?(args[1])
      raise KeysNotAtSameSlotError.new(args[1])
    end

    return args[1][0]
  else
    return args.first
  end
end
node_by(key) click to toggle source
# File lib/redis_cluster/pool.rb, line 85
def node_by(key)
  slot = Slot.slot_by(key)
  @nodes.find { |node| node.has_slot?(slot) }
end
on_each_node(method, *args) click to toggle source
# File lib/redis_cluster/pool.rb, line 113
def on_each_node(method, *args)
  @nodes.map do |node|
    node.execute(method, args)
  end
end
random_node() click to toggle source
# File lib/redis_cluster/pool.rb, line 90
def random_node
  @nodes.sample
end