Skip to content

Commit ba4adce

Browse files
authored
fix: use hostname in node_key if present in CLUSTER NODES (#207)
2 parents 953a094 + f173f91 commit ba4adce

File tree

4 files changed

+121
-3
lines changed

4 files changed

+121
-3
lines changed

lib/redis_client/cluster/node.rb

+15-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ def parse_cluster_node_reply(reply) # rubocop:disable Metrics/AbcSize, Metrics/C
151151

152152
::RedisClient::Cluster::Node::Info.new(
153153
id: fields[0],
154-
node_key: fields[1].split('@').first,
154+
node_key: parse_node_key(fields[1]),
155155
role: (flags & ROLE_FLAGS).first,
156156
primary_id: fields[3],
157157
ping_sent: fields[4],
@@ -162,6 +162,20 @@ def parse_cluster_node_reply(reply) # rubocop:disable Metrics/AbcSize, Metrics/C
162162
)
163163
end
164164
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
165179
end
166180

167181
def initialize(

test/cluster_controller.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,6 @@ def replica_client?(client)
501501
def print_debug(msg)
502502
return unless @debug == '1'
503503

504-
p msg # rubocop:disable Lint/Debugger
504+
p msg
505505
end
506506
end

test/redis_client/cluster/test_node.rb

+104
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def test_connection_prelude
2020
end
2121
end
2222

23+
# rubocop:disable Metrics/ClassLength
2324
class TestNode < TestingWrapper
2425
def setup
2526
@test_config = ::RedisClient::ClusterConfig.new(
@@ -179,6 +180,108 @@ def test_parse_cluster_node_reply_discrete_slots_and_resharding
179180
assert_equal(want, got.map(&:to_h))
180181
end
181182

183+
def test_parse_cluster_node_reply_with_hostname
184+
info = <<~INFO
185+
07c37dfeb235213a872192d90877d0cd55635b91 127.0.0.1:30004@31004,localhost slave e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca 0 1426238317239 4 connected
186+
67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1 127.0.0.1:30002@31002,localhost master - 0 1426238316232 2 connected 5461-10922
187+
292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f 127.0.0.1:30003@31003,localhost master - 0 1426238318243 3 connected 10923-16383
188+
6ec23923021cf3ffec47632106199cb7f496ce01 127.0.0.1:30005@31005,localhost slave 67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1 0 1426238316232 5 connected
189+
824fe116063bc5fcf9f4ffd895bc17aee7731ac3 127.0.0.1:30006@31006,localhost slave 292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f 0 1426238317741 6 connected
190+
e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca 127.0.0.1:30001@31001,localhost myself,master - 0 0 1 connected 0-5460
191+
INFO
192+
193+
want = [
194+
{ id: '07c37dfeb235213a872192d90877d0cd55635b91', node_key: 'localhost:30004', role: 'slave',
195+
primary_id: 'e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca', ping_sent: '0', pong_recv: '1426238317239',
196+
config_epoch: '4', link_state: 'connected', slots: [] },
197+
{ id: '67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1', node_key: 'localhost:30002', role: 'master',
198+
primary_id: '-', ping_sent: '0', pong_recv: '1426238316232',
199+
config_epoch: '2', link_state: 'connected', slots: [[5461, 10_922]] },
200+
{ id: '292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f', node_key: 'localhost:30003', role: 'master',
201+
primary_id: '-', ping_sent: '0', pong_recv: '1426238318243',
202+
config_epoch: '3', link_state: 'connected', slots: [[10_923, 16_383]] },
203+
{ id: '6ec23923021cf3ffec47632106199cb7f496ce01', node_key: 'localhost:30005', role: 'slave',
204+
primary_id: '67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1', ping_sent: '0', pong_recv: '1426238316232',
205+
config_epoch: '5', link_state: 'connected', slots: [] },
206+
{ id: '824fe116063bc5fcf9f4ffd895bc17aee7731ac3', node_key: 'localhost:30006', role: 'slave',
207+
primary_id: '292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f', ping_sent: '0', pong_recv: '1426238317741',
208+
config_epoch: '6', link_state: 'connected', slots: [] },
209+
{ id: 'e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca', node_key: 'localhost:30001', role: 'master',
210+
primary_id: '-', ping_sent: '0', pong_recv: '0', config_epoch: '1', link_state: 'connected', slots: [[0, 5460]] }
211+
]
212+
213+
got = ::RedisClient::Cluster::Node.send(:parse_cluster_node_reply, info)
214+
assert_equal(want, got.map(&:to_h))
215+
end
216+
217+
def test_parse_cluster_node_reply_with_hostname_and_auxiliaries
218+
info = <<~INFO
219+
07c37dfeb235213a872192d90877d0cd55635b91 127.0.0.1:30004@31004,localhost,shard-id=69bc080733d1355567173199cff4a6a039a2f024 slave e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca 0 1426238317239 4 connected
220+
67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1 127.0.0.1:30002@31002,localhost,shard-id=114f6674a35b84949fe567f5dfd41415ee776261 master - 0 1426238316232 2 connected 5461-10922
221+
292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f 127.0.0.1:30003@31003,localhost,shard-id=fdb36c73e72dd027bc19811b7c219ef6e55c550e master - 0 1426238318243 3 connected 10923-16383
222+
6ec23923021cf3ffec47632106199cb7f496ce01 127.0.0.1:30005@31005,localhost,shard-id=114f6674a35b84949fe567f5dfd41415ee776261 slave 67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1 0 1426238316232 5 connected
223+
824fe116063bc5fcf9f4ffd895bc17aee7731ac3 127.0.0.1:30006@31006,localhost,shard-id=fdb36c73e72dd027bc19811b7c219ef6e55c550e slave 292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f 0 1426238317741 6 connected
224+
e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca 127.0.0.1:30001@31001,localhost,shard-id=69bc080733d1355567173199cff4a6a039a2f024 myself,master - 0 0 1 connected 0-5460
225+
INFO
226+
227+
want = [
228+
{ id: '07c37dfeb235213a872192d90877d0cd55635b91', node_key: 'localhost:30004', role: 'slave',
229+
primary_id: 'e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca', ping_sent: '0', pong_recv: '1426238317239',
230+
config_epoch: '4', link_state: 'connected', slots: [] },
231+
{ id: '67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1', node_key: 'localhost:30002', role: 'master',
232+
primary_id: '-', ping_sent: '0', pong_recv: '1426238316232',
233+
config_epoch: '2', link_state: 'connected', slots: [[5461, 10_922]] },
234+
{ id: '292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f', node_key: 'localhost:30003', role: 'master',
235+
primary_id: '-', ping_sent: '0', pong_recv: '1426238318243',
236+
config_epoch: '3', link_state: 'connected', slots: [[10_923, 16_383]] },
237+
{ id: '6ec23923021cf3ffec47632106199cb7f496ce01', node_key: 'localhost:30005', role: 'slave',
238+
primary_id: '67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1', ping_sent: '0', pong_recv: '1426238316232',
239+
config_epoch: '5', link_state: 'connected', slots: [] },
240+
{ id: '824fe116063bc5fcf9f4ffd895bc17aee7731ac3', node_key: 'localhost:30006', role: 'slave',
241+
primary_id: '292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f', ping_sent: '0', pong_recv: '1426238317741',
242+
config_epoch: '6', link_state: 'connected', slots: [] },
243+
{ id: 'e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca', node_key: 'localhost:30001', role: 'master',
244+
primary_id: '-', ping_sent: '0', pong_recv: '0', config_epoch: '1', link_state: 'connected', slots: [[0, 5460]] }
245+
]
246+
247+
got = ::RedisClient::Cluster::Node.send(:parse_cluster_node_reply, info)
248+
assert_equal(want, got.map(&:to_h))
249+
end
250+
251+
def test_parse_cluster_node_reply_with_auxiliaries
252+
info = <<~INFO
253+
07c37dfeb235213a872192d90877d0cd55635b91 127.0.0.1:30004@31004,,shard-id=69bc080733d1355567173199cff4a6a039a2f024 slave e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca 0 1426238317239 4 connected
254+
67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1 127.0.0.1:30002@31002,,shard-id=114f6674a35b84949fe567f5dfd41415ee776261 master - 0 1426238316232 2 connected 5461-10922
255+
292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f 127.0.0.1:30003@31003,,shard-id=fdb36c73e72dd027bc19811b7c219ef6e55c550e master - 0 1426238318243 3 connected 10923-16383
256+
6ec23923021cf3ffec47632106199cb7f496ce01 127.0.0.1:30005@31005,,shard-id=114f6674a35b84949fe567f5dfd41415ee776261 slave 67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1 0 1426238316232 5 connected
257+
824fe116063bc5fcf9f4ffd895bc17aee7731ac3 127.0.0.1:30006@31006,,shard-id=fdb36c73e72dd027bc19811b7c219ef6e55c550e slave 292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f 0 1426238317741 6 connected
258+
e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca 127.0.0.1:30001@31001,,shard-id=69bc080733d1355567173199cff4a6a039a2f024 myself,master - 0 0 1 connected 0-5460
259+
INFO
260+
261+
want = [
262+
{ id: '07c37dfeb235213a872192d90877d0cd55635b91', node_key: '127.0.0.1:30004', role: 'slave',
263+
primary_id: 'e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca', ping_sent: '0', pong_recv: '1426238317239',
264+
config_epoch: '4', link_state: 'connected', slots: [] },
265+
{ id: '67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1', node_key: '127.0.0.1:30002', role: 'master',
266+
primary_id: '-', ping_sent: '0', pong_recv: '1426238316232',
267+
config_epoch: '2', link_state: 'connected', slots: [[5461, 10_922]] },
268+
{ id: '292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f', node_key: '127.0.0.1:30003', role: 'master',
269+
primary_id: '-', ping_sent: '0', pong_recv: '1426238318243',
270+
config_epoch: '3', link_state: 'connected', slots: [[10_923, 16_383]] },
271+
{ id: '6ec23923021cf3ffec47632106199cb7f496ce01', node_key: '127.0.0.1:30005', role: 'slave',
272+
primary_id: '67ed2db8d677e59ec4a4cefb06858cf2a1a89fa1', ping_sent: '0', pong_recv: '1426238316232',
273+
config_epoch: '5', link_state: 'connected', slots: [] },
274+
{ id: '824fe116063bc5fcf9f4ffd895bc17aee7731ac3', node_key: '127.0.0.1:30006', role: 'slave',
275+
primary_id: '292f8b365bb7edb5e285caf0b7e6ddc7265d2f4f', ping_sent: '0', pong_recv: '1426238317741',
276+
config_epoch: '6', link_state: 'connected', slots: [] },
277+
{ id: 'e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca', node_key: '127.0.0.1:30001', role: 'master',
278+
primary_id: '-', ping_sent: '0', pong_recv: '0', config_epoch: '1', link_state: 'connected', slots: [[0, 5460]] }
279+
]
280+
281+
got = ::RedisClient::Cluster::Node.send(:parse_cluster_node_reply, info)
282+
assert_equal(want, got.map(&:to_h))
283+
end
284+
182285
def test_parse_cluster_node_reply_failure_link_state
183286
info = <<~INFO
184287
07c37dfeb235213a872192d90877d0cd55635b91 127.0.0.1:30004@31004 slave e7d1eecce10fd6bb5eb35b9f99a514335d9ba9ca 0 1426238317239 4 disconnected
@@ -506,5 +609,6 @@ def test_try_map
506609
end
507610
end
508611
end
612+
# rubocop:enable Metrics/ClassLength
509613
end
510614
end

test/test_against_cluster_scale.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def test_02_scale_in
5353
raise unless e.message.start_with?('CLUSTERDOWN Hash slot not served')
5454

5555
# FIXME: Why does the error occur?
56-
p "key#{i}" # rubocop:disable Lint/Debugger
56+
p "key#{i}"
5757
end
5858

5959
want = TEST_NODE_URIS.size

0 commit comments

Comments
 (0)