Skip to content

Commit 7c00c5e

Browse files
committed
Extended "CLUSTER NODES" parser to support special slot entries (importing, migrating).
See https://redis.io/commands/cluster-nodes/#special-slot-entries
1 parent 876cafc commit 7c00c5e

File tree

2 files changed

+64
-5
lines changed

2 files changed

+64
-5
lines changed

redis/client.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -466,26 +466,49 @@ def _parse_node_line(line):
466466
line_items = line.split(" ")
467467
node_id, addr, flags, master_id, ping, pong, epoch, connected = line.split(" ")[:8]
468468
addr = addr.split("@")[0]
469-
slots = [sl.split("-") for sl in line_items[8:]]
470469
node_dict = {
471470
"node_id": node_id,
472471
"flags": flags,
473472
"master_id": master_id,
474473
"last_ping_sent": ping,
475474
"last_pong_rcvd": pong,
476475
"epoch": epoch,
477-
"slots": slots,
476+
"slots": [],
477+
"migrations": [],
478478
"connected": True if connected == "connected" else False,
479479
}
480+
if len(line_items) >= 9:
481+
slots, migrations = _parse_slots(line_items[8:])
482+
node_dict["slots"], node_dict["migrations"] = slots, migrations
480483
return addr, node_dict
481484

482485

486+
def _parse_slots(slot_ranges):
487+
slots, migrations = [], []
488+
for s_range in slot_ranges:
489+
if "->-" in s_range:
490+
slot_id, dst_node_id = s_range[1:-1].split("->-", 1)
491+
migrations.append(
492+
{"slot": slot_id, "node_id": dst_node_id, "state": "migrating"}
493+
)
494+
elif "-<-" in s_range:
495+
slot_id, src_node_id = s_range[1:-1].split("-<-", 1)
496+
migrations.append(
497+
{"slot": slot_id, "node_id": src_node_id, "state": "importing"}
498+
)
499+
else:
500+
s_range = [sl for sl in s_range.split("-")]
501+
slots.append(s_range)
502+
503+
return slots, migrations
504+
505+
483506
def parse_cluster_nodes(response, **options):
484507
"""
485-
@see: https://redis.io/commands/cluster-nodes # string
486-
@see: https://redis.io/commands/cluster-replicas # list of string
508+
@see: https://redis.io/commands/cluster-nodes # string / bytes
509+
@see: https://redis.io/commands/cluster-replicas # list of string / bytes
487510
"""
488-
if isinstance(response, str):
511+
if isinstance(response, (str, bytes)):
489512
response = response.splitlines()
490513
return dict(_parse_node_line(str_if_bytes(node)) for node in response)
491514

tests/test_cluster.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,42 @@ def test_cluster_nodes(self, r):
954954
== "c8253bae761cb1ecb2b61857d85dfe455a0fec8b"
955955
)
956956

957+
def test_cluster_nodes_importing_migrating(self, r):
958+
response = (
959+
"488ead2fcce24d8c0f158f9172cb1f4a9e040fe5 127.0.0.1:16381@26381 "
960+
"master - 0 1648975557664 3 connected 10923-16383\n"
961+
"8ae2e70812db80776f739a72374e57fc4ae6f89d 127.0.0.1:16380@26380 "
962+
"master - 0 1648975555000 2 connected 1 5461-10922 ["
963+
"2-<-ed8007ccfa2d91a7b76f8e6fba7ba7e257034a16]\n"
964+
"ed8007ccfa2d91a7b76f8e6fba7ba7e257034a16 127.0.0.1:16379@26379 "
965+
"myself,master - 0 1648975556000 1 connected 0 2-5460 ["
966+
"2->-8ae2e70812db80776f739a72374e57fc4ae6f89d]\n"
967+
)
968+
mock_all_nodes_resp(r, response)
969+
nodes = r.cluster_nodes()
970+
assert len(nodes) == 3
971+
node_16379 = nodes.get("127.0.0.1:16379")
972+
node_16380 = nodes.get("127.0.0.1:16380")
973+
node_16381 = nodes.get("127.0.0.1:16381")
974+
assert node_16379.get("migrations") == [
975+
{
976+
"slot": "2",
977+
"node_id": "8ae2e70812db80776f739a72374e57fc4ae6f89d",
978+
"state": "migrating",
979+
}
980+
]
981+
assert node_16379.get("slots") == [["0"], ["2", "5460"]]
982+
assert node_16380.get("migrations") == [
983+
{
984+
"slot": "2",
985+
"node_id": "ed8007ccfa2d91a7b76f8e6fba7ba7e257034a16",
986+
"state": "importing",
987+
}
988+
]
989+
assert node_16380.get("slots") == [["1"], ["5461", "10922"]]
990+
assert node_16381.get("slots") == [["10923", "16383"]]
991+
assert node_16381.get("migrations") == []
992+
957993
def test_cluster_replicate(self, r):
958994
node = r.get_random_node()
959995
all_replicas = r.get_replicas()

0 commit comments

Comments
 (0)