redis-cluster-client 0.0.7 → 0.0.10

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: aff938c0517542c32f98206c28f1f605a52751e2e2e9a1bd10f5576285f568ee
4
- data.tar.gz: 8a3d45fba93334959b1ee67504d2703bb116a8133ef8dac2aa8f314fdb74b268
3
+ metadata.gz: 86d73675660702eb937b5d27925248d16b64fe46306d49da0c2b89ee49b5dc34
4
+ data.tar.gz: d2472791161a5ba746cc29c504353dc0e8414c093a531ff1017653a5a354d7dd
5
5
  SHA512:
6
- metadata.gz: 63dec0155a50a0dbb7a17763c43291d371abe4e3df407340ba8edf125cf2c2bb338f607026a1d004dca489761cb2e6b5450e68a468f18799e5c3443b52a21be7
7
- data.tar.gz: 4de6c4688ca120d7f4b636bd884195b3cddc3bf8d217ea662a1f382ced46de2c9e24b0e967a801d175f0572a083b9e5ea835d54797422cf60ce799cda3002f74
6
+ metadata.gz: bd12c8ebbc013d36ead0ee5bb4f8914ad8e5dec4a302e1aa54890ba36abd2358376bc0329e94b859c9e5c5d71d1a07d11a2f9684db655fef375000e792ca5f0c
7
+ data.tar.gz: d05782f64503cc104ef789683448d967ca6d71355cdc8a1411e8a92ea98f9412ad94a7a411bc0a93ffffb5ff384f6d3fb6e48ef83cc07bf0fe907872045e2567
@@ -7,15 +7,21 @@ class RedisClient
7
7
  class Cluster
8
8
  class Command
9
9
  class << self
10
- def load(nodes)
11
- errors = nodes&.map do |node|
10
+ def load(nodes) # rubocop:disable Metrics/MethodLength
11
+ errors = []
12
+ cmd = nil
13
+ nodes&.each do |node|
14
+ break unless cmd.nil?
15
+
12
16
  reply = node.call('COMMAND')
13
17
  details = parse_command_details(reply)
14
- return ::RedisClient::Cluster::Command.new(details)
15
- rescue ::RedisClient::ConnectionError, ::RedisClient::CommandError => e
16
- e
18
+ cmd = ::RedisClient::Cluster::Command.new(details)
19
+ rescue ::RedisClient::Error => e
20
+ errors << e
17
21
  end
18
22
 
23
+ return cmd unless cmd.nil?
24
+
19
25
  raise ::RedisClient::Cluster::InitialSetupError, errors
20
26
  end
21
27
 
@@ -68,12 +74,14 @@ class RedisClient
68
74
  @details.fetch(name).fetch(key)
69
75
  end
70
76
 
71
- def determine_first_key_position(command) # rubocop:disable Metrics/CyclomaticComplexity
77
+ def determine_first_key_position(command) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
72
78
  case command&.flatten&.first.to_s.downcase
73
- when 'eval', 'evalsha', 'migrate', 'zinterstore', 'zunionstore' then 3
79
+ when 'eval', 'evalsha', 'zinterstore', 'zunionstore' then 3
74
80
  when 'object' then 2
75
81
  when 'memory'
76
82
  command[1].to_s.casecmp('usage').zero? ? 2 : 0
83
+ when 'migrate'
84
+ command[3] == '""' ? determine_optional_key_position(command, 'keys') : 3
77
85
  when 'xread', 'xreadgroup'
78
86
  determine_optional_key_position(command, 'streams')
79
87
  else
@@ -6,8 +6,6 @@ class RedisClient
6
6
  class Cluster
7
7
  ERR_ARG_NORMALIZATION = ->(arg) { Array[arg].flatten.reject { |e| e.nil? || (e.respond_to?(:empty?) && e.empty?) } }
8
8
 
9
- # Raised when client connected to redis as cluster mode
10
- # and failed to fetch cluster state information by commands.
11
9
  class InitialSetupError < ::RedisClient::Error
12
10
  def initialize(errors)
13
11
  msg = ERR_ARG_NORMALIZATION.call(errors).map(&:message).uniq.join(',')
@@ -15,8 +13,6 @@ class RedisClient
15
13
  end
16
14
  end
17
15
 
18
- # Raised when client connected to redis as cluster mode
19
- # and some cluster subcommands were called.
20
16
  class OrchestrationCommandNotSupported < ::RedisClient::Error
21
17
  def initialize(command)
22
18
  str = ERR_ARG_NORMALIZATION.call(command).map(&:to_s).join(' ').upcase
@@ -28,7 +24,6 @@ class RedisClient
28
24
  end
29
25
  end
30
26
 
31
- # Raised when error occurs on any node of cluster.
32
27
  class ErrorCollection < ::RedisClient::Error
33
28
  attr_reader :errors
34
29
 
@@ -41,15 +36,24 @@ class RedisClient
41
36
 
42
37
  @errors = errors
43
38
  messages = @errors.map { |node_key, error| "#{node_key}: #{error.message}" }
44
- super("Command errors were replied on any node: #{messages.join(', ')}")
39
+ super("Errors occurred on any node: #{messages.join(', ')}")
45
40
  end
46
41
  end
47
42
 
48
- # Raised when cluster client can't select node.
49
43
  class AmbiguousNodeError < ::RedisClient::Error
50
44
  def initialize(command)
51
45
  super("Cluster client doesn't know which node the #{command} command should be sent to.")
52
46
  end
53
47
  end
48
+
49
+ class NodeMightBeDown < ::RedisClient::Error
50
+ def initialize(_ = '')
51
+ super(
52
+ 'The client is trying to fetch the latest cluster state '\
53
+ 'because a subset of nodes might be down. '\
54
+ 'It might continue to raise errors for a while.'
55
+ )
56
+ end
57
+ end
54
58
  end
55
59
  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
@@ -87,7 +102,7 @@ class RedisClient
87
102
  end
88
103
 
89
104
  def each(&block)
90
- @clients.values.each(&block)
105
+ @clients.each_value(&block)
91
106
  end
92
107
 
93
108
  def sample
@@ -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_primaries(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_replicas(method, *command, **kwargs, &block)
130
- return call_primaries(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
 
@@ -241,9 +279,7 @@ class RedisClient
241
279
  end
242
280
 
243
281
  threads.each(&:join)
244
- return results if errors.empty?
245
-
246
- raise ::RedisClient::Cluster::ErrorCollection, errors
282
+ [results, errors]
247
283
  end
248
284
  end
249
285
  end
@@ -127,8 +127,7 @@ class RedisClient
127
127
  end
128
128
 
129
129
  def blocking_call(timeout, *command, **kwargs)
130
- node = assign_node(*command)
131
- try_send(node, :blocking_call, timeout, *command, **kwargs)
130
+ send_command(:blocking_call, timeout, *command, **kwargs)
132
131
  end
133
132
 
134
133
  def scan(*args, **kwargs, &block)
@@ -170,8 +169,10 @@ class RedisClient
170
169
  end
171
170
 
172
171
  def close
173
- @node.each(&:close)
172
+ @node.call_all(:close)
174
173
  nil
174
+ rescue StandardError
175
+ # ignore
175
176
  end
176
177
 
177
178
  private
@@ -184,106 +185,124 @@ class RedisClient
184
185
  node_info: node_info, pool: pool, with_replica: config.use_replica?, **kwargs)
185
186
  end
186
187
 
187
- 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
+
188
191
  cmd = command.first.to_s.downcase
189
192
  case cmd
190
- when 'acl', 'auth', 'bgrewriteaof', 'bgsave', 'quit', 'save', 'ping'
191
- @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
192
195
  when 'flushall', 'flushdb'
193
- @node.call_primaries(method, *command, **kwargs, &block).first
194
- when 'wait' then send_wait_command(method, *command, **kwargs, &block)
195
- when 'keys' then @node.call_replicas(method, *command, **kwargs, &block).flatten.sort
196
- when 'dbsize' then @node.call_replicas(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
197
201
  when 'scan' then _scan(*command, **kwargs)
198
- when 'lastsave' then @node.call_all(method, *command, **kwargs, &block).sort
199
- when 'role' then @node.call_all(method, *command, **kwargs, &block)
200
- when 'config' then send_config_command(method, *command, **kwargs, &block)
201
- when 'client' then send_client_command(method, *command, **kwargs, &block)
202
- 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)
203
207
  when 'readonly', 'readwrite', 'shutdown'
204
208
  raise ::RedisClient::Cluster::OrchestrationCommandNotSupported, cmd
205
- when 'memory' then send_memory_command(method, *command, **kwargs, &block)
206
- when 'script' then send_script_command(method, *command, **kwargs, &block)
207
- 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)
208
212
  when 'discard', 'exec', 'multi', 'unwatch'
209
213
  raise ::RedisClient::Cluster::AmbiguousNodeError, cmd
210
214
  else
211
215
  node = assign_node(*command)
212
- try_send(node, method, *command, **kwargs, &block)
216
+ try_send(node, method, *args, **kwargs, &block)
213
217
  end
214
- rescue RedisClient::Cluster::ErrorCollection => e
215
- update_cluster_info! if e.errors.values.map(&:class).any?(::RedisClient::ConnectionError)
216
- raise
218
+ rescue RedisClient::Cluster::Node::ReloadNeeded
219
+ update_cluster_info!
220
+ raise ::RedisClient::Cluster::NodeMightBeDown
217
221
  end
218
222
 
219
- def send_wait_command(method, *command, retry_count: 3, **kwargs, &block)
220
- @node.call_primaries(method, *command, **kwargs, &block).sum
223
+ def send_wait_command(method, *args, retry_count: 3, **kwargs, &block)
224
+ @node.call_primaries(method, *args, **kwargs, &block).sum
221
225
  rescue RedisClient::Cluster::ErrorCollection => e
222
- raise if retry_count <= 0 || e.errors.values.map(&:message).grep(/ERR WAIT cannot be used with replica instances/).empty?
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
223
230
 
224
231
  update_cluster_info!
225
232
  retry_count -= 1
226
233
  retry
227
234
  end
228
235
 
229
- 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
+
230
239
  case command[1].to_s.downcase
231
240
  when 'resetstat', 'rewrite', 'set'
232
- @node.call_all(method, *command, **kwargs, &block).first
233
- 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)
234
243
  end
235
244
  end
236
245
 
237
- 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
+
238
249
  case command[1].to_s.downcase
239
- when 'stats' then @node.call_all(method, *command, **kwargs, &block)
240
- when 'purge' then @node.call_all(method, *command, **kwargs, &block).first
241
- 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)
242
253
  end
243
254
  end
244
255
 
245
- 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
+
246
259
  case command[1].to_s.downcase
247
- when 'list' then @node.call_all(method, *command, **kwargs, &block).flatten
260
+ when 'list' then @node.call_all(method, *args, **kwargs, &block).flatten
248
261
  when 'pause', 'reply', 'setname'
249
- @node.call_all(method, *command, **kwargs, &block).first
250
- 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)
251
264
  end
252
265
  end
253
266
 
254
- def send_cluster_command(method, *command, **kwargs, &block) # rubocop:disable Metrics/MethodLength
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
255
269
  subcommand = command[1].to_s.downcase
270
+
256
271
  case subcommand
257
272
  when 'addslots', 'delslots', 'failover', 'forget', 'meet', 'replicate',
258
273
  'reset', 'set-config-epoch', 'setslot'
259
274
  raise ::RedisClient::Cluster::OrchestrationCommandNotSupported, ['cluster', subcommand]
260
- when 'saveconfig' then @node.call_all(method, *command, **kwargs, &block).first
275
+ when 'saveconfig' then @node.call_all(method, *args, **kwargs, &block).first
261
276
  when 'getkeysinslot'
262
277
  raise ArgumentError, command.join(' ') if command.size != 4
263
278
 
264
- find_node(@node.find_node_key_of_replica(command[2])).send(method, *command, **kwargs, &block)
265
- else assign_node(*command).send(method, *command, **kwargs, &block)
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)
266
281
  end
267
282
  end
268
283
 
269
- 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
+
270
287
  case command[1].to_s.downcase
271
288
  when 'debug', 'kill'
272
- @node.call_all(method, *command, **kwargs, &block).first
289
+ @node.call_all(method, *args, **kwargs, &block).first
273
290
  when 'flush', 'load'
274
- @node.call_primaries(method, *command, **kwargs, &block).first
275
- 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)
276
293
  end
277
294
  end
278
295
 
279
- 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
+
280
299
  case command[1].to_s.downcase
281
- 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
282
301
  when 'numsub'
283
- @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] }
284
303
  .reduce({}) { |a, e| a.merge(e) { |_, v1, v2| v1 + v2 } }
285
- when 'numpat' then @node.call_all(method, *command, **kwargs, &block).sum
286
- 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)
287
306
  end
288
307
  end
289
308
 
@@ -353,44 +372,30 @@ class RedisClient
353
372
  find_node(node_key)
354
373
  end
355
374
 
356
- def find_node_key(*command, primary_only: false) # rubocop:disable Metrics/MethodLength
375
+ def find_node_key(*command, primary_only: false)
357
376
  key = @command.extract_first_key(command)
358
- if key.empty?
359
- return @node.primary_node_keys.sample if @command.should_send_to_primary?(command) || primary_only
360
-
361
- return @node.replica_node_keys.sample
362
- end
363
-
364
- slot = ::RedisClient::Cluster::KeySlotConverter.convert(key)
365
- return unless @node.slot_exists?(slot)
377
+ slot = key.empty? ? nil : ::RedisClient::Cluster::KeySlotConverter.convert(key)
366
378
 
367
379
  if @command.should_send_to_primary?(command) || primary_only
368
- @node.find_node_key_of_primary(slot)
380
+ @node.find_node_key_of_primary(slot) || @node.primary_node_keys.sample
369
381
  else
370
- @node.find_node_key_of_replica(slot)
382
+ @node.find_node_key_of_replica(slot) || @node.replica_node_keys.sample
371
383
  end
372
384
  end
373
385
 
374
386
  def find_node(node_key, retry_count: 3)
375
- return @node.sample if node_key.nil?
376
-
377
387
  @node.find_by(node_key)
378
388
  rescue ::RedisClient::Cluster::Node::ReloadNeeded
379
- raise(::RedisClient::ConnectionError, 'unstable cluster state') if retry_count <= 0
389
+ raise ::RedieClient::Cluster::NodeMightBeDown if retry_count <= 0
380
390
 
381
- update_cluster_info!(node_key)
391
+ update_cluster_info!
382
392
  retry_count -= 1
383
393
  retry
384
394
  end
385
395
 
386
- def update_cluster_info!(node_key = nil)
396
+ def update_cluster_info!
387
397
  @mutex.synchronize do
388
- unless node_key.nil?
389
- host, port = ::RedisClient::Cluster::NodeKey.split(node_key)
390
- @config.add_node(host, port)
391
- end
392
-
393
- @node.each(&:close)
398
+ close
394
399
  @node = fetch_cluster_info!(@config, pool: @pool, **@client_kwargs)
395
400
  end
396
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.7
4
+ version: 0.0.10
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