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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 86d73675660702eb937b5d27925248d16b64fe46306d49da0c2b89ee49b5dc34
|
4
|
+
data.tar.gz: d2472791161a5ba746cc29c504353dc0e8414c093a531ff1017653a5a354d7dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 =
|
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
|
-
|
15
|
-
rescue ::RedisClient::
|
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', '
|
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("
|
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
|
@@ -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
|
-
|
37
|
-
|
38
|
-
errors =
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
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.
|
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, *
|
118
|
-
try_map
|
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, *
|
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, *
|
126
|
-
end
|
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, *
|
130
|
-
return call_primaries(method, *
|
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, *
|
137
|
-
end
|
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
|
-
|
245
|
-
|
246
|
-
raise ::RedisClient::Cluster::ErrorCollection, errors
|
282
|
+
[results, errors]
|
247
283
|
end
|
248
284
|
end
|
249
285
|
end
|
data/lib/redis_client/cluster.rb
CHANGED
@@ -127,8 +127,7 @@ class RedisClient
|
|
127
127
|
end
|
128
128
|
|
129
129
|
def blocking_call(timeout, *command, **kwargs)
|
130
|
-
|
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.
|
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, *
|
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'
|
191
|
-
@node.call_all(method, *
|
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, *
|
194
|
-
when '
|
195
|
-
when '
|
196
|
-
when '
|
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, *
|
199
|
-
when 'role' then @node.call_all(method, *
|
200
|
-
when 'config' then send_config_command(method, *
|
201
|
-
when 'client' then send_client_command(method, *
|
202
|
-
when 'cluster' then send_cluster_command(method, *
|
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, *
|
206
|
-
when 'script' then send_script_command(method, *
|
207
|
-
when 'pubsub' then send_pubsub_command(method, *
|
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, *
|
216
|
+
try_send(node, method, *args, **kwargs, &block)
|
213
217
|
end
|
214
|
-
rescue RedisClient::Cluster::
|
215
|
-
update_cluster_info!
|
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, *
|
220
|
-
@node.call_primaries(method, *
|
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
|
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, *
|
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, *
|
233
|
-
else assign_node(*command).send(method, *
|
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, *
|
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, *
|
240
|
-
when 'purge' then @node.call_all(method, *
|
241
|
-
else assign_node(*command).send(method, *
|
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, *
|
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, *
|
260
|
+
when 'list' then @node.call_all(method, *args, **kwargs, &block).flatten
|
248
261
|
when 'pause', 'reply', 'setname'
|
249
|
-
@node.call_all(method, *
|
250
|
-
else assign_node(*command).send(method, *
|
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, *
|
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, *
|
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, *
|
265
|
-
else assign_node(*command).send(method, *
|
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, *
|
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, *
|
289
|
+
@node.call_all(method, *args, **kwargs, &block).first
|
273
290
|
when 'flush', 'load'
|
274
|
-
@node.call_primaries(method, *
|
275
|
-
else assign_node(*command).send(method, *
|
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, *
|
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, *
|
300
|
+
when 'channels' then @node.call_all(method, *args, **kwargs, &block).flatten.uniq.sort
|
282
301
|
when 'numsub'
|
283
|
-
@node.call_all(method, *
|
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, *
|
286
|
-
else assign_node(*command).send(method, *
|
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)
|
375
|
+
def find_node_key(*command, primary_only: false)
|
357
376
|
key = @command.extract_first_key(command)
|
358
|
-
|
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
|
389
|
+
raise ::RedieClient::Cluster::NodeMightBeDown if retry_count <= 0
|
380
390
|
|
381
|
-
update_cluster_info!
|
391
|
+
update_cluster_info!
|
382
392
|
retry_count -= 1
|
383
393
|
retry
|
384
394
|
end
|
385
395
|
|
386
|
-
def update_cluster_info!
|
396
|
+
def update_cluster_info!
|
387
397
|
@mutex.synchronize do
|
388
|
-
|
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.
|
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-
|
11
|
+
date: 2022-06-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis-client
|