Skip to content

Commit db6533e

Browse files
authored
Merge branch 'master' into remove-redis-cluster-logs
2 parents 284be91 + e6cd4fd commit db6533e

File tree

14 files changed

+178
-172
lines changed

14 files changed

+178
-172
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,15 +1268,15 @@ Using scripting within pipelines in cluster mode is **not supported**.
12681268
When set to true, read commands will be assigned between the
12691269
primary and its replications in a Round-Robin manner.
12701270
1271-
dynamic_startup_nodes: (default=False)
1271+
dynamic_startup_nodes: (default=True)
12721272

12731273
Set the RedisCluster's startup nodes to all of the discovered nodes.
12741274
If true, the cluster's discovered nodes will be used to determine the
12751275
cluster nodes-slots mapping in the next topology refresh.
12761276
It will remove the initial passed startup nodes if their endpoints aren't
12771277
listed in the CLUSTER SLOTS output.
12781278
If you use dynamic DNS endpoints for startup nodes but CLUSTER SLOTS lists
1279-
specific IP addresses, keep it at false.
1279+
specific IP addresses, it is best to set it to false.
12801280
12811281
cluster_error_retry_attempts: (default=3)
12821282

redis/asyncio/cluster.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
from redis.cluster import (
2424
PIPELINE_BLOCKED_COMMANDS,
2525
PRIMARY,
26-
READ_COMMANDS,
2726
REPLICA,
2827
SLOT_ID,
2928
AbstractRedisCluster,
@@ -32,7 +31,7 @@
3231
get_node_name,
3332
parse_cluster_slots,
3433
)
35-
from redis.commands import AsyncRedisClusterCommands
34+
from redis.commands import READ_COMMANDS, AsyncRedisClusterCommands
3635
from redis.crc import REDIS_CLUSTER_HASH_SLOTS, key_slot
3736
from redis.exceptions import (
3837
AskError,
@@ -1350,11 +1349,17 @@ async def _execute(
13501349

13511350
nodes = {}
13521351
for cmd in todo:
1353-
target_nodes = await client._determine_nodes(*cmd.args)
1354-
if not target_nodes:
1355-
raise RedisClusterException(
1356-
f"No targets were found to execute {cmd.args} command on"
1352+
passed_targets = cmd.kwargs.pop("target_nodes", None)
1353+
if passed_targets and not client._is_node_flag(passed_targets):
1354+
target_nodes = client._parse_target_nodes(passed_targets)
1355+
else:
1356+
target_nodes = await client._determine_nodes(
1357+
*cmd.args, node_flag=passed_targets
13571358
)
1359+
if not target_nodes:
1360+
raise RedisClusterException(
1361+
f"No targets were found to execute {cmd.args} command on"
1362+
)
13581363
if len(target_nodes) > 1:
13591364
raise RedisClusterException(f"Too many targets for command {cmd.args}")
13601365

redis/client.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,8 @@ def parse_xclaim(response, **options):
310310
def parse_xautoclaim(response, **options):
311311
if options.get("parse_justid", False):
312312
return response[1]
313-
return parse_stream_list(response[1])
313+
response[1] = parse_stream_list(response[1])
314+
return response
314315

315316

316317
def parse_xinfo_stream(response, **options):

redis/cluster.py

Lines changed: 20 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from typing import Any, Callable, Dict, Tuple
99

1010
from redis.client import CaseInsensitiveDict, PubSub, Redis, parse_scan
11-
from redis.commands import CommandsParser, RedisClusterCommands
11+
from redis.commands import READ_COMMANDS, CommandsParser, RedisClusterCommands
1212
from redis.connection import ConnectionPool, DefaultParser, Encoder, parse_url
1313
from redis.crc import REDIS_CLUSTER_HASH_SLOTS, key_slot
1414
from redis.exceptions import (
@@ -150,52 +150,6 @@ def parse_cluster_shards(resp, **options):
150150
)
151151
KWARGS_DISABLED_KEYS = ("host", "port")
152152

153-
# Not complete, but covers the major ones
154-
# https://redis.io/commands
155-
READ_COMMANDS = frozenset(
156-
[
157-
"BITCOUNT",
158-
"BITPOS",
159-
"EXISTS",
160-
"GEODIST",
161-
"GEOHASH",
162-
"GEOPOS",
163-
"GEORADIUS",
164-
"GEORADIUSBYMEMBER",
165-
"GET",
166-
"GETBIT",
167-
"GETRANGE",
168-
"HEXISTS",
169-
"HGET",
170-
"HGETALL",
171-
"HKEYS",
172-
"HLEN",
173-
"HMGET",
174-
"HSTRLEN",
175-
"HVALS",
176-
"KEYS",
177-
"LINDEX",
178-
"LLEN",
179-
"LRANGE",
180-
"MGET",
181-
"PTTL",
182-
"RANDOMKEY",
183-
"SCARD",
184-
"SDIFF",
185-
"SINTER",
186-
"SISMEMBER",
187-
"SMEMBERS",
188-
"SRANDMEMBER",
189-
"STRLEN",
190-
"SUNION",
191-
"TTL",
192-
"ZCARD",
193-
"ZCOUNT",
194-
"ZRANGE",
195-
"ZSCORE",
196-
]
197-
)
198-
199153

200154
def cleanup_kwargs(**kwargs):
201155
"""
@@ -478,7 +432,7 @@ def __init__(
478432
require_full_coverage=False,
479433
reinitialize_steps=10,
480434
read_from_replicas=False,
481-
dynamic_startup_nodes=False,
435+
dynamic_startup_nodes=True,
482436
url=None,
483437
**kwargs,
484438
):
@@ -508,12 +462,12 @@ def __init__(
508462
primary and its replications in a Round-Robin manner.
509463
:dynamic_startup_nodes: 'bool'
510464
Set the RedisCluster's startup nodes to all of the discovered nodes.
511-
If true, the cluster's discovered nodes will be used to determine the
512-
cluster nodes-slots mapping in the next topology refresh.
465+
If true (default value), the cluster's discovered nodes will be used to
466+
determine the cluster nodes-slots mapping in the next topology refresh.
513467
It will remove the initial passed startup nodes if their endpoints aren't
514468
listed in the CLUSTER SLOTS output.
515469
If you use dynamic DNS endpoints for startup nodes but CLUSTER SLOTS lists
516-
specific IP addresses, keep it at false.
470+
specific IP addresses, it is best to set it to false.
517471
:cluster_error_retry_attempts: 'int'
518472
Retry command execution attempts when encountering ClusterDownError
519473
or ConnectionError
@@ -1265,7 +1219,7 @@ def __init__(
12651219
from_url=False,
12661220
require_full_coverage=False,
12671221
lock=None,
1268-
dynamic_startup_nodes=False,
1222+
dynamic_startup_nodes=True,
12691223
**kwargs,
12701224
):
12711225
self.nodes_cache = {}
@@ -1951,14 +1905,25 @@ def _send_cluster_commands(
19511905
# refer to our internal node -> slot table that
19521906
# tells us where a given
19531907
# command should route to.
1954-
node = self._determine_nodes(*c.args)
1908+
passed_targets = c.options.pop("target_nodes", None)
1909+
if passed_targets and not self._is_nodes_flag(passed_targets):
1910+
target_nodes = self._parse_target_nodes(passed_targets)
1911+
else:
1912+
target_nodes = self._determine_nodes(*c.args, node_flag=passed_targets)
1913+
if not target_nodes:
1914+
raise RedisClusterException(
1915+
f"No targets were found to execute {c.args} command on"
1916+
)
1917+
if len(target_nodes) > 1:
1918+
raise RedisClusterException(f"Too many targets for command {c.args}")
19551919

1920+
node = target_nodes[0]
19561921
# now that we know the name of the node
19571922
# ( it's just a string in the form of host:port )
19581923
# we can build a list of commands for each node.
1959-
node_name = node[0].name
1924+
node_name = node.name
19601925
if node_name not in nodes:
1961-
redis_node = self.get_redis_connection(node[0])
1926+
redis_node = self.get_redis_connection(node)
19621927
connection = get_connection(redis_node, c.args)
19631928
nodes[node_name] = NodeCommands(
19641929
redis_node.parse_response, redis_node.connection_pool, connection

redis/commands/__init__.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1-
from .cluster import AsyncRedisClusterCommands, RedisClusterCommands
1+
from .cluster import READ_COMMANDS, AsyncRedisClusterCommands, RedisClusterCommands
22
from .core import AsyncCoreCommands, CoreCommands
33
from .helpers import list_or_args
44
from .parser import CommandsParser
55
from .redismodules import AsyncRedisModuleCommands, RedisModuleCommands
66
from .sentinel import AsyncSentinelCommands, SentinelCommands
77

88
__all__ = [
9+
"AsyncCoreCommands",
910
"AsyncRedisClusterCommands",
10-
"RedisClusterCommands",
11+
"AsyncRedisModuleCommands",
12+
"AsyncSentinelCommands",
1113
"CommandsParser",
12-
"AsyncCoreCommands",
1314
"CoreCommands",
14-
"list_or_args",
15-
"AsyncRedisModuleCommands",
15+
"READ_COMMANDS",
16+
"RedisClusterCommands",
1617
"RedisModuleCommands",
17-
"AsyncSentinelCommands",
1818
"SentinelCommands",
19+
"list_or_args",
1920
]

0 commit comments

Comments
 (0)