redis-cluster-client 0.4.2 → 0.4.3
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 +4 -4
- data/lib/redis_client/cluster/command.rb +15 -15
- data/lib/redis_client/cluster/node.rb +44 -21
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e29792dd4eb3b7609baa8943b25a385c87dd36767ba679e9c9209be765a670b
|
4
|
+
data.tar.gz: 367d7cb722ef026b76c7f200237c1c64a0dced84026c78a43feb55a72eb7accb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3b7eb12f99b928072eeb00f4465afc5be3a3cb07aeabfc821369151f94ebbf12029409317c21b57cb628710e786e1e423b84f543b7430c23d89f71e9fe9339b
|
7
|
+
data.tar.gz: c317f99c5bb51be184f4aab415017260237e3614e535565649bb90d79a2b47c7b9edfb07c83b3a96ead85849c7bd97639ce6d60eb1f957df351908ae098f6795
|
@@ -10,6 +10,7 @@ class RedisClient
|
|
10
10
|
EMPTY_STRING = ''
|
11
11
|
LEFT_BRACKET = '{'
|
12
12
|
RIGHT_BRACKET = '}'
|
13
|
+
EMPTY_HASH = {}.freeze
|
13
14
|
|
14
15
|
Detail = Struct.new(
|
15
16
|
'RedisCommand',
|
@@ -21,15 +22,15 @@ class RedisClient
|
|
21
22
|
|
22
23
|
class << self
|
23
24
|
def load(nodes)
|
24
|
-
errors =
|
25
|
-
cmd = nil
|
26
|
-
nodes&.each do |node|
|
27
|
-
break unless cmd.nil?
|
25
|
+
cmd = errors = nil
|
28
26
|
|
27
|
+
nodes&.each do |node|
|
29
28
|
reply = node.call('COMMAND')
|
30
29
|
commands = parse_command_reply(reply)
|
31
30
|
cmd = ::RedisClient::Cluster::Command.new(commands)
|
31
|
+
break
|
32
32
|
rescue ::RedisClient::Error => e
|
33
|
+
errors ||= []
|
33
34
|
errors << e
|
34
35
|
end
|
35
36
|
|
@@ -41,21 +42,20 @@ class RedisClient
|
|
41
42
|
private
|
42
43
|
|
43
44
|
def parse_command_reply(rows)
|
44
|
-
rows&.
|
45
|
-
[
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
45
|
+
rows&.each_with_object({}) do |row, acc|
|
46
|
+
next if row[0].nil?
|
47
|
+
|
48
|
+
acc[row[0].downcase] = ::RedisClient::Cluster::Command::Detail.new(
|
49
|
+
first_key_position: row[3],
|
50
|
+
write?: row[2].include?('write'),
|
51
|
+
readonly?: row[2].include?('readonly')
|
52
|
+
)
|
53
|
+
end.freeze || EMPTY_HASH
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
57
|
def initialize(commands)
|
58
|
-
@commands = commands ||
|
58
|
+
@commands = commands || EMPTY_HASH
|
59
59
|
end
|
60
60
|
|
61
61
|
def extract_first_key(command)
|
@@ -18,6 +18,9 @@ class RedisClient
|
|
18
18
|
MAX_STARTUP_SAMPLE = 37
|
19
19
|
MAX_THREADS = Integer(ENV.fetch('REDIS_CLIENT_MAX_THREADS', 5))
|
20
20
|
IGNORE_GENERIC_CONFIG_KEYS = %i[url host port path].freeze
|
21
|
+
DEAD_FLAGS = %w[fail? fail handshake noaddr noflags].freeze
|
22
|
+
ROLE_FLAGS = %w[master slave].freeze
|
23
|
+
EMPTY_ARRAY = [].freeze
|
21
24
|
|
22
25
|
ReloadNeeded = Class.new(::RedisClient::Error)
|
23
26
|
|
@@ -118,13 +121,13 @@ class RedisClient
|
|
118
121
|
raise ::RedisClient::Cluster::InitialSetupError, errors if node_info_list.nil?
|
119
122
|
|
120
123
|
grouped = node_info_list.compact.group_by do |info_list|
|
121
|
-
info_list
|
122
|
-
|
123
|
-
|
124
|
-
|
124
|
+
info_list.sort_by!(&:id)
|
125
|
+
info_list.each_with_object(String.new(capacity: 128 * info_list.size)) do |e, a|
|
126
|
+
a << e.id << e.node_key << e.role << e.primary_id << e.config_epoch
|
127
|
+
end
|
125
128
|
end
|
126
129
|
|
127
|
-
grouped.max_by { |_, v| v.size }[1].first
|
130
|
+
grouped.max_by { |_, v| v.size }[1].first.freeze
|
128
131
|
end
|
129
132
|
|
130
133
|
private
|
@@ -132,27 +135,47 @@ class RedisClient
|
|
132
135
|
# @see https://redis.io/commands/cluster-nodes/
|
133
136
|
# @see https://github.com/redis/redis/blob/78960ad57b8a5e6af743d789ed8fd767e37d42b8/src/cluster.c#L4660-L4683
|
134
137
|
def parse_cluster_node_reply(reply) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
138
|
+
reply.each_line("\n", chomp: true).filter_map do |line|
|
139
|
+
fields = line.split
|
140
|
+
flags = fields[2].split(',')
|
141
|
+
next unless fields[7] == 'connected' && (flags & DEAD_FLAGS).empty?
|
142
|
+
|
143
|
+
slots = if fields[8].nil?
|
144
|
+
EMPTY_ARRAY
|
145
|
+
else
|
146
|
+
fields[8..].reject { |str| str.start_with?('[') }
|
147
|
+
.map { |str| str.split('-').map { |s| Integer(s) } }
|
148
|
+
.map { |a| a.size == 1 ? a << a.first : a }
|
149
|
+
.map(&:sort)
|
150
|
+
end
|
148
151
|
|
149
|
-
rows.map do |arr|
|
150
152
|
::RedisClient::Cluster::Node::Info.new(
|
151
|
-
id:
|
152
|
-
|
153
|
+
id: fields[0],
|
154
|
+
node_key: parse_node_key(fields[1]),
|
155
|
+
role: (flags & ROLE_FLAGS).first,
|
156
|
+
primary_id: fields[3],
|
157
|
+
ping_sent: fields[4],
|
158
|
+
pong_recv: fields[5],
|
159
|
+
config_epoch: fields[6],
|
160
|
+
link_state: fields[7],
|
161
|
+
slots: slots
|
153
162
|
)
|
154
163
|
end
|
155
164
|
end
|
165
|
+
|
166
|
+
# As redirection node_key is dependent on `cluster-preferred-endpoint-type` config,
|
167
|
+
# node_key should use hostname if present in CLUSTER NODES output.
|
168
|
+
#
|
169
|
+
# See https://redis.io/commands/cluster-nodes/ for details on the output format.
|
170
|
+
# node_address matches fhe format: <ip:port@cport[,hostname[,auxiliary_field=value]*]>
|
171
|
+
def parse_node_key(node_address)
|
172
|
+
ip_chunk, hostname, _auxiliaries = node_address.split(',')
|
173
|
+
ip_port_string = ip_chunk.split('@').first
|
174
|
+
return ip_port_string if hostname.nil? || hostname.empty?
|
175
|
+
|
176
|
+
port = ip_port_string.split(':')[1]
|
177
|
+
"#{hostname}:#{port}"
|
178
|
+
end
|
156
179
|
end
|
157
180
|
|
158
181
|
def initialize(
|
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.4.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Taishi Kasuga
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis-client
|
@@ -24,7 +24,7 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0.12'
|
27
|
-
description:
|
27
|
+
description:
|
28
28
|
email:
|
29
29
|
- proxy0721@gmail.com
|
30
30
|
executables: []
|
@@ -54,7 +54,7 @@ licenses:
|
|
54
54
|
metadata:
|
55
55
|
rubygems_mfa_required: 'true'
|
56
56
|
allowed_push_host: https://rubygems.org
|
57
|
-
post_install_message:
|
57
|
+
post_install_message:
|
58
58
|
rdoc_options: []
|
59
59
|
require_paths:
|
60
60
|
- lib
|
@@ -69,8 +69,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
69
69
|
- !ruby/object:Gem::Version
|
70
70
|
version: '0'
|
71
71
|
requirements: []
|
72
|
-
rubygems_version: 3.
|
73
|
-
signing_key:
|
72
|
+
rubygems_version: 3.4.6
|
73
|
+
signing_key:
|
74
74
|
specification_version: 4
|
75
75
|
summary: A Redis cluster client for Ruby
|
76
76
|
test_files: []
|