redis-cluster-client 0.0.7 → 0.0.10

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: 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