Class: Renoir::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/renoir/client.rb

Constant Summary collapse

REDIS_CLUSTER_HASH_SLOTS =
16_384
DEFAULT_OPTIONS =
{
  cluster_nodes: [
    ["127.0.0.1", 6379]
  ],
  max_redirection: 10,
  max_connection_error: 5,
  connect_retry_random_factor: 0.1,
  connect_retry_interval: 0.001, # 1 ms
  connection_adapter: :redis,
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ Client

Returns a new instance of Client.

Parameters:

  • options (Hash)

    a customizable set of options

Options Hash (options):

  • :cluster_nodes (Array<String, Array<String, Fixnum>, Hash{String => Fixnum}>)

    Array of hostnames and ports of cluster nodes. At least one node must be specified. An element could be one of: String ("127.0.0.1:6379"), Array (["127.0.0.1", 6379]) or Hash ({ host: "127.0.0.1", port: 6379 }). Defaults to [["127.0.0.1", 6379]].

  • :max_redirection (Fixnum)

    Max number of MOVED/ASK redirections. Defaults to 10.

  • :max_connection_error (Fixnum)

    Max number of reconnections for connection errors. Defaults to 5.

  • :connect_retry_random_factor (Float)

    A factor of reconnection interval. Defaults to 0.1.

  • :connect_retry_interval (Float)

    A base interval (seconds) of reconnection. Defaults to 0.001, i.e., 1 ms.

  • :connection_adapter (String, Symbol)

    Adapter name of a connection used by client. Defaults to :redis.

  • :logger (Logger)

    A logger. Defaults to nil.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/renoir/client.rb', line 36

def initialize(options)
  @connections = {}
  @cluster_info = ClusterInfo.new
  @refresh_slots = true

  options = options.map { |k, v| [k.to_sym, v] }.to_h
  @options = DEFAULT_OPTIONS.merge(options)
  @logger = @options[:logger]
  @adapter_class = ConnectionAdapters.const_get(@options[:connection_adapter].to_s.capitalize)

  cluster_nodes = @options.delete(:cluster_nodes)
  fail "the cluster_nodes option must contain at least one node" if cluster_nodes.empty?
  cluster_nodes.each do |node|
    host, port = case node
                 when Array
                   node
                 when Hash
                   [node[:host], node[:port]]
                 when String
                   node.split(":")
                 else
                   fail "invalid entry in cluster_nodes option: #{node}"
                 end
    port ||= 6379
    @cluster_info.add_node(host, port.to_i)
  end

  @connections_mutex = Mutex.new
  @refresh_slots_mutex = Mutex.new
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(command, *args, &block) ⇒ Object

Delegated to #call.



142
143
144
# File 'lib/renoir/client.rb', line 142

def method_missing(command, *args, &block)
  call(command, *args, &block)
end

Instance Method Details

#call(*command) {|Object| ... } ⇒ Object

Call a Redis command.

Parameters:

  • command (Array)

    a Redis command passed to a connection backend

Yields:

  • (Object)

    a connection backend may yield

Returns:

  • the value returned by a connection backend

Raises:



111
112
113
114
115
116
# File 'lib/renoir/client.rb', line 111

def call(*command, &block)
  slot = get_slot_from_commands([command])

  refresh_slots
  call_with_redirection(slot, [command], &block)[0]
end

#closeObject

Close all holding connections.



119
120
121
122
123
# File 'lib/renoir/client.rb', line 119

def close
  while entry = @connections.shift
    entry[1].close
  end
end

#each_node {|Object| ... } ⇒ Enumerable

Enumerate connections of cluster nodes.

Yields:

  • (Object)

    an connection instance of connection backend

Returns:

  • (Enumerable)


129
130
131
132
133
134
135
136
137
138
139
# File 'lib/renoir/client.rb', line 129

def each_node
  return enum_for(:each_node) unless block_given?

  @refresh_slots = true
  refresh_slots
  @cluster_info.nodes.each do |node|
    fetch_connection(node).with_raw_connection do |conn|
      yield conn
    end
  end
end

#eval(*args) {|Object| ... } ⇒ Object

Call EVAL command.

Parameters:

  • args (Array)

    arguments of EVAL passed to a connection backend

Yields:

  • (Object)

    a connection backend may yield

Returns:

  • the value returned by a connection backend

Raises:



73
74
75
# File 'lib/renoir/client.rb', line 73

def eval(*args, &block)
  call(:eval, *args, &block)
end

#multi {|Renoir::Pipeline| ... } ⇒ Object

Note:

Return value of Pipeline methods is useless since "future variable" is not yet supported.

Pipeline commands and call them with MULTI/EXEC.

Yields:

Returns:

  • the value returned by a connection backend

Raises:



83
84
85
86
87
88
89
# File 'lib/renoir/client.rb', line 83

def multi(&block)
  commands = pipeline_commands(&block)
  slot = get_slot_from_commands(commands)

  refresh_slots
  call_with_redirection(slot, [[:multi]] + commands + [[:exec]])
end

#pipelined {|Renoir::Pipeline| ... } ⇒ Object

Note:

Return value of Pipeline methods is useless since "future variable" is not yet supported.

Pipeline commands and call them.

Yields:

Returns:

  • the value returned by a connection backend

Raises:



97
98
99
100
101
102
103
# File 'lib/renoir/client.rb', line 97

def pipelined(&block)
  commands = pipeline_commands(&block)
  slot = get_slot_from_commands(commands)

  refresh_slots
  call_with_redirection(slot, commands)
end