redis-cluster-client 0.3.5 → 0.3.7

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: a697c2bd33f615cb435ee48c11c301bba56cad4eac139f30db70a183d888d891
4
- data.tar.gz: 52200e9400bd7bd7fde2019c52b6cf1e26c6c019cbf1ed12a25c2167cd7ac129
3
+ metadata.gz: 5243f77ab4cb1322ddaaade9b001780e8f24d702d293f56870ce9e1109780222
4
+ data.tar.gz: fabae20f3a0d9bede270602adb247ca3cbe2b36ad42d68ecdd908320b18a31bb
5
5
  SHA512:
6
- metadata.gz: 05dc86fd1aa3cbf3cd3f0fa43d9d1c8463fcbe9e0ce1bcfe094f6095fd92d878a4bb21e6d6fa62203e91f3dc642e5869552f0b83d579cfa158b791501e1cb600
7
- data.tar.gz: 8f80c5072d4d1bdbeb3e2cb4c9f92493537a6d9002edd71426598844ba28a497171c055135bb19a1d89a325c194026195100f9a0aea89c0beac3d8e9424f7f58
6
+ metadata.gz: 999a6b334092b0e498d5e8ba773131542d212d8e5b8cb7b117811c465ccb4385b5bea11637cd8e4febdebc3d1e33c218b084e13bd5e5f1686ab477dca0f9411f
7
+ data.tar.gz: b7edede3965d1878459a128a3e7cc0f5c84b9b3e434ec44c86b408830670058b28ec023ffeeb2f0bcd1503ba5c274c46ecf791f5b03ebbdcccff09c3e3b1cf06
@@ -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,14 +34,13 @@ 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 = nil
44
- 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|
45
44
  threads = chuncked_clients.map do |k, v|
46
45
  Thread.new(k, v) do |node_key, client|
47
46
  Thread.pass
@@ -63,12 +62,9 @@ class RedisClient
63
62
 
64
63
  threads.each do |t|
65
64
  t.join
66
- latencies ||= {}
67
- latencies[t.thread_variable_get(:node_key)] = t.thread_variable_get(:latency)
65
+ acc[t.thread_variable_get(:node_key)] = t.thread_variable_get(:latency)
68
66
  end
69
67
  end
70
-
71
- latencies
72
68
  end
73
69
 
74
70
  def select_replica_clients(replications, clients)
@@ -37,7 +37,7 @@ 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
42
  node_info_list = errors = nil
43
43
  startup_options = options.to_a.sample(MAX_STARTUP_SAMPLE).to_h
@@ -83,7 +83,7 @@ class RedisClient
83
83
 
84
84
  # @see https://redis.io/commands/cluster-nodes/
85
85
  # @see https://github.com/redis/redis/blob/78960ad57b8a5e6af743d789ed8fd767e37d42b8/src/cluster.c#L4660-L4683
86
- 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
87
87
  rows = info.split("\n").map(&:split)
88
88
  rows.each { |arr| arr[2] = arr[2].split(',') }
89
89
  rows.select! { |arr| arr[7] == 'connected' && (arr[2] & %w[fail? fail handshake noaddr noflags]).empty? }
@@ -232,7 +232,7 @@ class RedisClient
232
232
  client.send(method, *args, command, &block)
233
233
  end
234
234
 
235
- [results.values, errors]
235
+ [results&.values, errors]
236
236
  end
237
237
 
238
238
  def call_multiple_nodes!(clients, method, command, args, &block)
@@ -242,7 +242,7 @@ class RedisClient
242
242
  raise ::RedisClient::Cluster::ErrorCollection, errors
243
243
  end
244
244
 
245
- def try_map(clients) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
245
+ def try_map(clients) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
246
246
  results = errors = nil
247
247
  clients.each_slice(MAX_THREADS) do |chuncked_clients|
248
248
  threads = chuncked_clients.map do |k, v|
@@ -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,84 +2,172 @@
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_row(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_row(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_row(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_row(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_row(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_row(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
140
+ def execute # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
62
141
  all_replies = errors = nil
63
- @grouped.each_slice(MAX_THREADS) do |chuncked_grouped|
64
- threads = chuncked_grouped.map do |k, v|
65
- Thread.new(@router, k, v) do |router, node_key, rows|
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|
66
145
  Thread.pass
67
- replies = do_pipelining(router.find_node(node_key), rows)
68
- 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
69
149
 
70
- Thread.current.thread_variable_set(:rows, rows)
71
150
  Thread.current.thread_variable_set(:replies, replies)
151
+ rescue ::RedisClient::Cluster::Pipeline::RedirectionNeeded => e
152
+ Thread.current.thread_variable_set(:redirection_needed, e)
72
153
  rescue StandardError => e
73
- Thread.current.thread_variable_set(:node_key, node_key)
74
154
  Thread.current.thread_variable_set(:error, e)
75
155
  end
76
156
  end
77
157
 
158
+ threads.each(&:join)
78
159
  threads.each do |t|
79
- t.join
80
160
  if t.thread_variable?(:replies)
81
161
  all_replies ||= Array.new(@size)
82
- t.thread_variable_get(:rows).each_with_index { |r, i| all_replies[r.first] = t.thread_variable_get(:replies)[i] }
162
+ @pipelines[t.thread_variable_get(:node_key)]
163
+ .outer_indices
164
+ .each_with_index { |outer, inner| all_replies[outer] = t.thread_variable_get(:replies)[inner] }
165
+ elsif t.thread_variable?(:redirection_needed)
166
+ all_replies ||= Array.new(@size)
167
+ pipeline = @pipelines[t.thread_variable_get(:node_key)]
168
+ err = t.thread_variable_get(:redirection_needed)
169
+ err.indices.each { |i| err.replies[i] = handle_redirection(err.replies[i], pipeline, i) }
170
+ pipeline.outer_indices.each_with_index { |outer, inner| all_replies[outer] = err.replies[inner] }
83
171
  elsif t.thread_variable?(:error)
84
172
  errors ||= {}
85
173
  errors[t.thread_variable_get(:node_key)] = t.thread_variable_get(:error)
@@ -87,28 +175,78 @@ class RedisClient
87
175
  end
88
176
  end
89
177
 
90
- return all_replies if errors.nil?
178
+ raise ::RedisClient::Cluster::ErrorCollection, errors unless errors.nil?
91
179
 
92
- raise ::RedisClient::Cluster::ErrorCollection, errors
180
+ all_replies
93
181
  end
94
182
 
95
183
  private
96
184
 
97
- def add_row(node_key, row)
98
- @grouped[node_key] = [] unless @grouped.key?(node_key)
99
- @grouped[node_key] << row
185
+ def append_pipeline(node_key)
186
+ @pipelines ||= {}
187
+ @pipelines[node_key] ||= ::RedisClient::Cluster::Pipeline::Extended.new(@command_builder)
188
+ @pipelines[node_key].add_outer_index(@size)
100
189
  @size += 1
190
+ @pipelines[node_key]
101
191
  end
102
192
 
103
- def do_pipelining(node, rows)
104
- node.pipelined do |pipeline|
105
- rows.each do |row|
106
- case row.size
107
- when 4 then pipeline.send(row[1], row[2], &row[3])
108
- when 5 then pipeline.send(row[1], row[2], row[3], &row[4])
109
- end
193
+ def do_pipelining(client, pipeline)
194
+ case client
195
+ when ::RedisClient then send_pipeline(client, pipeline)
196
+ when ::RedisClient::Pooled then client.with { |cli| send_pipeline(cli, pipeline) }
197
+ else raise NotImplementedError, "#{client.class.name}#pipelined for cluster client"
198
+ end
199
+ end
200
+
201
+ def send_pipeline(client, pipeline)
202
+ results = client.send(:ensure_connected, retryable: pipeline._retryable?) do |connection|
203
+ commands = pipeline._commands
204
+ ::RedisClient::Middlewares.call_pipelined(commands, client.config) do
205
+ connection.call_pipelined_aware_of_redirection(commands, pipeline._timeouts)
110
206
  end
111
207
  end
208
+
209
+ pipeline._coerce!(results)
210
+ end
211
+
212
+ def handle_redirection(err, pipeline, inner_index)
213
+ return err unless err.is_a?(::RedisClient::CommandError)
214
+
215
+ if err.message.start_with?('MOVED')
216
+ node = @router.assign_redirection_node(err.message)
217
+ try_redirection(node, pipeline, inner_index)
218
+ elsif err.message.start_with?('ASK')
219
+ node = @router.assign_asking_node(err.message)
220
+ try_asking(node) ? try_redirection(node, pipeline, inner_index) : err
221
+ else
222
+ err
223
+ end
224
+ end
225
+
226
+ def try_redirection(node, pipeline, inner_index)
227
+ redirect_command(node, pipeline, inner_index)
228
+ rescue StandardError => e
229
+ e
230
+ end
231
+
232
+ def redirect_command(node, pipeline, inner_index)
233
+ method = pipeline.get_callee_method(inner_index)
234
+ command = pipeline.get_command(inner_index)
235
+ timeout = pipeline.get_timeout(inner_index)
236
+ block = pipeline.get_block(inner_index)
237
+ args = timeout.nil? ? [] : [timeout]
238
+
239
+ if block.nil?
240
+ @router.try_send(node, method, command, args)
241
+ else
242
+ @router.try_send(node, method, command, args, &block)
243
+ end
244
+ end
245
+
246
+ def try_asking(node)
247
+ node.call('ASKING') == 'OK'
248
+ rescue StandardError
249
+ false
112
250
  end
113
251
  end
114
252
  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.5
4
+ version: 0.3.7
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-21 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