Skip to content

Commit 56b27c0

Browse files
committed
remove COMMAND GETKEYS call from ZUNION and ZUNIONSTORE (#4)
* make EVALSHA and EVALSHA_RO to avoid command_keys as well * make ZUNION, ZUNIONSTORE to avoid command_keys as well
1 parent d5aa066 commit 56b27c0

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

redis/cluster.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,7 @@ def determine_slot(self, *args):
956956
# redis server to parse the keys. Besides, there is a bug in redis<7.0
957957
# where `self._get_command_keys()` fails anyway. So, we special case
958958
# EVAL/EVALSHA.
959-
if command in ("EVAL", "EVALSHA"):
959+
if command in ("EVAL", "EVALSHA", "EVAL_RO", "EVALSHA_RO"):
960960
# command syntax: EVAL "script body" num_keys ...
961961
if len(args) <= 2:
962962
raise RedisClusterException(f"Invalid args in command: {args}")
@@ -967,6 +967,14 @@ def determine_slot(self, *args):
967967
if len(eval_keys) == 0:
968968
return random.randrange(0, REDIS_CLUSTER_HASH_SLOTS)
969969
keys = eval_keys
970+
elif command == "ZUNIONSTORE":
971+
# https://github.com/redis/redis/pull/12380
972+
# command syntax: ZUNIONSTORE destination numkeys key [key ...]
973+
# [WEIGHTS weight [weight ...]] [AGGREGATE <SUM | MIN | MAX>]
974+
if len(args) <= 3:
975+
raise RedisClusterException(f"Invalid args in ZUNIONSTORE: {args}")
976+
num_actual_keys = args[2]
977+
keys = (args[1],) + args[3 : 3 + num_actual_keys]
970978
else:
971979
keys = self._get_command_keys(*args)
972980
if keys is None or len(keys) == 0:

tests/test_cluster.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2006,10 +2006,30 @@ def test_cluster_zunion(self, r):
20062006
]
20072007

20082008
def test_cluster_zunionstore_sum(self, r):
2009+
assert r.zunionstore("{foo}d", ["{foo}" + str(i) for i in range(0, 256)]) == 0
2010+
20092011
r.zadd("{foo}a", {"a1": 1, "a2": 1, "a3": 1})
20102012
r.zadd("{foo}b", {"a1": 2, "a2": 2, "a3": 2})
20112013
r.zadd("{foo}c", {"a1": 6, "a3": 5, "a4": 4})
2014+
2015+
result_key = "{foo}d"
2016+
failed_keys = ["{foo1}a", "{foo}b", "{foo}c"]
2017+
with pytest.raises(
2018+
RedisClusterException,
2019+
match="ZUNIONSTORE - all keys must map to the same key slot",
2020+
):
2021+
r.zunionstore(result_key, failed_keys)
2022+
2023+
result_key = "{foo1}d"
2024+
failed_keys = ["{foo}a", "{foo}b"]
2025+
with pytest.raises(
2026+
RedisClusterException,
2027+
match="ZUNIONSTORE - all keys must map to the same key slot",
2028+
):
2029+
r.zunionstore(result_key, failed_keys)
2030+
20122031
assert r.zunionstore("{foo}d", ["{foo}a", "{foo}b", "{foo}c"]) == 4
2032+
assert r.zunionstore("{foo}e", ["{foo}a"]) == 3
20132033
assert r.zrange("{foo}d", 0, -1, withscores=True) == [
20142034
(b"a2", 3),
20152035
(b"a4", 4),

0 commit comments

Comments
 (0)