Skip to content

Commit 2ac3f82

Browse files
committed
cluster support for functions
1 parent 4a714aa commit 2ac3f82

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

redis/cluster.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,12 +289,21 @@ class RedisCluster(RedisClusterCommands):
289289
[
290290
"FLUSHALL",
291291
"FLUSHDB",
292+
"FUNCTION DELETE",
293+
"FUNCTION FLUSH",
294+
"FUNCTION LIST",
295+
"FUNCTION LOAD",
296+
"FUNCTION RESTORE",
292297
"SCRIPT EXISTS",
293298
"SCRIPT FLUSH",
294299
"SCRIPT LOAD",
295300
],
296301
PRIMARIES,
297302
),
303+
list_keys_to_dict(
304+
["FUNCTION DUMP"],
305+
RANDOM,
306+
),
298307
list_keys_to_dict(
299308
[
300309
"CLUSTER COUNTKEYSINSLOT",
@@ -843,6 +852,10 @@ def determine_slot(self, *args):
843852
else:
844853
keys = self._get_command_keys(*args)
845854
if keys is None or len(keys) == 0:
855+
# FCALL can call a function with 0 keys, that means the function
856+
# can be run on any node so we can just return a random slot
857+
if command in ("FCALL", "FCALL_RO"):
858+
return random.randrange(0, REDIS_CLUSTER_HASH_SLOTS)
846859
raise RedisClusterException(
847860
"No way to dispatch this command to Redis Cluster. "
848861
"Missing key.\nYou can execute the command by specifying "

redis/commands/cluster.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from .core import (
55
ACLCommands,
66
DataAccessCommands,
7+
FunctionCommands,
78
ManagementCommands,
89
PubSubCommands,
910
ScriptCommands,
@@ -212,6 +213,7 @@ class RedisClusterCommands(
212213
PubSubCommands,
213214
ClusterDataAccessCommands,
214215
ScriptCommands,
216+
FunctionCommands,
215217
):
216218
"""
217219
A class for all Redis Cluster commands

tests/test_function.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
return redis.call('GET', keys[1]) end)"
1111

1212

13-
@pytest.mark.onlynoncluster
1413
# @skip_if_server_version_lt("7.0.0") turn on after redis 7 release
1514
class TestFunction:
1615
@pytest.fixture(autouse=True)
@@ -44,6 +43,7 @@ def test_function_flush(self, unstable_r):
4443
with pytest.raises(ResponseError):
4544
unstable_r.function_flush("ABC")
4645

46+
@pytest.mark.onlynoncluster
4747
def test_function_list(self, unstable_r):
4848
unstable_r.function_load("Lua", "mylib", function)
4949
res = [
@@ -62,6 +62,30 @@ def test_function_list(self, unstable_r):
6262
assert unstable_r.function_list(library="*lib") == res
6363
assert unstable_r.function_list(withcode=True)[0][9] == function
6464

65+
@pytest.mark.onlynoncluster
66+
def test_function_list_on_cluster(self, unstable_r):
67+
unstable_r.function_load("Lua", "mylib", function)
68+
function_list = [
69+
[
70+
"library_name",
71+
"mylib",
72+
"engine",
73+
"LUA",
74+
"description",
75+
None,
76+
"functions",
77+
[["name", "myfunc", "description", None]],
78+
],
79+
]
80+
primaries = unstable_r.get_primaries()
81+
res = {}
82+
for node in primaries:
83+
res[node.name] = function_list
84+
assert unstable_r.function_list() == res
85+
assert unstable_r.function_list(library="*lib") == res
86+
node = primaries[0].name
87+
assert unstable_r.function_list(withcode=True)[node][0][9] == function
88+
6589
def test_fcall(self, unstable_r):
6690
unstable_r.function_load("Lua", "mylib", set_function)
6791
unstable_r.function_load("Lua", "mylib2", get_function)

0 commit comments

Comments
 (0)