Skip to content

Commit 116c4d6

Browse files
authored
refactor: parsing cluster node command reply (#201)
1 parent 637cd49 commit 116c4d6

File tree

1 file changed

+28
-19
lines changed

1 file changed

+28
-19
lines changed

lib/redis_client/cluster/node.rb

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ class Node
1818
MAX_STARTUP_SAMPLE = 37
1919
MAX_THREADS = Integer(ENV.fetch('REDIS_CLIENT_MAX_THREADS', 5))
2020
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
2124

2225
ReloadNeeded = Class.new(::RedisClient::Error)
2326

@@ -132,26 +135,32 @@ def load_info(options, **kwargs) # rubocop:disable Metrics/AbcSize, Metrics/Cycl
132135
# @see https://redis.io/commands/cluster-nodes/
133136
# @see https://github.com/redis/redis/blob/78960ad57b8a5e6af743d789ed8fd767e37d42b8/src/cluster.c#L4660-L4683
134137
def parse_cluster_node_reply(reply) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
135-
rows = reply.split("\n").map(&:split)
136-
rows.each { |arr| arr[2] = arr[2].split(',') }
137-
rows.select! { |arr| arr[7] == 'connected' && (arr[2] & %w[fail? fail handshake noaddr noflags]).empty? }
138-
rows.each do |arr|
139-
arr[1] = arr[1].split('@').first
140-
arr[2] = (arr[2] & %w[master slave]).first
141-
if arr[8].nil?
142-
arr[8] = []
143-
next
144-
end
145-
arr[8] = arr[8..].filter_map { |str| str.start_with?('[') ? nil : str.split('-').map { |s| Integer(s) } }
146-
.map { |a| a.size == 1 ? a << a.first : a }.map(&:sort)
147-
end
148-
149-
rows.map do |arr|
150-
::RedisClient::Cluster::Node::Info.new(
151-
id: arr[0], node_key: arr[1], role: arr[2], primary_id: arr[3], ping_sent: arr[4],
152-
pong_recv: arr[5], config_epoch: arr[6], link_state: arr[7], slots: arr[8]
138+
reply.each_line("\n", chomp: true).with_object(Array.new(reply.count("\n"))) do |line, acc|
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
151+
152+
acc << ::RedisClient::Cluster::Node::Info.new(
153+
id: fields[0],
154+
node_key: fields[1].split('@').first,
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
153162
)
154-
end
163+
end.compact
155164
end
156165
end
157166

0 commit comments

Comments
 (0)