redis-cluster-client 0.3.4 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 458c3d9cc4d1f6595510663cede0403953b2555ace0d3cae814663b23f69f1cb
4
- data.tar.gz: 01d2a34641e298ff7e99cc5f9edbad4ed152e5ca4f18e16181b9a4b84a2492c2
3
+ metadata.gz: 24e153973525e8cd3905e92e851194a5c1f4349cecd71ca4a71db34fa678d1d8
4
+ data.tar.gz: 963ac53058e861d50c55160f55f9b064e853c49b29811075ece80ce34fa7b0f8
5
5
  SHA512:
6
- metadata.gz: 3680e6b8b1594001060eb2dea29eb60f0779bba6a43350246b1d5c7e47b1bb1e04a6e1188ac87c1228adac21e86347cb3820679d6c92b693d7f7fedabba88402
7
- data.tar.gz: 21927b8a14e9ad075e3808e736789c4339af907f5d99e16806273f1553c505e7fc86faabfa067b98f2a3dd7d45a41fb0f89e780e08825aa9df4317531871da5d
6
+ metadata.gz: 841bdd5aa580dcd7c3169fe88f36b8ed888ffffd3cf50b9f75449365c430afb41d79d88f2265183119f0ed012ace418868679cad468bcf39b25aed30b6207da1
7
+ data.tar.gz: 5f36751289ba73d5471cfe44d9e3d10cb70fd517249ce48ad7ea4254de0595c869fb900fecd3b0abd690fe977a732650ebf8da80a5d95ed1464a3345b79243fa
@@ -10,7 +10,7 @@ class RedisClient
10
10
  EMPTY_STRING = ''
11
11
 
12
12
  class << self
13
- def load(nodes) # rubocop:disable Metrics/MethodLength
13
+ def load(nodes)
14
14
  errors = []
15
15
  cmd = nil
16
16
  nodes&.each do |node|
@@ -32,10 +32,7 @@ class RedisClient
32
32
 
33
33
  def parse_command_details(rows)
34
34
  rows&.reject { |row| row[0].nil? }.to_h do |row|
35
- [
36
- ::RedisClient::Cluster::NormalizedCmdName.instance.get_by_name(row[0]),
37
- { arity: row[1], flags: row[2], first: row[3], last: row[4], step: row[5] }
38
- ]
35
+ [row[0].downcase, { arity: row[1], flags: row[2], first: row[3], last: row[4], step: row[5] }]
39
36
  end
40
37
  end
41
38
  end
@@ -85,7 +82,7 @@ class RedisClient
85
82
  @details.fetch(name).fetch(key)
86
83
  end
87
84
 
88
- def determine_first_key_position(command) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
85
+ def determine_first_key_position(command) # rubocop:disable Metrics/CyclomaticComplexity
89
86
  case ::RedisClient::Cluster::NormalizedCmdName.instance.get_by_command(command)
90
87
  when 'eval', 'evalsha', 'zinterstore', 'zunionstore' then 3
91
88
  when 'object' then 2
@@ -34,18 +34,17 @@ class RedisClient
34
34
 
35
35
  def any_replica_node_key(seed: nil)
36
36
  random = seed.nil? ? Random : Random.new(seed)
37
- @existed_replicas.sample(random: random).first
37
+ @existed_replicas.sample(random: random)&.first
38
38
  end
39
39
 
40
40
  private
41
41
 
42
- def measure_latencies(clients) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
43
- latencies = {}
44
-
45
- clients.each_slice(::RedisClient::Cluster::Node::MAX_THREADS) do |chuncked_clients|
42
+ def measure_latencies(clients) # rubocop:disable Metrics/AbcSize
43
+ clients.each_slice(::RedisClient::Cluster::Node::MAX_THREADS).each_with_object({}) do |chuncked_clients, acc|
46
44
  threads = chuncked_clients.map do |k, v|
47
45
  Thread.new(k, v) do |node_key, client|
48
46
  Thread.pass
47
+ Thread.current.thread_variable_set(:node_key, node_key)
49
48
 
50
49
  min = DUMMY_LATENCY_NSEC
51
50
  MEASURE_ATTEMPT_COUNT.times do
@@ -55,16 +54,17 @@ class RedisClient
55
54
  min = duration if duration < min
56
55
  end
57
56
 
58
- latencies[node_key] = min
57
+ Thread.current.thread_variable_set(:latency, min)
59
58
  rescue StandardError
60
- latencies[node_key] = DUMMY_LATENCY_NSEC
59
+ Thread.current.thread_variable_set(:latency, DUMMY_LATENCY_NSEC)
61
60
  end
62
61
  end
63
62
 
64
- threads.each(&:join)
63
+ threads.each do |t|
64
+ t.join
65
+ acc[t.thread_variable_get(:node_key)] = t.thread_variable_get(:latency)
66
+ end
65
67
  end
66
-
67
- latencies
68
68
  end
69
69
 
70
70
  def select_replica_clients(replications, clients)
@@ -37,29 +37,38 @@ class RedisClient
37
37
  end
38
38
 
39
39
  class << self
40
- def load_info(options, **kwargs) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
40
+ def load_info(options, **kwargs) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
41
41
  startup_size = options.size > MAX_STARTUP_SAMPLE ? MAX_STARTUP_SAMPLE : options.size
42
- node_info_list = Array.new(startup_size)
43
- errors = Array.new(startup_size)
42
+ node_info_list = errors = nil
44
43
  startup_options = options.to_a.sample(MAX_STARTUP_SAMPLE).to_h
45
44
  startup_nodes = ::RedisClient::Cluster::Node.new(startup_options, **kwargs)
46
45
  startup_nodes.each_slice(MAX_THREADS).with_index do |chuncked_startup_nodes, chuncked_idx|
47
46
  threads = chuncked_startup_nodes.each_with_index.map do |raw_client, idx|
48
47
  Thread.new(raw_client, (MAX_THREADS * chuncked_idx) + idx) do |cli, i|
49
48
  Thread.pass
49
+ Thread.current.thread_variable_set(:index, i)
50
50
  reply = cli.call('CLUSTER', 'NODES')
51
- node_info_list[i] = parse_node_info(reply)
51
+ Thread.current.thread_variable_set(:info, parse_node_info(reply))
52
52
  rescue StandardError => e
53
- errors[i] = e
53
+ Thread.current.thread_variable_set(:error, e)
54
54
  ensure
55
55
  cli&.close
56
56
  end
57
57
  end
58
58
 
59
- threads.each(&:join)
59
+ threads.each do |t|
60
+ t.join
61
+ if t.thread_variable?(:info)
62
+ node_info_list ||= Array.new(startup_size)
63
+ node_info_list[t.thread_variable_get(:index)] = t.thread_variable_get(:info)
64
+ elsif t.thread_variable?(:error)
65
+ errors ||= Array.new(startup_size)
66
+ errors[t.thread_variable_get(:index)] = t.thread_variable_get(:error)
67
+ end
68
+ end
60
69
  end
61
70
 
62
- raise ::RedisClient::Cluster::InitialSetupError, errors if node_info_list.all?(&:nil?)
71
+ raise ::RedisClient::Cluster::InitialSetupError, errors if node_info_list.nil?
63
72
 
64
73
  grouped = node_info_list.compact.group_by do |rows|
65
74
  rows.sort_by { |row| row[:id] }
@@ -74,7 +83,7 @@ class RedisClient
74
83
 
75
84
  # @see https://redis.io/commands/cluster-nodes/
76
85
  # @see https://github.com/redis/redis/blob/78960ad57b8a5e6af743d789ed8fd767e37d42b8/src/cluster.c#L4660-L4683
77
- def parse_node_info(info) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
86
+ def parse_node_info(info) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
78
87
  rows = info.split("\n").map(&:split)
79
88
  rows.each { |arr| arr[2] = arr[2].split(',') }
80
89
  rows.select! { |arr| arr[7] == 'connected' && (arr[2] & %w[fail? fail handshake noaddr noflags]).empty? }
@@ -147,7 +156,7 @@ class RedisClient
147
156
 
148
157
  def send_ping(method, command, args, &block)
149
158
  result_values, errors = call_multiple_nodes(@topology.clients, method, command, args, &block)
150
- return result_values if errors.empty?
159
+ return result_values if errors.nil? || errors.empty?
151
160
 
152
161
  raise ReloadNeeded if errors.values.any?(::RedisClient::ConnectionError)
153
162
 
@@ -228,26 +237,35 @@ class RedisClient
228
237
 
229
238
  def call_multiple_nodes!(clients, method, command, args, &block)
230
239
  result_values, errors = call_multiple_nodes(clients, method, command, args, &block)
231
- return result_values if errors.empty?
240
+ return result_values if errors.nil? || errors.empty?
232
241
 
233
242
  raise ::RedisClient::Cluster::ErrorCollection, errors
234
243
  end
235
244
 
236
- def try_map(clients) # rubocop:disable Metrics/MethodLength
237
- results = {}
238
- errors = {}
245
+ def try_map(clients) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
246
+ results = errors = nil
239
247
  clients.each_slice(MAX_THREADS) do |chuncked_clients|
240
248
  threads = chuncked_clients.map do |k, v|
241
249
  Thread.new(k, v) do |node_key, client|
242
250
  Thread.pass
251
+ Thread.current.thread_variable_set(:node_key, node_key)
243
252
  reply = yield(node_key, client)
244
- results[node_key] = reply unless reply.nil?
253
+ Thread.current.thread_variable_set(:result, reply)
245
254
  rescue StandardError => e
246
- errors[node_key] = e
255
+ Thread.current.thread_variable_set(:error, e)
247
256
  end
248
257
  end
249
258
 
250
- threads.each(&:join)
259
+ threads.each do |t|
260
+ t.join
261
+ if t.thread_variable?(:result)
262
+ results ||= {}
263
+ results[t.thread_variable_get(:node_key)] = t.thread_variable_get(:result)
264
+ elsif t.thread_variable?(:error)
265
+ errors ||= {}
266
+ errors[t.thread_variable_get(:node_key)] = t.thread_variable_get(:error)
267
+ end
268
+ end
251
269
  end
252
270
 
253
271
  [results, errors]
@@ -28,6 +28,7 @@ class RedisClient
28
28
 
29
29
  def clear
30
30
  @mutex.synchronize { @cache.clear }
31
+ true
31
32
  end
32
33
 
33
34
  private
@@ -2,100 +2,252 @@
2
2
 
3
3
  require 'redis_client'
4
4
  require 'redis_client/cluster/errors'
5
+ require 'redis_client/connection_mixin'
6
+ require 'redis_client/middlewares'
7
+ require 'redis_client/pooled'
5
8
 
6
9
  class RedisClient
7
10
  class Cluster
8
11
  class Pipeline
12
+ class Extended < ::RedisClient::Pipeline
13
+ attr_reader :outer_indices
14
+
15
+ def initialize(command_builder)
16
+ super
17
+ @outer_indices = nil
18
+ end
19
+
20
+ def add_outer_index(index)
21
+ @outer_indices ||= []
22
+ @outer_indices << index
23
+ end
24
+
25
+ def get_inner_index(outer_index)
26
+ @outer_indices&.find_index(outer_index)
27
+ end
28
+
29
+ def get_callee_method(inner_index)
30
+ if @timeouts.is_a?(Array) && !@timeouts[inner_index].nil?
31
+ :blocking_call_v
32
+ elsif _retryable?
33
+ :call_once_v
34
+ else
35
+ :call_v
36
+ end
37
+ end
38
+
39
+ def get_command(inner_index)
40
+ @commands.is_a?(Array) ? @commands[inner_index] : nil
41
+ end
42
+
43
+ def get_timeout(inner_index)
44
+ @timeouts.is_a?(Array) ? @timeouts[inner_index] : nil
45
+ end
46
+
47
+ def get_block(inner_index)
48
+ @blocks.is_a?(Array) ? @blocks[inner_index] : nil
49
+ end
50
+ end
51
+
52
+ ::RedisClient::ConnectionMixin.module_eval do
53
+ def call_pipelined_aware_of_redirection(commands, timeouts) # rubocop:disable Metrics/AbcSize
54
+ size = commands.size
55
+ results = Array.new(commands.size)
56
+ @pending_reads += size
57
+ write_multi(commands)
58
+
59
+ redirection_indices = nil
60
+ size.times do |index|
61
+ timeout = timeouts && timeouts[index]
62
+ result = read(timeout)
63
+ @pending_reads -= 1
64
+ if result.is_a?(CommandError)
65
+ result._set_command(commands[index])
66
+ if result.message.start_with?('MOVED', 'ASK')
67
+ redirection_indices ||= []
68
+ redirection_indices << index
69
+ end
70
+ end
71
+
72
+ results[index] = result
73
+ end
74
+
75
+ return results if redirection_indices.nil?
76
+
77
+ err = ::RedisClient::Cluster::Pipeline::RedirectionNeeded.new
78
+ err.replies = results
79
+ err.indices = redirection_indices
80
+ raise err
81
+ end
82
+ end
83
+
9
84
  ReplySizeError = Class.new(::RedisClient::Error)
85
+
86
+ class RedirectionNeeded < ::RedisClient::Error
87
+ attr_accessor :replies, :indices
88
+ end
89
+
10
90
  MAX_THREADS = Integer(ENV.fetch('REDIS_CLIENT_MAX_THREADS', 5))
11
91
 
12
92
  def initialize(router, command_builder, seed: Random.new_seed)
13
93
  @router = router
14
94
  @command_builder = command_builder
15
- @grouped = {}
16
- @size = 0
17
95
  @seed = seed
96
+ @pipelines = nil
97
+ @size = 0
18
98
  end
19
99
 
20
100
  def call(*args, **kwargs, &block)
21
101
  command = @command_builder.generate(args, kwargs)
22
102
  node_key = @router.find_node_key(command, seed: @seed)
23
- add_line(node_key, [@size, :call_v, command, block])
103
+ append_pipeline(node_key).call_v(command, &block)
24
104
  end
25
105
 
26
106
  def call_v(args, &block)
27
107
  command = @command_builder.generate(args)
28
108
  node_key = @router.find_node_key(command, seed: @seed)
29
- add_line(node_key, [@size, :call_v, command, block])
109
+ append_pipeline(node_key).call_v(command, &block)
30
110
  end
31
111
 
32
112
  def call_once(*args, **kwargs, &block)
33
113
  command = @command_builder.generate(args, kwargs)
34
114
  node_key = @router.find_node_key(command, seed: @seed)
35
- add_line(node_key, [@size, :call_once_v, command, block])
115
+ append_pipeline(node_key).call_once_v(command, &block)
36
116
  end
37
117
 
38
118
  def call_once_v(args, &block)
39
119
  command = @command_builder.generate(args)
40
120
  node_key = @router.find_node_key(command, seed: @seed)
41
- add_line(node_key, [@size, :call_once_v, command, block])
121
+ append_pipeline(node_key).call_once_v(command, &block)
42
122
  end
43
123
 
44
124
  def blocking_call(timeout, *args, **kwargs, &block)
45
125
  command = @command_builder.generate(args, kwargs)
46
126
  node_key = @router.find_node_key(command, seed: @seed)
47
- add_line(node_key, [@size, :blocking_call_v, timeout, command, block])
127
+ append_pipeline(node_key).blocking_call_v(timeout, command, &block)
48
128
  end
49
129
 
50
130
  def blocking_call_v(timeout, args, &block)
51
131
  command = @command_builder.generate(args)
52
132
  node_key = @router.find_node_key(command, seed: @seed)
53
- add_line(node_key, [@size, :blocking_call_v, timeout, command, block])
133
+ append_pipeline(node_key).blocking_call_v(timeout, command, &block)
54
134
  end
55
135
 
56
136
  def empty?
57
137
  @size.zero?
58
138
  end
59
139
 
60
- # TODO: https://github.com/redis-rb/redis-cluster-client/issues/37 handle redirections
61
- def execute # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
62
- all_replies = Array.new(@size)
63
- errors = {}
64
- @grouped.each_slice(MAX_THREADS) do |chuncked_grouped|
65
- threads = chuncked_grouped.map do |k, v|
66
- Thread.new(@router, k, v) do |router, node_key, rows|
140
+ def execute # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
141
+ all_replies = errors = nil
142
+ @pipelines&.each_slice(MAX_THREADS) do |chuncked_pipelines|
143
+ threads = chuncked_pipelines.map do |node_key, pipeline|
144
+ Thread.new(node_key, pipeline) do |nk, pl|
67
145
  Thread.pass
68
- replies = router.find_node(node_key).pipelined do |pipeline|
69
- rows.each do |row|
70
- case row.size
71
- when 4 then pipeline.send(row[1], row[2], &row[3])
72
- when 5 then pipeline.send(row[1], row[2], row[3], &row[4])
73
- end
74
- end
75
- end
76
-
77
- raise ReplySizeError, "commands: #{rows.size}, replies: #{replies.size}" if rows.size != replies.size
146
+ Thread.current.thread_variable_set(:node_key, nk)
147
+ replies = do_pipelining(@router.find_node(nk), pl)
148
+ raise ReplySizeError, "commands: #{pl._size}, replies: #{replies.size}" if pl._size != replies.size
78
149
 
79
- rows.each_with_index { |row, idx| all_replies[row.first] = replies[idx] }
150
+ Thread.current.thread_variable_set(:replies, replies)
151
+ rescue ::RedisClient::Cluster::Pipeline::RedirectionNeeded => e
152
+ Thread.current.thread_variable_set(:redirection_needed, e)
80
153
  rescue StandardError => e
81
- errors[node_key] = e
154
+ Thread.current.thread_variable_set(:error, e)
82
155
  end
83
156
  end
84
157
 
85
- threads.each(&:join)
158
+ threads.each do |t|
159
+ t.join
160
+
161
+ if t.thread_variable?(:replies)
162
+ all_replies ||= Array.new(@size)
163
+ @pipelines[t.thread_variable_get(:node_key)]
164
+ .outer_indices
165
+ .each_with_index { |outer, inner| all_replies[outer] = t.thread_variable_get(:replies)[inner] }
166
+ elsif t.thread_variable?(:redirection_needed)
167
+ all_replies ||= Array.new(@size)
168
+ pipeline = @pipelines[t.thread_variable_get(:node_key)]
169
+ err = t.thread_variable_get(:redirection_needed)
170
+ err.indices.each { |i| err.replies[i] = handle_redirection(err.replies[i], pipeline, i) }
171
+ pipeline.outer_indices.each_with_index { |outer, inner| all_replies[outer] = err.replies[inner] }
172
+ elsif t.thread_variable?(:error)
173
+ errors ||= {}
174
+ errors[t.thread_variable_get(:node_key)] = t.thread_variable_get(:error)
175
+ end
176
+ end
86
177
  end
87
178
 
88
- return all_replies if errors.empty?
179
+ raise ::RedisClient::Cluster::ErrorCollection, errors unless errors.nil?
89
180
 
90
- raise ::RedisClient::Cluster::ErrorCollection, errors
181
+ all_replies
91
182
  end
92
183
 
93
184
  private
94
185
 
95
- def add_line(node_key, line)
96
- @grouped[node_key] = [] unless @grouped.key?(node_key)
97
- @grouped[node_key] << line
186
+ def append_pipeline(node_key)
187
+ @pipelines ||= {}
188
+ @pipelines[node_key] ||= ::RedisClient::Cluster::Pipeline::Extended.new(@command_builder)
189
+ @pipelines[node_key].add_outer_index(@size)
98
190
  @size += 1
191
+ @pipelines[node_key]
192
+ end
193
+
194
+ def do_pipelining(client, pipeline)
195
+ case client
196
+ when ::RedisClient then send_pipeline(client, pipeline)
197
+ when ::RedisClient::Pooled then client.with { |cli| send_pipeline(cli, pipeline) }
198
+ else raise NotImplementedError, "#{client.class.name}#pipelined for cluster client"
199
+ end
200
+ end
201
+
202
+ def send_pipeline(client, pipeline)
203
+ results = client.send(:ensure_connected, retryable: pipeline._retryable?) do |connection|
204
+ commands = pipeline._commands
205
+ ::RedisClient::Middlewares.call_pipelined(commands, client.config) do
206
+ connection.call_pipelined_aware_of_redirection(commands, pipeline._timeouts)
207
+ end
208
+ end
209
+
210
+ pipeline._coerce!(results)
211
+ end
212
+
213
+ def handle_redirection(err, pipeline, inner_index)
214
+ return err unless err.is_a?(::RedisClient::CommandError)
215
+
216
+ if err.message.start_with?('MOVED')
217
+ node = @router.assign_redirection_node(err.message)
218
+ try_redirection(node, pipeline, inner_index)
219
+ elsif err.message.start_with?('ASK')
220
+ node = @router.assign_asking_node(err.message)
221
+ try_asking(node) ? try_redirection(node, pipeline, inner_index) : err
222
+ else
223
+ err
224
+ end
225
+ end
226
+
227
+ def try_redirection(node, pipeline, inner_index)
228
+ redirect_command(node, pipeline, inner_index)
229
+ rescue StandardError => e
230
+ e
231
+ end
232
+
233
+ def redirect_command(node, pipeline, inner_index)
234
+ method = pipeline.get_callee_method(inner_index)
235
+ command = pipeline.get_command(inner_index)
236
+ timeout = pipeline.get_timeout(inner_index)
237
+ block = pipeline.get_block(inner_index)
238
+ args = timeout.nil? ? [] : [timeout]
239
+
240
+ if block.nil?
241
+ @router.try_send(node, method, command, args)
242
+ else
243
+ @router.try_send(node, method, command, args, &block)
244
+ end
245
+ end
246
+
247
+ def try_asking(node)
248
+ node.call('ASKING') == 'OK'
249
+ rescue StandardError
250
+ false
99
251
  end
100
252
  end
101
253
  end
@@ -25,7 +25,7 @@ class RedisClient
25
25
  @command_builder = @config.command_builder
26
26
  end
27
27
 
28
- def send_command(method, command, *args, &block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
28
+ def send_command(method, command, *args, &block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
29
29
  cmd = ::RedisClient::Cluster::NormalizedCmdName.instance.get_by_command(command)
30
30
  case cmd
31
31
  when 'acl', 'auth', 'bgrewriteaof', 'bgsave', 'quit', 'save'
@@ -65,7 +65,7 @@ class RedisClient
65
65
 
66
66
  # @see https://redis.io/topics/cluster-spec#redirection-and-resharding
67
67
  # Redirection and resharding
68
- def try_send(node, method, command, args, retry_count: 3, &block) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
68
+ def try_send(node, method, command, args, retry_count: 3, &block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
69
69
  if args.empty?
70
70
  # prevent memory allocation for variable-length args
71
71
  node.send(method, command, &block)
@@ -100,7 +100,7 @@ class RedisClient
100
100
  retry
101
101
  end
102
102
 
103
- def try_delegate(node, method, *args, retry_count: 3, **kwargs, &block) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
103
+ def try_delegate(node, method, *args, retry_count: 3, **kwargs, &block) # rubocop:disable Metrics/AbcSize
104
104
  node.send(method, *args, **kwargs, &block)
105
105
  rescue ::RedisClient::CommandError => e
106
106
  raise if retry_count <= 0
@@ -129,7 +129,7 @@ class RedisClient
129
129
  retry
130
130
  end
131
131
 
132
- def scan(*command, seed: nil, **kwargs) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
132
+ def scan(*command, seed: nil, **kwargs) # rubocop:disable Metrics/AbcSize
133
133
  command = @command_builder.generate(command, kwargs)
134
134
 
135
135
  command[1] = ZERO_CURSOR_FOR_SCAN if command.size == 1
@@ -172,7 +172,7 @@ class RedisClient
172
172
  def find_node(node_key, retry_count: 3)
173
173
  @node.find_by(node_key)
174
174
  rescue ::RedisClient::Cluster::Node::ReloadNeeded
175
- raise ::RedieClient::Cluster::NodeMightBeDown if retry_count <= 0
175
+ raise ::RedisClient::Cluster::NodeMightBeDown if retry_count <= 0
176
176
 
177
177
  update_cluster_info!
178
178
  retry_count -= 1
@@ -183,6 +183,18 @@ class RedisClient
183
183
  @command.exists?(name)
184
184
  end
185
185
 
186
+ def assign_redirection_node(err_msg)
187
+ _, slot, node_key = err_msg.split
188
+ slot = slot.to_i
189
+ @node.update_slot(slot, node_key)
190
+ find_node(node_key)
191
+ end
192
+
193
+ def assign_asking_node(err_msg)
194
+ _, _, node_key = err_msg.split
195
+ find_node(node_key)
196
+ end
197
+
186
198
  private
187
199
 
188
200
  def send_wait_command(method, command, args, retry_count: 3, &block)
@@ -258,19 +270,7 @@ class RedisClient
258
270
  end
259
271
  end
260
272
 
261
- def assign_redirection_node(err_msg)
262
- _, slot, node_key = err_msg.split
263
- slot = slot.to_i
264
- @node.update_slot(slot, node_key)
265
- find_node(node_key)
266
- end
267
-
268
- def assign_asking_node(err_msg)
269
- _, _, node_key = err_msg.split
270
- find_node(node_key)
271
- end
272
-
273
- def fetch_cluster_info(config, pool: nil, **kwargs) # rubocop:disable Metrics/MethodLength
273
+ def fetch_cluster_info(config, pool: nil, **kwargs)
274
274
  node_info = ::RedisClient::Cluster::Node.load_info(config.per_node_key, **kwargs)
275
275
  node_addrs = node_info.map { |info| ::RedisClient::Cluster::NodeKey.hashify(info[:node_key]) }
276
276
  config.update_node(node_addrs)
@@ -81,7 +81,7 @@ class RedisClient
81
81
  seed = @config.use_replica? && @config.replica_affinity == :random ? nil : Random.new_seed
82
82
  pipeline = ::RedisClient::Cluster::Pipeline.new(@router, @command_builder, seed: seed)
83
83
  yield pipeline
84
- return [] if pipeline.empty? == 0
84
+ return [] if pipeline.empty?
85
85
 
86
86
  pipeline.execute
87
87
  end
@@ -114,7 +114,7 @@ class RedisClient
114
114
  end
115
115
  end
116
116
 
117
- def parse_node_url(addr) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
117
+ def parse_node_url(addr) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
118
118
  return if addr.empty?
119
119
 
120
120
  uri = URI(addr)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis-cluster-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Taishi Kasuga
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-19 00:00:00.000000000 Z
11
+ date: 2022-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis-client