summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordvora-h <67596500+dvora-h@users.noreply.github.com>2022-05-08 15:23:00 +0300
committerGitHub <noreply@github.com>2022-05-08 15:23:00 +0300
commitfaf55b65ffb7294b1a639cc9adb0231b987b0e32 (patch)
tree532e567a2d83598be3ef88bd14f76fb3d4f4da93
parent3a8802214a05fed4a0828b1f2965ac140e11ee32 (diff)
downloadredis-py-faf55b65ffb7294b1a639cc9adb0231b987b0e32.tar.gz
Add support for CLUSTER SHARDS (#2151)
* Add support for CLUSTER SHARDS * linters * add docstring * linters
-rw-r--r--redis/cluster.py26
-rw-r--r--redis/commands/cluster.py8
-rw-r--r--tests/test_cluster.py23
3 files changed, 56 insertions, 1 deletions
diff --git a/redis/cluster.py b/redis/cluster.py
index d42d49b..e5baee2 100644
--- a/redis/cluster.py
+++ b/redis/cluster.py
@@ -92,6 +92,26 @@ def parse_cluster_slots(resp, **options):
return slots
+def parse_cluster_shards(resp, **options):
+ """
+ Parse CLUSTER SHARDS response.
+ """
+ shards = []
+ for x in resp:
+ shard = {"slots": [], "nodes": []}
+ for i in range(0, len(x[1]), 2):
+ shard["slots"].append((x[1][i], (x[1][i + 1])))
+ nodes = x[3]
+ for node in nodes:
+ dict_node = {}
+ for i in range(0, len(node), 2):
+ dict_node[node[i]] = node[i + 1]
+ shard["nodes"].append(dict_node)
+ shards.append(shard)
+
+ return shards
+
+
PRIMARY = "primary"
REPLICA = "replica"
SLOT_ID = "slot-id"
@@ -274,6 +294,7 @@ class AbstractRedisCluster:
"CLUSTER RESET",
"CLUSTER SET-CONFIG-EPOCH",
"CLUSTER SLOTS",
+ "CLUSTER SHARDS",
"CLUSTER COUNT-FAILURE-REPORTS",
"CLUSTER KEYSLOT",
"COMMAND",
@@ -354,7 +375,10 @@ class AbstractRedisCluster:
],
)
- CLUSTER_COMMANDS_RESPONSE_CALLBACKS = {"CLUSTER SLOTS": parse_cluster_slots}
+ CLUSTER_COMMANDS_RESPONSE_CALLBACKS = {
+ "CLUSTER SLOTS": parse_cluster_slots,
+ "CLUSTER SHARDS": parse_cluster_shards,
+ }
RESULT_CALLBACKS = dict_merge(
list_keys_to_dict(["PUBSUB NUMSUB"], parse_pubsub_numsub),
diff --git a/redis/commands/cluster.py b/redis/commands/cluster.py
index 06b702f..b91b65f 100644
--- a/redis/commands/cluster.py
+++ b/redis/commands/cluster.py
@@ -581,6 +581,14 @@ class ClusterManagementCommands(ManagementCommands):
"""
return self.execute_command("CLUSTER SLOTS", target_nodes=target_nodes)
+ def cluster_shards(self, target_nodes=None):
+ """
+ Returns details about the shards of the cluster.
+
+ For more information see https://redis.io/commands/cluster-shards
+ """
+ return self.execute_command("CLUSTER SHARDS", target_nodes=target_nodes)
+
def cluster_links(self, target_node: "TargetNodesT") -> ResponseT:
"""
Each node in a Redis Cluster maintains a pair of long-lived TCP link with each
diff --git a/tests/test_cluster.py b/tests/test_cluster.py
index 376e3f8..7e64345 100644
--- a/tests/test_cluster.py
+++ b/tests/test_cluster.py
@@ -856,6 +856,29 @@ class TestClusterRedisCommands:
assert cluster_slots.get((0, 8191)) is not None
assert cluster_slots.get((0, 8191)).get("primary") == ("127.0.0.1", 7000)
+ @skip_if_server_version_lt("7.0.0")
+ @skip_if_redis_enterprise()
+ def test_cluster_shards(self, r):
+ cluster_shards = r.cluster_shards()
+ assert isinstance(cluster_shards, list)
+ assert isinstance(cluster_shards[0], dict)
+ attributes = [
+ "id",
+ "endpoint",
+ "ip",
+ "hostname",
+ "port",
+ "tls-port",
+ "role",
+ "replication-offset",
+ "health",
+ ]
+ for x in cluster_shards:
+ assert list(x.keys()) == ["slots", "nodes"]
+ for node in x["nodes"]:
+ for attribute in node.keys():
+ assert attribute in attributes
+
@skip_if_redis_enterprise()
def test_cluster_addslots(self, r):
node = r.get_random_node()