redis-cluster-client 0.0.6 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fde84481c2ca9680670f252a002391a34ae793148a21a8e02086d199412a53ab
4
- data.tar.gz: 5af188432f9ae5e76c13d0dd174c25cde4b98d1de49efeb97e2a809bd111a9a6
3
+ metadata.gz: 032431ff16773725b9cb68482bc5df78affdf23e66b6bbd91b6ddbabdd9da921
4
+ data.tar.gz: dc789f59f6509e35ab23df03a70867b5e8414ee3bb327462fbcd5d63be4c6744
5
5
  SHA512:
6
- metadata.gz: f26dc7bb447ee70742efc90344758ad3058cd0d1506ad8576637b7e9ad296a806d7e15e3b824cead0fb2313140dea00f6f579a15803399c16257ac347c45085f
7
- data.tar.gz: 06f43e223a53d9ada0803f7292bc1ca58505fb3c341fd7643eb6cf0eff73bebe4ecd2022b0a1b59af81dda879a9d8a9b078107181ff45037773382dada321597
6
+ metadata.gz: 6013ff65d8dc06b776b7b201244d75eaf62993368f5285d823472f78bec2c81639734f23c32793bc1b8d1981905e5794e35e4e353696d70f1d66930434e6104f
7
+ data.tar.gz: 0e1dc5f17a9706c2fc64bdd03e74ee457f9b9aea81740cdeb5459bd9bbc769b6353047b64ef008b6d34b950fbc7cb8cf57e66c9deb41d33edbacaba78ca2a12e
@@ -68,12 +68,14 @@ class RedisClient
68
68
  @details.fetch(name).fetch(key)
69
69
  end
70
70
 
71
- def determine_first_key_position(command) # rubocop:disable Metrics/CyclomaticComplexity
71
+ def determine_first_key_position(command) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
72
72
  case command&.flatten&.first.to_s.downcase
73
- when 'eval', 'evalsha', 'migrate', 'zinterstore', 'zunionstore' then 3
73
+ when 'eval', 'evalsha', 'zinterstore', 'zunionstore' then 3
74
74
  when 'object' then 2
75
75
  when 'memory'
76
76
  command[1].to_s.casecmp('usage').zero? ? 2 : 0
77
+ when 'migrate'
78
+ command[3] == '""' ? determine_optional_key_position(command, 'keys') : 3
77
79
  when 'xread', 'xreadgroup'
78
80
  determine_optional_key_position(command, 'streams')
79
81
  else
@@ -29,7 +29,7 @@ class RedisClient
29
29
  end
30
30
 
31
31
  # Raised when error occurs on any node of cluster.
32
- class CommandErrorCollection < ::RedisClient::Error
32
+ class ErrorCollection < ::RedisClient::Error
33
33
  attr_reader :errors
34
34
 
35
35
  def initialize(errors)
@@ -51,5 +51,15 @@ class RedisClient
51
51
  super("Cluster client doesn't know which node the #{command} command should be sent to.")
52
52
  end
53
53
  end
54
+
55
+ class NodeMightBeDown < ::RedisClient::Error
56
+ def initialize(_ = '')
57
+ super(
58
+ 'The client is trying to fetch the latest cluster state '\
59
+ 'because a subset of nodes might be down. '\
60
+ 'It might continue to raise errors for a while.'
61
+ )
62
+ end
63
+ end
54
64
  end
55
65
  end
@@ -43,6 +43,8 @@ class RedisClient
43
43
  module_function
44
44
 
45
45
  def convert(key)
46
+ return nil if key.nil?
47
+
46
48
  crc = 0
47
49
  key.each_byte do |b|
48
50
  crc = ((crc << 8) & 0xffff) ^ XMODEM_CRC16_LOOKUP[((crc >> 8) ^ b) & 0xff]
@@ -12,6 +12,7 @@ class RedisClient
12
12
  SLOT_SIZE = 16_384
13
13
  MIN_SLOT = 0
14
14
  MAX_SLOT = SLOT_SIZE - 1
15
+ MAX_STARTUP_SAMPLE = 37
15
16
  IGNORE_GENERIC_CONFIG_KEYS = %i[url host port path].freeze
16
17
 
17
18
  ReloadNeeded = Class.new(::RedisClient::Error)
@@ -32,19 +33,33 @@ class RedisClient
32
33
  end
33
34
 
34
35
  class << self
35
- def load_info(options, **kwargs)
36
- startup_nodes = ::RedisClient::Cluster::Node.new(options, **kwargs)
37
-
38
- errors = startup_nodes.map do |n|
39
- reply = n.call('CLUSTER', 'NODES')
40
- return parse_node_info(reply)
41
- rescue ::RedisClient::ConnectionError, ::RedisClient::CommandError => e
42
- e
36
+ def load_info(options, **kwargs) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
37
+ startup_size = options.size > MAX_STARTUP_SAMPLE ? MAX_STARTUP_SAMPLE : options.size
38
+ node_info_list = Array.new(startup_size)
39
+ errors = Array.new(startup_size)
40
+ startup_options = options.to_a.sample(MAX_STARTUP_SAMPLE).to_h
41
+ startup_nodes = ::RedisClient::Cluster::Node.new(startup_options, **kwargs)
42
+ threads = startup_nodes.each_with_index.map do |raw_client, idx|
43
+ Thread.new(raw_client, idx) do |cli, i|
44
+ Thread.pass
45
+ reply = cli.call('CLUSTER', 'NODES')
46
+ node_info_list[i] = parse_node_info(reply)
47
+ rescue StandardError => e
48
+ errors[i] = e
49
+ ensure
50
+ cli&.close
51
+ end
52
+ end
53
+ threads.each(&:join)
54
+ raise ::RedisClient::Cluster::InitialSetupError, errors if node_info_list.all?(&:nil?)
55
+
56
+ grouped = node_info_list.compact.group_by do |rows|
57
+ rows.sort_by { |row| row[:id] }
58
+ .map { |r| "#{r[:id]}#{r[:node_key]}#{r[:role]}#{r[:primary_id]}#{r[:config_epoch]}" }
59
+ .join
43
60
  end
44
61
 
45
- raise ::RedisClient::Cluster::InitialSetupError, errors
46
- ensure
47
- startup_nodes&.each(&:close)
62
+ grouped.max_by { |_, v| v.size }[1].first
48
63
  end
49
64
 
50
65
  private
@@ -109,32 +124,58 @@ class RedisClient
109
124
  end
110
125
 
111
126
  def find_by(node_key)
127
+ raise ReloadNeeded if node_key.nil? || !@clients.key?(node_key)
128
+
112
129
  @clients.fetch(node_key)
113
- rescue KeyError
114
- raise ReloadNeeded
115
130
  end
116
131
 
117
- def call_all(method, *command, **kwargs, &block)
118
- try_map { |_, client| client.send(method, *command, **kwargs, &block) }.values
132
+ def call_all(method, *args, **kwargs, &block)
133
+ results, errors = try_map do |_, client|
134
+ client.send(method, *args, **kwargs, &block)
135
+ end
136
+
137
+ return results.values if errors.empty?
138
+
139
+ raise ::RedisClient::Cluster::ErrorCollection, errors
119
140
  end
120
141
 
121
- def call_primary(method, *command, **kwargs, &block)
122
- try_map do |node_key, client|
142
+ def call_primaries(method, *args, **kwargs, &block)
143
+ results, errors = try_map do |node_key, client|
123
144
  next if replica?(node_key)
124
145
 
125
- client.send(method, *command, **kwargs, &block)
126
- end.values
146
+ client.send(method, *args, **kwargs, &block)
147
+ end
148
+
149
+ return results.values if errors.empty?
150
+
151
+ raise ::RedisClient::Cluster::ErrorCollection, errors
127
152
  end
128
153
 
129
- def call_replica(method, *command, **kwargs, &block)
130
- return call_primary(method, *command, **kwargs, &block) if replica_disabled?
154
+ def call_replicas(method, *args, **kwargs, &block)
155
+ return call_primaries(method, *args, **kwargs, &block) if replica_disabled?
131
156
 
132
157
  replica_node_keys = @replications.values.map(&:sample)
133
- try_map do |node_key, client|
158
+ results, errors = try_map do |node_key, client|
134
159
  next if primary?(node_key) || !replica_node_keys.include?(node_key)
135
160
 
136
- client.send(method, *command, **kwargs, &block)
137
- end.values
161
+ client.send(method, *args, **kwargs, &block)
162
+ end
163
+
164
+ return results.values if errors.empty?
165
+
166
+ raise ::RedisClient::Cluster::ErrorCollection, errors
167
+ end
168
+
169
+ def send_ping(method, *args, **kwargs, &block)
170
+ results, errors = try_map do |_, client|
171
+ client.send(method, *args, **kwargs, &block)
172
+ end
173
+
174
+ return results.values if errors.empty?
175
+
176
+ raise ReloadNeeded if errors.values.any?(::RedisClient::ConnectionError)
177
+
178
+ raise ::RedisClient::Cluster::ErrorCollection, errors
138
179
  end
139
180
 
140
181
  def scale_reading_clients
@@ -144,14 +185,9 @@ class RedisClient
144
185
  end
145
186
  end
146
187
 
147
- def slot_exists?(slot)
148
- slot = Integer(slot)
149
- return false if slot < MIN_SLOT || slot > MAX_SLOT
150
-
151
- !@slots[slot].nil?
152
- end
153
-
154
188
  def find_node_key_of_primary(slot)
189
+ return if slot.nil?
190
+
155
191
  slot = Integer(slot)
156
192
  return if slot < MIN_SLOT || slot > MAX_SLOT
157
193
 
@@ -159,6 +195,8 @@ class RedisClient
159
195
  end
160
196
 
161
197
  def find_node_key_of_replica(slot)
198
+ return if slot.nil?
199
+
162
200
  slot = Integer(slot)
163
201
  return if slot < MIN_SLOT || slot > MAX_SLOT
164
202
 
@@ -228,22 +266,20 @@ class RedisClient
228
266
  end
229
267
 
230
268
  def try_map # rubocop:disable Metrics/MethodLength
231
- errors = {}
232
269
  results = {}
270
+ errors = {}
233
271
  threads = @clients.map do |k, v|
234
272
  Thread.new(k, v) do |node_key, client|
235
273
  Thread.pass
236
274
  reply = yield(node_key, client)
237
275
  results[node_key] = reply unless reply.nil?
238
- rescue ::RedisClient::CommandError => e
276
+ rescue StandardError => e
239
277
  errors[node_key] = e
240
278
  end
241
279
  end
242
280
 
243
281
  threads.each(&:join)
244
- return results if errors.empty?
245
-
246
- raise ::RedisClient::Cluster::CommandErrorCollection, errors
282
+ [results, errors]
247
283
  end
248
284
  end
249
285
  end
@@ -40,9 +40,10 @@ class RedisClient
40
40
  @size.zero?
41
41
  end
42
42
 
43
- # TODO: https://github.com/redis-rb/redis-cluster-client/issues/37
44
- def execute # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
43
+ # TODO: https://github.com/redis-rb/redis-cluster-client/issues/37 handle redirections
44
+ def execute # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
45
45
  all_replies = Array.new(@size)
46
+ errors = {}
46
47
  threads = @grouped.map do |k, v|
47
48
  Thread.new(@client, k, v) do |client, node_key, rows|
48
49
  Thread.pass
@@ -60,11 +61,15 @@ class RedisClient
60
61
  raise ReplySizeError, "commands: #{rows.size}, replies: #{replies.size}" if rows.size != replies.size
61
62
 
62
63
  rows.each_with_index { |row, idx| all_replies[row.first] = replies[idx] }
64
+ rescue StandardError => e
65
+ errors[node_key] = e
63
66
  end
64
67
  end
65
68
 
66
69
  threads.each(&:join)
67
- all_replies
70
+ return all_replies if errors.empty?
71
+
72
+ raise ::RedisClient::Cluster::ErrorCollection, errors
68
73
  end
69
74
  end
70
75
 
@@ -122,8 +127,7 @@ class RedisClient
122
127
  end
123
128
 
124
129
  def blocking_call(timeout, *command, **kwargs)
125
- node = assign_node(*command)
126
- try_send(node, :blocking_call, timeout, *command, **kwargs)
130
+ send_command(:blocking_call, timeout, *command, **kwargs)
127
131
  end
128
132
 
129
133
  def scan(*args, **kwargs, &block)
@@ -165,8 +169,10 @@ class RedisClient
165
169
  end
166
170
 
167
171
  def close
168
- @node.each(&:close)
172
+ @node.call_all(:close)
169
173
  nil
174
+ rescue StandardError
175
+ # ignore
170
176
  end
171
177
 
172
178
  private
@@ -179,102 +185,124 @@ class RedisClient
179
185
  node_info: node_info, pool: pool, with_replica: config.use_replica?, **kwargs)
180
186
  end
181
187
 
182
- def send_command(method, *command, **kwargs, &block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
188
+ def send_command(method, *args, **kwargs, &block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
189
+ command = method == :blocking_call && args.size > 1 ? args[1..] : args
190
+
183
191
  cmd = command.first.to_s.downcase
184
192
  case cmd
185
- when 'acl', 'auth', 'bgrewriteaof', 'bgsave', 'quit', 'save', 'ping'
186
- @node.call_all(method, *command, **kwargs, &block).first
193
+ when 'acl', 'auth', 'bgrewriteaof', 'bgsave', 'quit', 'save'
194
+ @node.call_all(method, *args, **kwargs, &block).first
187
195
  when 'flushall', 'flushdb'
188
- @node.call_primary(method, *command, **kwargs, &block).first
189
- when 'wait' then send_wait_command(method, *command, **kwargs, &block)
190
- when 'keys' then @node.call_replica(method, *command, **kwargs, &block).flatten.sort
191
- when 'dbsize' then @node.call_replica(method, *command, **kwargs, &block).sum
196
+ @node.call_primaries(method, *args, **kwargs, &block).first
197
+ when 'ping' then @node.send_ping(method, *args, **kwargs, &block).first
198
+ when 'wait' then send_wait_command(method, *args, **kwargs, &block)
199
+ when 'keys' then @node.call_replicas(method, *args, **kwargs, &block).flatten.sort
200
+ when 'dbsize' then @node.call_replicas(method, *args, **kwargs, &block).sum
192
201
  when 'scan' then _scan(*command, **kwargs)
193
- when 'lastsave' then @node.call_all(method, *command, **kwargs, &block).sort
194
- when 'role' then @node.call_all(method, *command, **kwargs, &block)
195
- when 'config' then send_config_command(method, *command, **kwargs, &block)
196
- when 'client' then send_client_command(method, *command, **kwargs, &block)
197
- when 'cluster' then send_cluster_command(method, *command, **kwargs, &block)
202
+ when 'lastsave' then @node.call_all(method, *args, **kwargs, &block).sort
203
+ when 'role' then @node.call_all(method, *args, **kwargs, &block)
204
+ when 'config' then send_config_command(method, *args, **kwargs, &block)
205
+ when 'client' then send_client_command(method, *args, **kwargs, &block)
206
+ when 'cluster' then send_cluster_command(method, *args, **kwargs, &block)
198
207
  when 'readonly', 'readwrite', 'shutdown'
199
208
  raise ::RedisClient::Cluster::OrchestrationCommandNotSupported, cmd
200
- when 'memory' then send_memory_command(method, *command, **kwargs, &block)
201
- when 'script' then send_script_command(method, *command, **kwargs, &block)
202
- when 'pubsub' then send_pubsub_command(method, *command, **kwargs, &block)
209
+ when 'memory' then send_memory_command(method, *args, **kwargs, &block)
210
+ when 'script' then send_script_command(method, *args, **kwargs, &block)
211
+ when 'pubsub' then send_pubsub_command(method, *args, **kwargs, &block)
203
212
  when 'discard', 'exec', 'multi', 'unwatch'
204
213
  raise ::RedisClient::Cluster::AmbiguousNodeError, cmd
205
214
  else
206
215
  node = assign_node(*command)
207
- try_send(node, method, *command, **kwargs, &block)
216
+ try_send(node, method, *args, **kwargs, &block)
208
217
  end
209
- rescue RedisClient::Cluster::CommandErrorCollection => e
210
- update_cluster_info! if e.errors.values.map(&:class).any?(::RedisClient::ConnectionError)
211
- raise
218
+ rescue RedisClient::Cluster::Node::ReloadNeeded
219
+ update_cluster_info!
220
+ raise ::RedisClient::Cluster::NodeMightBeDown
212
221
  end
213
222
 
214
- def send_wait_command(method, *command, retry_count: 3, **kwargs, &block)
215
- @node.call_primary(method, *command, **kwargs, &block).sum
216
- rescue RedisClient::Cluster::CommandErrorCollection => e
217
- raise if retry_count <= 0 || e.errors.values.map(&:message).grep(/ERR WAIT cannot be used with replica instances/).empty?
223
+ def send_wait_command(method, *args, retry_count: 3, **kwargs, &block)
224
+ @node.call_primaries(method, *args, **kwargs, &block).sum
225
+ rescue RedisClient::Cluster::ErrorCollection => e
226
+ raise if retry_count <= 0
227
+ raise if e.errors.values.none? do |err|
228
+ err.message.include?('WAIT cannot be used with replica instances')
229
+ end
218
230
 
219
231
  update_cluster_info!
220
232
  retry_count -= 1
221
233
  retry
222
234
  end
223
235
 
224
- def send_config_command(method, *command, **kwargs, &block)
236
+ def send_config_command(method, *args, **kwargs, &block)
237
+ command = method == :blocking_call && args.size > 1 ? args[1..] : args
238
+
225
239
  case command[1].to_s.downcase
226
240
  when 'resetstat', 'rewrite', 'set'
227
- @node.call_all(method, *command, **kwargs, &block).first
228
- else assign_node(*command).send(method, *command, **kwargs, &block)
241
+ @node.call_all(method, *args, **kwargs, &block).first
242
+ else assign_node(*command).send(method, *args, **kwargs, &block)
229
243
  end
230
244
  end
231
245
 
232
- def send_memory_command(method, *command, **kwargs, &block)
246
+ def send_memory_command(method, *args, **kwargs, &block)
247
+ command = method == :blocking_call && args.size > 1 ? args[1..] : args
248
+
233
249
  case command[1].to_s.downcase
234
- when 'stats' then @node.call_all(method, *command, **kwargs, &block)
235
- when 'purge' then @node.call_all(method, *command, **kwargs, &block).first
236
- else assign_node(*command).send(method, *command, **kwargs, &block)
250
+ when 'stats' then @node.call_all(method, *args, **kwargs, &block)
251
+ when 'purge' then @node.call_all(method, *args, **kwargs, &block).first
252
+ else assign_node(*command).send(method, *args, **kwargs, &block)
237
253
  end
238
254
  end
239
255
 
240
- def send_client_command(method, *command, **kwargs, &block)
256
+ def send_client_command(method, *args, **kwargs, &block)
257
+ command = method == :blocking_call && args.size > 1 ? args[1..] : args
258
+
241
259
  case command[1].to_s.downcase
242
- when 'list' then @node.call_all(method, *command, **kwargs, &block).flatten
260
+ when 'list' then @node.call_all(method, *args, **kwargs, &block).flatten
243
261
  when 'pause', 'reply', 'setname'
244
- @node.call_all(method, *command, **kwargs, &block).first
245
- else assign_node(*command).send(method, *command, **kwargs, &block)
262
+ @node.call_all(method, *args, **kwargs, &block).first
263
+ else assign_node(*command).send(method, *args, **kwargs, &block)
246
264
  end
247
265
  end
248
266
 
249
- def send_cluster_command(method, *command, **kwargs, &block)
267
+ def send_cluster_command(method, *args, **kwargs, &block) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
268
+ command = method == :blocking_call && args.size > 1 ? args[1..] : args
250
269
  subcommand = command[1].to_s.downcase
270
+
251
271
  case subcommand
252
272
  when 'addslots', 'delslots', 'failover', 'forget', 'meet', 'replicate',
253
273
  'reset', 'set-config-epoch', 'setslot'
254
274
  raise ::RedisClient::Cluster::OrchestrationCommandNotSupported, ['cluster', subcommand]
255
- when 'saveconfig' then @node.call_all(method, *command, **kwargs, &block).first
256
- else assign_node(*command).send(method, *command, **kwargs, &block)
275
+ when 'saveconfig' then @node.call_all(method, *args, **kwargs, &block).first
276
+ when 'getkeysinslot'
277
+ raise ArgumentError, command.join(' ') if command.size != 4
278
+
279
+ find_node(@node.find_node_key_of_replica(command[2])).send(method, *args, **kwargs, &block)
280
+ else assign_node(*command).send(method, *args, **kwargs, &block)
257
281
  end
258
282
  end
259
283
 
260
- def send_script_command(method, *command, **kwargs, &block)
284
+ def send_script_command(method, *args, **kwargs, &block)
285
+ command = method == :blocking_call && args.size > 1 ? args[1..] : args
286
+
261
287
  case command[1].to_s.downcase
262
288
  when 'debug', 'kill'
263
- @node.call_all(method, *command, **kwargs, &block).first
289
+ @node.call_all(method, *args, **kwargs, &block).first
264
290
  when 'flush', 'load'
265
- @node.call_primary(method, *command, **kwargs, &block).first
266
- else assign_node(*command).send(method, *command, **kwargs, &block)
291
+ @node.call_primaries(method, *args, **kwargs, &block).first
292
+ else assign_node(*command).send(method, *args, **kwargs, &block)
267
293
  end
268
294
  end
269
295
 
270
- def send_pubsub_command(method, *command, **kwargs, &block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
296
+ def send_pubsub_command(method, *args, **kwargs, &block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
297
+ command = method == :blocking_call && args.size > 1 ? args[1..] : args
298
+
271
299
  case command[1].to_s.downcase
272
- when 'channels' then @node.call_all(method, *command, **kwargs, &block).flatten.uniq.sort
300
+ when 'channels' then @node.call_all(method, *args, **kwargs, &block).flatten.uniq.sort
273
301
  when 'numsub'
274
- @node.call_all(method, *command, **kwargs, &block).reject(&:empty?).map { |e| Hash[*e] }
302
+ @node.call_all(method, *args, **kwargs, &block).reject(&:empty?).map { |e| Hash[*e] }
275
303
  .reduce({}) { |a, e| a.merge(e) { |_, v1, v2| v1 + v2 } }
276
- when 'numpat' then @node.call_all(method, *command, **kwargs, &block).sum
277
- else assign_node(*command).send(method, *command, **kwargs, &block)
304
+ when 'numpat' then @node.call_all(method, *args, **kwargs, &block).sum
305
+ else assign_node(*command).send(method, *args, **kwargs, &block)
278
306
  end
279
307
  end
280
308
 
@@ -344,44 +372,30 @@ class RedisClient
344
372
  find_node(node_key)
345
373
  end
346
374
 
347
- def find_node_key(*command, primary_only: false) # rubocop:disable Metrics/MethodLength
375
+ def find_node_key(*command, primary_only: false)
348
376
  key = @command.extract_first_key(command)
349
- if key.empty?
350
- return @node.primary_node_keys.sample if @command.should_send_to_primary?(command) || primary_only
351
-
352
- return @node.replica_node_keys.sample
353
- end
354
-
355
- slot = ::RedisClient::Cluster::KeySlotConverter.convert(key)
356
- return unless @node.slot_exists?(slot)
377
+ slot = key.empty? ? nil : ::RedisClient::Cluster::KeySlotConverter.convert(key)
357
378
 
358
379
  if @command.should_send_to_primary?(command) || primary_only
359
- @node.find_node_key_of_primary(slot)
380
+ @node.find_node_key_of_primary(slot) || @node.primary_node_keys.sample
360
381
  else
361
- @node.find_node_key_of_replica(slot)
382
+ @node.find_node_key_of_replica(slot) || @node.replica_node_keys.sample
362
383
  end
363
384
  end
364
385
 
365
386
  def find_node(node_key, retry_count: 3)
366
- return @node.sample if node_key.nil?
367
-
368
387
  @node.find_by(node_key)
369
388
  rescue ::RedisClient::Cluster::Node::ReloadNeeded
370
- raise(::RedisClient::ConnectionError, 'unstable cluster state') if retry_count <= 0
389
+ raise ::RedieClient::Cluster::NodeMightBeDown if retry_count <= 0
371
390
 
372
- update_cluster_info!(node_key)
391
+ update_cluster_info!
373
392
  retry_count -= 1
374
393
  retry
375
394
  end
376
395
 
377
- def update_cluster_info!(node_key = nil)
396
+ def update_cluster_info!
378
397
  @mutex.synchronize do
379
- unless node_key.nil?
380
- host, port = ::RedisClient::Cluster::NodeKey.split(node_key)
381
- @config.add_node(host, port)
382
- end
383
-
384
- @node.each(&:close)
398
+ close
385
399
  @node = fetch_cluster_info!(@config, pool: @pool, **@client_kwargs)
386
400
  end
387
401
  end
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.0.6
4
+ version: 0.0.9
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-06-19 00:00:00.000000000 Z
11
+ date: 2022-06-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis-client