From e22e12d3cdf9570142f8c687f58c0994be8425aa Mon Sep 17 00:00:00 2001 From: vladvildanov Date: Tue, 7 Oct 2025 10:45:25 +0300 Subject: [PATCH 01/13] Added poilcy resolution method --- redis/_parsers/commands.py | 120 ++++++++++++++++++++++++++++++++++- redis/exceptions.py | 6 ++ tests/test_command_parser.py | 28 ++++++++ 3 files changed, 152 insertions(+), 2 deletions(-) diff --git a/redis/_parsers/commands.py b/redis/_parsers/commands.py index b5109252ae..55becf5825 100644 --- a/redis/_parsers/commands.py +++ b/redis/_parsers/commands.py @@ -1,11 +1,37 @@ +from dataclasses import dataclass +from enum import Enum from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, Union -from redis.exceptions import RedisError, ResponseError +from redis.exceptions import RedisError, ResponseError, IncorrectPolicyType from redis.utils import str_if_bytes if TYPE_CHECKING: from redis.asyncio.cluster import ClusterNode +class RequestPolicy(Enum): + ALL_NODES = 'all_nodes' + ALL_SHARDS = 'all_shards' + MULTI_SHARD = 'multi_shard' + SPECIAL = 'special' + DEFAULT_KEYLESS = 'default_keyless' + DEFAULT_KEYED = 'default_keyed' + +class ResponsePolicy(Enum): + ONE_SUCCEEDED = 'one_succeeded' + ALL_SUCCEEDED = 'all_succeeded' + AGG_LOGICAL_AND = 'agg_logical_and' + AGG_LOGICAL_OR = 'agg_logical_or' + AGG_MIN = 'agg_min' + AGG_MAX = 'agg_max' + AGG_SUM = 'agg_sum' + SPECIAL = 'special' + DEFAULT_KEYLESS = 'default_keyless' + DEFAULT_KEYED = 'default_keyed' + +class CommandPolicies: + def __init__(self, is_keyless: bool): + self.request_policy = RequestPolicy.DEFAULT_KEYLESS if is_keyless else RequestPolicy.DEFAULT_KEYED + self.response_policy = ResponsePolicy.DEFAULT_KEYLESS if is_keyless else ResponsePolicy.DEFAULT_KEYED class AbstractCommandsParser: def _get_pubsub_keys(self, *args): @@ -64,7 +90,8 @@ class CommandsParser(AbstractCommandsParser): def __init__(self, redis_connection): self.commands = {} - self.initialize(redis_connection) + self.redis_connection = redis_connection + self.initialize(self.redis_connection) def initialize(self, r): commands = r.command() @@ -169,6 +196,95 @@ def _get_moveable_keys(self, redis_conn, *args): raise e return keys + def get_command_policies(self) -> dict[str, CommandPolicies]: + command_with_policies = {} + + def extract_policies(data, command_name): + """ + Recursively extract policies from nested data structures. + + Args: + data: The data structure to search (can be list, dict, str, bytes, etc.) + command_name: The command name to associate with found policies + """ + if isinstance(data, (str, bytes)): + # Decode bytes to string if needed + policy = data.decode() if isinstance(data, bytes) else data + + # Check if this is a policy string + if policy.startswith('request_policy') or policy.startswith('response_policy'): + if policy.startswith('request_policy'): + policy_type = policy.split(':')[1] + + try: + command_with_policies[command_name].request_policy = RequestPolicy(policy_type) + except ValueError: + raise IncorrectPolicyType(f"Incorrect request policy type: {policy_type}") + + if policy.startswith('response_policy'): + policy_type = policy.split(':')[1] + + try: + command_with_policies[command_name].response_policy = ResponsePolicy(policy_type) + except ValueError: + raise IncorrectPolicyType(f"Incorrect response policy type: {policy_type}") + + elif isinstance(data, list): + # For lists, recursively process each element + for item in data: + extract_policies(item, command_name) + + elif isinstance(data, dict): + # For dictionaries, recursively process each value + for value in data.values(): + extract_policies(value, command_name) + + for command, details in self.commands.items(): + # Check whether the command has keys + keys = self.get_keys(self.redis_connection, command) + + if not keys: + is_keyless = False + else: + is_keyless = True + + # Create a CommandPolicies object with default policies on the new command. + command_with_policies[command] = CommandPolicies(is_keyless) + + tips = details.get('tips') + subcommands = details.get('subcommands') + + # Process subcommands + if subcommands: + for subcommand_details in subcommands: + # Get the subcommand name (first element) + if subcommand_details: + subcmd_name = subcommand_details[0] + if isinstance(subcmd_name, bytes): + subcmd_name = subcmd_name.decode() + + subcmd_name = subcmd_name.replace('|', ' ') + + # Check whether the command has keys + keys = self.get_keys(self.redis_connection, subcmd_name) + + if not keys: + is_keyless = False + else: + is_keyless = True + + # Create a CommandPolicies object with default policies on the new command. + command_with_policies[subcmd_name] = CommandPolicies(is_keyless) + + # Recursively extract policies from the rest of the subcommand details + for subcommand_detail in subcommand_details[1:]: + extract_policies(subcommand_detail, subcmd_name) + + # Process tips for the main command + if tips: + extract_policies(tips, command) + + return command_with_policies class AsyncCommandsParser(AbstractCommandsParser): """ diff --git a/redis/exceptions.py b/redis/exceptions.py index 643444986b..458ba5843f 100644 --- a/redis/exceptions.py +++ b/redis/exceptions.py @@ -245,3 +245,9 @@ class InvalidPipelineStack(RedisClusterException): """ pass + +class IncorrectPolicyType(Exception): + """ + Raised when a policy type isn't matching to any known policy types. + """ + pass \ No newline at end of file diff --git a/tests/test_command_parser.py b/tests/test_command_parser.py index e3b44a147f..e556eb3d4f 100644 --- a/tests/test_command_parser.py +++ b/tests/test_command_parser.py @@ -1,5 +1,6 @@ import pytest from redis._parsers import CommandsParser +from redis._parsers.commands import RequestPolicy, ResponsePolicy from .conftest import ( assert_resp_response, @@ -106,3 +107,30 @@ def test_get_pubsub_keys(self, r): assert commands_parser.get_keys(r, *args2) == ["foo1", "foo2", "foo3"] assert commands_parser.get_keys(r, *args3) == ["*"] assert commands_parser.get_keys(r, *args4) == ["foo1", "foo2", "foo3"] + + @skip_if_server_version_lt("7.0.0") + def test_get_command_policies(self, r): + commands_parser = CommandsParser(r) + expected_command_policies = { + 'keys': [RequestPolicy.ALL_SHARDS, ResponsePolicy.DEFAULT_KEYED], + 'acl setuser': [RequestPolicy.ALL_NODES, ResponsePolicy.ALL_SUCCEEDED], + 'exists': [RequestPolicy.MULTI_SHARD, ResponsePolicy.AGG_SUM], + 'config resetstat': [RequestPolicy.ALL_NODES, ResponsePolicy.ALL_SUCCEEDED], + 'slowlog len': [RequestPolicy.ALL_NODES, ResponsePolicy.AGG_SUM], + 'scan': [RequestPolicy.SPECIAL, ResponsePolicy.SPECIAL], + 'latency history': [RequestPolicy.ALL_NODES, ResponsePolicy.SPECIAL], + 'memory doctor': [RequestPolicy.ALL_SHARDS, ResponsePolicy.SPECIAL], + 'randomkey': [RequestPolicy.ALL_SHARDS, ResponsePolicy.SPECIAL], + 'mget': [RequestPolicy.MULTI_SHARD, ResponsePolicy.DEFAULT_KEYED], + 'function restore': [RequestPolicy.ALL_SHARDS, ResponsePolicy.ALL_SUCCEEDED], + } + + actual_policies = commands_parser.get_command_policies() + assert len(actual_policies) > 0 + + for command, command_policies in expected_command_policies.items(): + assert command in actual_policies + assert command_policies == [ + actual_policies[command].request_policy, + actual_policies[command].response_policy + ] \ No newline at end of file From 8b32b085432a3c86fca15d9be54d252d0c6b8e4b Mon Sep 17 00:00:00 2001 From: vladvildanov Date: Tue, 7 Oct 2025 11:47:52 +0300 Subject: [PATCH 02/13] Moved main command proceessing on top --- redis/_parsers/commands.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/redis/_parsers/commands.py b/redis/_parsers/commands.py index 55becf5825..d0afcc7f53 100644 --- a/redis/_parsers/commands.py +++ b/redis/_parsers/commands.py @@ -254,6 +254,10 @@ def extract_policies(data, command_name): tips = details.get('tips') subcommands = details.get('subcommands') + # Process tips for the main command + if tips: + extract_policies(tips, command) + # Process subcommands if subcommands: for subcommand_details in subcommands: @@ -280,10 +284,6 @@ def extract_policies(data, command_name): for subcommand_detail in subcommand_details[1:]: extract_policies(subcommand_detail, subcmd_name) - # Process tips for the main command - if tips: - extract_policies(tips, command) - return command_with_policies class AsyncCommandsParser(AbstractCommandsParser): From 05475eef0abda04003772bc248476047edf28f38 Mon Sep 17 00:00:00 2001 From: vladvildanov Date: Wed, 8 Oct 2025 12:22:19 +0300 Subject: [PATCH 03/13] Fixed return type and keyless detection --- redis/_parsers/commands.py | 123 +++++++++++++++++++++++++---------- tests/test_command_parser.py | 66 ++++++++++++++----- 2 files changed, 139 insertions(+), 50 deletions(-) diff --git a/redis/_parsers/commands.py b/redis/_parsers/commands.py index d0afcc7f53..507d5350f4 100644 --- a/redis/_parsers/commands.py +++ b/redis/_parsers/commands.py @@ -33,6 +33,8 @@ def __init__(self, is_keyless: bool): self.request_policy = RequestPolicy.DEFAULT_KEYLESS if is_keyless else RequestPolicy.DEFAULT_KEYED self.response_policy = ResponsePolicy.DEFAULT_KEYLESS if is_keyless else ResponsePolicy.DEFAULT_KEYED +PolicyRecords = dict[str, dict[str, CommandPolicies]] + class AbstractCommandsParser: def _get_pubsub_keys(self, *args): """ @@ -196,10 +198,63 @@ def _get_moveable_keys(self, redis_conn, *args): raise e return keys - def get_command_policies(self) -> dict[str, CommandPolicies]: + def _is_keyless_command(self, command_name: str, subcommand_name: Optional[str]=None) -> bool: + """ + Determines whether a given command or subcommand is considered "keyless". + + A keyless command does not operate on specific keys, which is determined based + on the first key position in the command or subcommand details. If the command + or subcommand's first key position is zero or negative, it is treated as keyless. + + Parameters: + command_name: str + The name of the command to check. + subcommand_name: Optional[str], default=None + The name of the subcommand to check, if applicable. If not provided, + the check is performed only on the command. + + Returns: + bool + True if the specified command or subcommand is considered keyless, + False otherwise. + + Raises: + ValueError + If the specified subcommand is not found within the command or the + specified command does not exist in the available commands. + """ + if subcommand_name: + for subcommand in self.commands.get(command_name)['subcommands']: + if str_if_bytes(subcommand[0]) == subcommand_name: + parsed_subcmd = self.parse_subcommand(subcommand) + return parsed_subcmd['first_key_pos'] <= 0 + raise ValueError(f"Subcommand {subcommand_name} not found in command {command_name}") + else: + command_details = self.commands.get(command_name, None) + if command_details is not None: + return command_details['first_key_pos'] <= 0 + + raise ValueError(f"Command {command_name} not found in commands") + + def get_command_policies(self) -> PolicyRecords: + """ + Retrieve and process the command policies for all commands and subcommands. + + This method traverses through commands and subcommands, extracting policy details + from associated data structures and constructing a dictionary of commands with their + associated policies. It supports nested data structures and handles both main commands + and their subcommands. + + Returns: + PolicyRecords: A collection of commands and subcommands associated with their + respective policies. + + Raises: + IncorrectPolicyType: If an invalid policy type is encountered during policy extraction. + """ command_with_policies = {} - def extract_policies(data, command_name): + def extract_policies(data, command_name, module_name): """ Recursively extract policies from nested data structures. @@ -217,7 +272,7 @@ def extract_policies(data, command_name): policy_type = policy.split(':')[1] try: - command_with_policies[command_name].request_policy = RequestPolicy(policy_type) + command_with_policies[module_name][command_name].request_policy = RequestPolicy(policy_type) except ValueError: raise IncorrectPolicyType(f"Incorrect request policy type: {policy_type}") @@ -225,64 +280,66 @@ def extract_policies(data, command_name): policy_type = policy.split(':')[1] try: - command_with_policies[command_name].response_policy = ResponsePolicy(policy_type) + command_with_policies[module_name][command_name].response_policy = ResponsePolicy(policy_type) except ValueError: raise IncorrectPolicyType(f"Incorrect response policy type: {policy_type}") elif isinstance(data, list): # For lists, recursively process each element for item in data: - extract_policies(item, command_name) + extract_policies(item, command_name, module_name) elif isinstance(data, dict): # For dictionaries, recursively process each value for value in data.values(): - extract_policies(value, command_name) + extract_policies(value, command_name, module_name) for command, details in self.commands.items(): # Check whether the command has keys - keys = self.get_keys(self.redis_connection, command) + is_keyless = self._is_keyless_command(command) - if not keys: - is_keyless = False + # Check if it's a core or module command + split_name = command.split('.') + + if len(split_name) > 1: + module_name = split_name[0] + command_name = split_name[1] else: - is_keyless = True + module_name = 'core' + command_name = split_name[0] # Create a CommandPolicies object with default policies on the new command. - command_with_policies[command] = CommandPolicies(is_keyless) + if command_with_policies.get(module_name, None) is None: + command_with_policies[module_name] = {command_name: CommandPolicies(is_keyless)} + else: + command_with_policies[module_name][command_name] = CommandPolicies(is_keyless) tips = details.get('tips') subcommands = details.get('subcommands') # Process tips for the main command if tips: - extract_policies(tips, command) + extract_policies(tips, command_name, module_name) # Process subcommands if subcommands: for subcommand_details in subcommands: # Get the subcommand name (first element) - if subcommand_details: - subcmd_name = subcommand_details[0] - if isinstance(subcmd_name, bytes): - subcmd_name = subcmd_name.decode() - - subcmd_name = subcmd_name.replace('|', ' ') - - # Check whether the command has keys - keys = self.get_keys(self.redis_connection, subcmd_name) - - if not keys: - is_keyless = False - else: - is_keyless = True - - # Create a CommandPolicies object with default policies on the new command. - command_with_policies[subcmd_name] = CommandPolicies(is_keyless) - - # Recursively extract policies from the rest of the subcommand details - for subcommand_detail in subcommand_details[1:]: - extract_policies(subcommand_detail, subcmd_name) + subcmd_name = subcommand_details[0] + if isinstance(subcmd_name, bytes): + subcmd_name = subcmd_name.decode() + + # Check whether the subcommand has keys + is_keyless = self._is_keyless_command(command, subcmd_name) + + subcmd_name = subcmd_name.replace('|', ' ') + + # Create a CommandPolicies object with default policies on the new command. + command_with_policies[module_name][subcmd_name] = CommandPolicies(is_keyless) + + # Recursively extract policies from the rest of the subcommand details + for subcommand_detail in subcommand_details[1:]: + extract_policies(subcommand_detail, subcmd_name, module_name) return command_with_policies diff --git a/tests/test_command_parser.py b/tests/test_command_parser.py index e556eb3d4f..bc0c4c3379 100644 --- a/tests/test_command_parser.py +++ b/tests/test_command_parser.py @@ -112,25 +112,57 @@ def test_get_pubsub_keys(self, r): def test_get_command_policies(self, r): commands_parser = CommandsParser(r) expected_command_policies = { - 'keys': [RequestPolicy.ALL_SHARDS, ResponsePolicy.DEFAULT_KEYED], - 'acl setuser': [RequestPolicy.ALL_NODES, ResponsePolicy.ALL_SUCCEEDED], - 'exists': [RequestPolicy.MULTI_SHARD, ResponsePolicy.AGG_SUM], - 'config resetstat': [RequestPolicy.ALL_NODES, ResponsePolicy.ALL_SUCCEEDED], - 'slowlog len': [RequestPolicy.ALL_NODES, ResponsePolicy.AGG_SUM], - 'scan': [RequestPolicy.SPECIAL, ResponsePolicy.SPECIAL], - 'latency history': [RequestPolicy.ALL_NODES, ResponsePolicy.SPECIAL], - 'memory doctor': [RequestPolicy.ALL_SHARDS, ResponsePolicy.SPECIAL], - 'randomkey': [RequestPolicy.ALL_SHARDS, ResponsePolicy.SPECIAL], - 'mget': [RequestPolicy.MULTI_SHARD, ResponsePolicy.DEFAULT_KEYED], - 'function restore': [RequestPolicy.ALL_SHARDS, ResponsePolicy.ALL_SUCCEEDED], + 'core': { + 'keys': ['keys', RequestPolicy.ALL_SHARDS, ResponsePolicy.DEFAULT_KEYLESS], + 'acl setuser': ['acl setuser', RequestPolicy.ALL_NODES, ResponsePolicy.ALL_SUCCEEDED], + 'exists': ['exists', RequestPolicy.MULTI_SHARD, ResponsePolicy.AGG_SUM], + 'config resetstat': ['config resetstat', RequestPolicy.ALL_NODES, ResponsePolicy.ALL_SUCCEEDED], + 'slowlog len': ['slowlog len', RequestPolicy.ALL_NODES, ResponsePolicy.AGG_SUM], + 'scan': ['scan', RequestPolicy.SPECIAL, ResponsePolicy.SPECIAL], + 'latency history': ['latency history', RequestPolicy.ALL_NODES, ResponsePolicy.SPECIAL], + 'memory doctor': ['memory doctor', RequestPolicy.ALL_SHARDS, ResponsePolicy.SPECIAL], + 'randomkey': ['randomkey', RequestPolicy.ALL_SHARDS, ResponsePolicy.SPECIAL], + 'mget': ['mget', RequestPolicy.MULTI_SHARD, ResponsePolicy.DEFAULT_KEYED], + 'function restore': ['function restore', RequestPolicy.ALL_SHARDS, ResponsePolicy.ALL_SUCCEEDED], + }, + 'json': { + 'debug': ['debug', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + 'get': ['get', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + }, + 'ft': { + 'search': ['search', RequestPolicy.DEFAULT_KEYLESS, ResponsePolicy.DEFAULT_KEYLESS], + 'create': ['create', RequestPolicy.DEFAULT_KEYLESS, ResponsePolicy.DEFAULT_KEYLESS], + }, + 'bf': { + 'add': ['add', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + 'madd': ['madd', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + }, + 'cf': { + 'add': ['add', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + 'mexists': ['mexists', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + }, + 'tdigest': { + 'add': ['add', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + 'min': ['min', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + }, + 'ts': { + 'create': ['create', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + 'info': ['info', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + }, + 'topk': { + 'list': ['list', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + 'query': ['query', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + } } actual_policies = commands_parser.get_command_policies() assert len(actual_policies) > 0 - for command, command_policies in expected_command_policies.items(): - assert command in actual_policies - assert command_policies == [ - actual_policies[command].request_policy, - actual_policies[command].response_policy - ] \ No newline at end of file + for module_name, commands in expected_command_policies.items(): + for command, command_policies in commands.items(): + assert command in actual_policies[module_name] + assert command_policies == [ + command, + actual_policies[module_name][command].request_policy, + actual_policies[module_name][command].response_policy + ] \ No newline at end of file From 87d1a326ff3517f9a4ca0b94baa07559b1ff3085 Mon Sep 17 00:00:00 2001 From: vladvildanov Date: Wed, 8 Oct 2025 16:12:37 +0300 Subject: [PATCH 04/13] Added Dynamic and Static policies --- redis/_parsers/commands.py | 39 ++- redis/commands/policies.py | 649 +++++++++++++++++++++++++++++++++++ tests/test_command_parser.py | 2 + 3 files changed, 684 insertions(+), 6 deletions(-) create mode 100644 redis/commands/policies.py diff --git a/redis/_parsers/commands.py b/redis/_parsers/commands.py index 507d5350f4..a9b4fe67b0 100644 --- a/redis/_parsers/commands.py +++ b/redis/_parsers/commands.py @@ -29,9 +29,13 @@ class ResponsePolicy(Enum): DEFAULT_KEYED = 'default_keyed' class CommandPolicies: - def __init__(self, is_keyless: bool): - self.request_policy = RequestPolicy.DEFAULT_KEYLESS if is_keyless else RequestPolicy.DEFAULT_KEYED - self.response_policy = ResponsePolicy.DEFAULT_KEYLESS if is_keyless else ResponsePolicy.DEFAULT_KEYED + def __init__( + self, + request_policy: RequestPolicy = RequestPolicy.DEFAULT_KEYLESS, + response_policy: ResponsePolicy = ResponsePolicy.DEFAULT_KEYLESS + ): + self.request_policy = request_policy + self.response_policy = response_policy PolicyRecords = dict[str, dict[str, CommandPolicies]] @@ -298,6 +302,13 @@ def extract_policies(data, command_name, module_name): # Check whether the command has keys is_keyless = self._is_keyless_command(command) + if is_keyless: + default_request_policy = RequestPolicy.DEFAULT_KEYLESS + default_response_policy = ResponsePolicy.DEFAULT_KEYLESS + else: + default_request_policy = RequestPolicy.DEFAULT_KEYED + default_response_policy = ResponsePolicy.DEFAULT_KEYED + # Check if it's a core or module command split_name = command.split('.') @@ -310,9 +321,15 @@ def extract_policies(data, command_name, module_name): # Create a CommandPolicies object with default policies on the new command. if command_with_policies.get(module_name, None) is None: - command_with_policies[module_name] = {command_name: CommandPolicies(is_keyless)} + command_with_policies[module_name] = {command_name: CommandPolicies( + request_policy=default_request_policy, + response_policy=default_response_policy + )} else: - command_with_policies[module_name][command_name] = CommandPolicies(is_keyless) + command_with_policies[module_name][command_name] = CommandPolicies( + request_policy=default_request_policy, + response_policy=default_response_policy + ) tips = details.get('tips') subcommands = details.get('subcommands') @@ -332,10 +349,20 @@ def extract_policies(data, command_name, module_name): # Check whether the subcommand has keys is_keyless = self._is_keyless_command(command, subcmd_name) + if is_keyless: + default_request_policy = RequestPolicy.DEFAULT_KEYLESS + default_response_policy = ResponsePolicy.DEFAULT_KEYLESS + else: + default_request_policy = RequestPolicy.DEFAULT_KEYED + default_response_policy = ResponsePolicy.DEFAULT_KEYED + subcmd_name = subcmd_name.replace('|', ' ') # Create a CommandPolicies object with default policies on the new command. - command_with_policies[module_name][subcmd_name] = CommandPolicies(is_keyless) + command_with_policies[module_name][subcmd_name] = CommandPolicies( + request_policy=default_request_policy, + response_policy=default_response_policy + ) # Recursively extract policies from the rest of the subcommand details for subcommand_detail in subcommand_details[1:]: diff --git a/redis/commands/policies.py b/redis/commands/policies.py new file mode 100644 index 0000000000..8853d9a6fa --- /dev/null +++ b/redis/commands/policies.py @@ -0,0 +1,649 @@ +from abc import ABC, abstractmethod +from typing import Optional + +from redis._parsers.commands import CommandPolicies, PolicyRecords, RequestPolicy, ResponsePolicy, CommandsParser + +STATIC_POLICIES: PolicyRecords = { + 'core': { + 'sinter': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'lpushx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'hexpiretime': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'lrem': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zinter': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'decr': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'msetnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'fcall_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'xinfo': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'xinfo stream': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'xinfo help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'xinfo groups': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'xinfo consumers': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'keys': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'georadiusbymember_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'renamenx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'del': CommandPolicies(request_policy=RequestPolicy.MULTI_SHARD, response_policy=ResponsePolicy.AGG_SUM), + 'discard': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'bzpopmax': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zcount': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'rpoplpush': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'sadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'ltrim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'fcall': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'exec': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'getbit': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'geohash': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'hexists': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'flushdb': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'xpending': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'hincrbyfloat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'xautoclaim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'readwrite': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'eval': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'acl': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'acl genpass': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'acl users': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'acl cat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'acl list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'acl load': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'acl getuser': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'acl help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'acl dryrun': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'acl whoami': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'acl setuser': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'acl deluser': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'acl save': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'acl log': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'hgetall': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'geosearch': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'quit': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'hvals': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zunionstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'append': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'xackdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'dump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'eval_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'hpexpiretime': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'cluster': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster set-config-epoch': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster delslots': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster nodes': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster count-failure-reports': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster flushslots': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster links': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster replicate': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster addslots': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster delslotsrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster addslotsrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster bumpepoch': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster slaves': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster replicas': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster myid': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster countkeysinslot': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster getkeysinslot': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster meet': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster setslot': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster saveconfig': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster slot-stats': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster myshardid': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster forget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster slots': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster keyslot': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster reset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster failover': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster shards': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cluster info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'sort_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'waitaof': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.AGG_MIN), + 'hexpireat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'flushall': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'zinterstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'monitor': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'sunionstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'incr': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'hmget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'type': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'publish': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'slaveof': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'hpttl': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'xrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'hello': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'zrank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'xtrim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'sync': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'replconf': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'llen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'command': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'command docs': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'command help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'command getkeysandflags': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'command list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'command count': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'command info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'command getkeys': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'sunion': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'xsetid': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'georadiusbymember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'lolwut': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'zrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'hpexpireat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'readonly': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'pfmerge': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'getrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'bitpos': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'hlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'lset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'persist': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'object': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'object help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'object encoding': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'object idletime': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'object freq': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'object refcount': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'hpersist': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'debug': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'script': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'script kill': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ONE_SUCCEEDED), + 'script debug': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'script exists': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.AGG_LOGICAL_AND), + 'script help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'script load': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'script flush': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'xreadgroup': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'mset': CommandPolicies(request_policy=RequestPolicy.MULTI_SHARD, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'brpoplpush': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'srem': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'getex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'geodist': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zrevrangebyscore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'sscan': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'xclaim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'lpos': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'expireat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'rpush': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'geopos': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'bitfield': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'touch': CommandPolicies(request_policy=RequestPolicy.MULTI_SHARD, response_policy=ResponsePolicy.AGG_SUM), + 'wait': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.AGG_MIN), + 'pttl': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'sinterstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'getset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'set': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'bitcount': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'xdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zpopmin': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'bzpopmin': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'psync': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'hgetdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zrevrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'scard': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zrevrank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'xrevrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'multi': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'psubscribe': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'exists': CommandPolicies(request_policy=RequestPolicy.MULTI_SHARD, response_policy=ResponsePolicy.AGG_SUM), + 'select': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'decrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'unwatch': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'pfcount': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'hkeys': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'smembers': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'watch': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zdiffstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'setex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'restore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'brpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zrevrangebylex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zlexcount': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'dbsize': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.AGG_SUM), + 'zincrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zrandmember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'setnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'bitop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'lcs': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'expire': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'config': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'config get': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'config set': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'config help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'config resetstat': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'config rewrite': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'pexpiretime': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'spublish': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'pfdebug': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'setrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'hsetex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'linsert': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'sdiffstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zrem': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'restore-asking': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'xread': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'copy': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'ttl': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'asking': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'hscan': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'bgsave': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'blpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'substr': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'hpexpire': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'migrate': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'module': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'module help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'module list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'module load': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'module loadex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'module unload': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'pfselftest': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'save': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'ssubscribe': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zdiff': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'lindex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zremrangebyrank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'slowlog': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'slowlog reset': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'slowlog get': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'slowlog help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'slowlog len': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.AGG_SUM), + 'replicaof': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'incrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'reset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'lmove': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'spop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'sdiff': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'evalsha_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'psetex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'lrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'client': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'client no-evict': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'client kill': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'client help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'client no-touch': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'client pause': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'client setname': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'client caching': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'client getredir': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'client tracking': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'client list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'client setinfo': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'client trackinginfo': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'client getname': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'client reply': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'client unblock': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'client unpause': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'client info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'client id': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'evalsha': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'zscore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'strlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zremrangebylex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'xadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'blmove': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'failover': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'swapdb': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'zintercard': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'hexpire': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'pexpire': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'move': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'hdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'rpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'hget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'smismember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'getdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'get': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'pubsub': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'pubsub shardchannels': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'pubsub help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'pubsub channels': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'pubsub shardnumsub': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'pubsub numpat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'pubsub numsub': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'scan': CommandPolicies(request_policy=RequestPolicy.SPECIAL, response_policy=ResponsePolicy.SPECIAL), + 'smove': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'xlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zrangestore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zrangebyscore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'punsubscribe': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'unsubscribe': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'georadius': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'sintercard': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'time': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'xdelex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'hstrlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zpopmax': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'lmpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'latency': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'latency doctor': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.SPECIAL), + 'latency history': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.SPECIAL), + 'latency help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'latency histogram': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.SPECIAL), + 'latency reset': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.AGG_SUM), + 'latency latest': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.SPECIAL), + 'latency graph': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.SPECIAL), + 'bzmpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'xack': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'ping': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'zmpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'subscribe': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'lpush': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'hrandfield': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'xgroup': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'xgroup help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'xgroup create': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'xgroup destroy': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'xgroup setid': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'xgroup createconsumer': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'xgroup delconsumer': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'memory': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'memory doctor': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.SPECIAL), + 'memory purge': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'memory help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'memory usage': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'memory malloc-stats': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.SPECIAL), + 'memory stats': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.SPECIAL), + 'rpushx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'httl': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'georadius_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'role': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'geosearchstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'pexpireat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zscan': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'randomkey': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.SPECIAL), + 'shutdown': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'rename': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'mget': CommandPolicies(request_policy=RequestPolicy.MULTI_SHARD, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'expiretime': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zcard': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'sunsubscribe': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'lpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'setbit': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'unlink': CommandPolicies(request_policy=RequestPolicy.MULTI_SHARD, response_policy=ResponsePolicy.AGG_SUM), + 'hmset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'geoadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'bitfield_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'echo': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'zrangebylex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'incrbyfloat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'info': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.SPECIAL), + 'zremrangebyscore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'hset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'hincrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'sort': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'hsetnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'blmpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'hgetex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'function': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'function list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'function load': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'function dump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'function kill': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ONE_SUCCEEDED), + 'function help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'function flush': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'function delete': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'function stats': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.SPECIAL), + 'function restore': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), + 'srandmember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'lastsave': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'zunion': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'bgrewriteaof': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'auth': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'sismember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'zmscore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'pfadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'vsim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'vinfo': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'vcard': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'vlinks': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'vrandmember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'vismember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'vrem': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'vdim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'vgetattr': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'vadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'vsetattr': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'vemb': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + }, + 'topk': { + 'list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'query': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'incrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'add': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'count': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'reserve': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + }, + 'ts': { + 'get': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'add': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'alter': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'decrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'createrule': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'madd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'del': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'revrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'create': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'mrevrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'mget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'range': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'queryindex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'incrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'deleterule': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'mrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + }, + 'tdigest': { + 'min': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'create': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'byrevrank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'rank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'byrank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'quantile': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'add': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'cdf': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'reset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'trimmed_mean': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'merge': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'max': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'revrank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + }, + 'json': { + 'get': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'arrappend': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'numpowby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'numincrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'objkeys': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'arrtrim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'toggle': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'del': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'forget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'arrlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'mget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'arrindex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'arrpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'objlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'debug': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'type': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'arrinsert': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'mset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'clear': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'nummultby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'strlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'set': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'strappend': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'merge': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'resp': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + }, + 'bf': { + 'add': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'debug': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'insert': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'madd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'reserve': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'mexists': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'loadchunk': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'card': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'scandump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'exists': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + }, + 'cf': { + 'add': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'reserve': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'insert': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'insertnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'exists': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'scandump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'mexists': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'loadchunk': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'addnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'del': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'count': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'debug': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'compact': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + }, + 'cms': { + 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'initbydim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'initbyprob': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'query': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'incrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'merge': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + }, + 'ft': { + 'explaincli': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'suglen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'profile': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'dropindex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'synadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'aliasupdate': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'alter': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'aggregate': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'syndump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + '_dropindexifx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'add': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'create': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'explain': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + '_aliasaddifnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + '_dropifx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'get': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + '_createifnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'sugget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'dictdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'aliasadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'dictadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'synupdate': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'drop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'sugadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + '_aliasdelifx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'dictdump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cursor': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + '_alterifnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'mget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'del': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'search': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + '_list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'tagvals': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'aliasdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'sugdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), + 'spellcheck': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + } +} + +class PolicyResolver(ABC): + + @abstractmethod + def resolve(self, command_name: str) -> CommandPolicies: + """ + Resolves the command name and determines the associated command policies. + + Args: + command_name: The name of the command to resolve. + + Returns: + CommandPolicies: The policies associated with the specified command. + """ + pass + + @abstractmethod + def with_fallback(self, fallback: "PolicyResolver") -> "PolicyResolver": + """ + Factory method to instantiate a policy resolver with a fallback resolver. + + Args: + fallback: Fallback resolver + + Returns: + PolicyResolver: Returns a new policy resolver with the specified fallback resolver. + """ + pass + +class BasePolicyResolver(PolicyResolver): + """ + Base class for policy resolvers. + """ + def __init__(self, policies: PolicyRecords, fallback: Optional[PolicyResolver] = None) -> None: + self._policies = policies + self._fallback = fallback + + def resolve(self, command_name: str) -> CommandPolicies: + parts = command_name.split(".") + + if len(parts) > 2: + raise ValueError(f"Wrong command or module name: {command_name}") + + module_name, command_name = parts if len(parts) == 2 else ("core", parts[0]) + + if self._policies.get(module_name, None) is None: + if self._fallback is not None: + return self._fallback.resolve(command_name) + else: + raise ValueError(f"Module {module_name} not found") + + if self._policies.get(module_name).get(command_name, None) is None: + if self._fallback is not None: + return self._fallback.resolve(command_name) + else: + raise ValueError(f"Command {command_name} not found in module {module_name}") + + return self._policies.get(module_name).get(command_name) + + @abstractmethod + def with_fallback(self, fallback: "PolicyResolver") -> "PolicyResolver": + pass + + +class DynamicPolicyResolver(BasePolicyResolver): + """ + Resolves policy dynamically based on the COMMAND output. + """ + def __init__(self, commands_parser: CommandsParser, fallback: Optional[PolicyResolver] = None) -> None: + """ + Parameters: + commands_parser (CommandsParser): COMMAND output parser. + fallback (Optional[PolicyResolver]): An optional resolver to be used when the + primary policies cannot handle a specific request. + """ + self._commands_parser = commands_parser + super().__init__(commands_parser.get_command_policies(), fallback) + + def with_fallback(self, fallback: "PolicyResolver") -> "PolicyResolver": + return DynamicPolicyResolver(self._commands_parser, fallback) + + +class StaticPolicyResolver(BasePolicyResolver): + """ + Resolves policy from a static list of policy records. + """ + def __init__(self, fallback: Optional[PolicyResolver] = None) -> None: + """ + Parameters: + fallback (Optional[PolicyResolver]): An optional fallback policy resolver + used for resolving policies if static policies are inadequate. + """ + super().__init__(STATIC_POLICIES, fallback) + + def with_fallback(self, fallback: "PolicyResolver") -> "PolicyResolver": + return StaticPolicyResolver(fallback) \ No newline at end of file diff --git a/tests/test_command_parser.py b/tests/test_command_parser.py index bc0c4c3379..cebf1de688 100644 --- a/tests/test_command_parser.py +++ b/tests/test_command_parser.py @@ -1,3 +1,5 @@ +from pprint import pprint + import pytest from redis._parsers import CommandsParser from redis._parsers.commands import RequestPolicy, ResponsePolicy From 56302a818bff8c8da9fba85a555ce4ae43c7f04b Mon Sep 17 00:00:00 2001 From: vladvildanov Date: Mon, 20 Oct 2025 11:16:48 +0300 Subject: [PATCH 05/13] Added coverage for policy resolvers --- redis/commands/policies.py | 12 +++---- tests/test_command_parser.py | 1 + tests/test_command_policies.py | 57 ++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 tests/test_command_policies.py diff --git a/redis/commands/policies.py b/redis/commands/policies.py index 8853d9a6fa..c61be47db7 100644 --- a/redis/commands/policies.py +++ b/redis/commands/policies.py @@ -594,21 +594,21 @@ def resolve(self, command_name: str) -> CommandPolicies: if len(parts) > 2: raise ValueError(f"Wrong command or module name: {command_name}") - module_name, command_name = parts if len(parts) == 2 else ("core", parts[0]) + module, command = parts if len(parts) == 2 else ("core", parts[0]) - if self._policies.get(module_name, None) is None: + if self._policies.get(module, None) is None: if self._fallback is not None: return self._fallback.resolve(command_name) else: - raise ValueError(f"Module {module_name} not found") + raise ValueError(f"Module {module} not found") - if self._policies.get(module_name).get(command_name, None) is None: + if self._policies.get(module).get(command, None) is None: if self._fallback is not None: return self._fallback.resolve(command_name) else: - raise ValueError(f"Command {command_name} not found in module {module_name}") + raise ValueError(f"Command {command} not found in module {module}") - return self._policies.get(module_name).get(command_name) + return self._policies.get(module).get(command) @abstractmethod def with_fallback(self, fallback: "PolicyResolver") -> "PolicyResolver": diff --git a/tests/test_command_parser.py b/tests/test_command_parser.py index cebf1de688..6be43e5823 100644 --- a/tests/test_command_parser.py +++ b/tests/test_command_parser.py @@ -111,6 +111,7 @@ def test_get_pubsub_keys(self, r): assert commands_parser.get_keys(r, *args4) == ["foo1", "foo2", "foo3"] @skip_if_server_version_lt("7.0.0") + @pytest.mark.onlycluster def test_get_command_policies(self, r): commands_parser = CommandsParser(r) expected_command_policies = { diff --git a/tests/test_command_policies.py b/tests/test_command_policies.py new file mode 100644 index 0000000000..e2f69cfc77 --- /dev/null +++ b/tests/test_command_policies.py @@ -0,0 +1,57 @@ +from unittest.mock import Mock + +import pytest + +from redis._parsers import CommandsParser +from redis._parsers.commands import CommandPolicies, RequestPolicy, ResponsePolicy +from redis.commands.policies import DynamicPolicyResolver, StaticPolicyResolver + + +@pytest.mark.onlycluster +class TestBasePolicyResolver: + def test_resolve(self): + mock_command_parser = Mock(spec=CommandsParser) + zcount_policy = CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED) + rpoplpush_policy = CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED) + + mock_command_parser.get_command_policies.return_value = { + 'core': { + 'zcount': zcount_policy, + 'rpoplpush': rpoplpush_policy, + } + } + + dynamic_resolver = DynamicPolicyResolver(mock_command_parser) + assert dynamic_resolver.resolve('zcount') == zcount_policy + assert dynamic_resolver.resolve('rpoplpush') == rpoplpush_policy + + with pytest.raises(ValueError, match="Wrong command or module name: foo.bar.baz"): + dynamic_resolver.resolve('foo.bar.baz') + + with pytest.raises(ValueError, match="Module foo not found"): + dynamic_resolver.resolve('foo.bar') + + with pytest.raises(ValueError, match="Command foo not found in module core"): + dynamic_resolver.resolve('core.foo') + + # Test that policy fallback correctly + static_resolver = StaticPolicyResolver() + with_fallback_dynamic_resolver = dynamic_resolver.with_fallback(static_resolver) + + assert with_fallback_dynamic_resolver.resolve('tdigest.min').request_policy == RequestPolicy.DEFAULT_KEYED + assert with_fallback_dynamic_resolver.resolve('tdigest.min').response_policy == ResponsePolicy.DEFAULT_KEYED + + # Extended chain with one more resolver + mock_command_parser = Mock(spec=CommandsParser) + foo_bar_policy = CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS) + + mock_command_parser.get_command_policies.return_value = { + 'foo': { + 'bar': foo_bar_policy, + } + } + another_dynamic_resolver = DynamicPolicyResolver(mock_command_parser) + with_fallback_static_resolver = static_resolver.with_fallback(another_dynamic_resolver) + with_double_fallback_dynamic_resolver = dynamic_resolver.with_fallback(with_fallback_static_resolver) + + assert with_double_fallback_dynamic_resolver.resolve('foo.bar') == foo_bar_policy \ No newline at end of file From 59732116ef671ba7347f20700c53c0a10fa77066 Mon Sep 17 00:00:00 2001 From: vladvildanov Date: Thu, 23 Oct 2025 11:07:13 +0300 Subject: [PATCH 06/13] Applied request policies --- redis/_parsers/commands.py | 1 + redis/cluster.py | 177 +++++++++---- redis/commands/policies.py | 529 +------------------------------------ 3 files changed, 134 insertions(+), 573 deletions(-) diff --git a/redis/_parsers/commands.py b/redis/_parsers/commands.py index a9b4fe67b0..f41e3a1c0d 100644 --- a/redis/_parsers/commands.py +++ b/redis/_parsers/commands.py @@ -11,6 +11,7 @@ class RequestPolicy(Enum): ALL_NODES = 'all_nodes' ALL_SHARDS = 'all_shards' + ANY_MASTER_SHARD = 'any_master_shard' MULTI_SHARD = 'multi_shard' SPECIAL = 'special' DEFAULT_KEYLESS = 'default_keyless' diff --git a/redis/cluster.py b/redis/cluster.py index 839721edf1..69d80a9ee4 100644 --- a/redis/cluster.py +++ b/redis/cluster.py @@ -8,15 +8,17 @@ from copy import copy from enum import Enum from itertools import chain -from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union +from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union, Mapping from redis._parsers import CommandsParser, Encoder +from redis._parsers.commands import RequestPolicy, CommandPolicies, ResponsePolicy from redis._parsers.helpers import parse_scan from redis.backoff import ExponentialWithJitterBackoff, NoBackoff from redis.cache import CacheConfig, CacheFactory, CacheFactoryInterface, CacheInterface from redis.client import EMPTY_RESPONSE, CaseInsensitiveDict, PubSub, Redis from redis.commands import READ_COMMANDS, RedisClusterCommands from redis.commands.helpers import list_or_args +from redis.commands.policies import PolicyResolver, StaticPolicyResolver, DynamicPolicyResolver from redis.connection import ( Connection, ConnectionPool, @@ -531,6 +533,7 @@ def __init__( cache: Optional[CacheInterface] = None, cache_config: Optional[CacheConfig] = None, event_dispatcher: Optional[EventDispatcher] = None, + policy_resolver: Optional[PolicyResolver] = StaticPolicyResolver(), **kwargs, ): """ @@ -712,7 +715,26 @@ def __init__( ) self.result_callbacks = CaseInsensitiveDict(self.__class__.RESULT_CALLBACKS) + self._policies_callback_mapping: dict[Union[RequestPolicy, ResponsePolicy], Callable] = { + RequestPolicy.DEFAULT_KEYLESS: lambda: [self.get_random_node()], + RequestPolicy.DEFAULT_KEYED: lambda *args: self.get_node_from_slot(*args), + RequestPolicy.ALL_SHARDS: self.get_primaries, + RequestPolicy.ALL_NODES: self.get_nodes, + RequestPolicy.ANY_MASTER_SHARD: lambda: [self.get_random_primary_node()], + RequestPolicy.MULTI_SHARD: lambda *args, **kwargs: self._split_multi_shard_command(*args, **kwargs), + RequestPolicy.SPECIAL: self.get_special_nodes, + ResponsePolicy.DEFAULT_KEYLESS: lambda res: res, + ResponsePolicy.DEFAULT_KEYED: lambda res: res, + ResponsePolicy.ONE_SUCCEEDED: lambda res: res, + ResponsePolicy.ALL_SUCCEEDED: lambda res: self._evaluate_all_succeeded(res) + } + + # Needs for a commands parser to successfully execute COMMAND + self._policy_resolver = policy_resolver self.commands_parser = CommandsParser(self) + + # Node where FT.AGGREGATE command is executed. + self._aggregate_nodes = None self._lock = threading.RLock() def __enter__(self): @@ -804,6 +826,74 @@ def get_default_node(self): """ return self.nodes_manager.default_node + def get_node_from_slot(self, *args): + """ + Returns a list of nodes that hold the specified keys' slots. + """ + # get the node that holds the key's slot + slot = self.determine_slot(*args) + node = self.nodes_manager.get_node_from_slot( + slot, + self.read_from_replicas and command in READ_COMMANDS, + self.load_balancing_strategy if command in READ_COMMANDS else None, + ) + return [node] + + def _split_multi_shard_command(self, *args, **kwargs) -> list[dict]: + """ + Splits the command with Multi-Shard policy, to the multiple commands + """ + keys = self._get_command_keys(*args) + commands = [] + + for key in keys: + commands.append({ + 'args': (args[0], key), + 'kwargs': kwargs, + }) + + return commands + + def get_special_nodes(self) -> Optional[list["ClusterNode"]]: + """ + Returns a list of nodes for commands with a special policy. + """ + if not self._aggregate_nodes: + raise RedisClusterException('Cannot execute FT.CURSOR commands without FT.AGGREGATE') + + return self._aggregate_nodes + + def get_random_primary_node(self) -> "ClusterNode": + """ + Returns a random primary node + """ + return random.choice(self.get_primaries()) + + def _evaluate_all_succeeded(self, res): + """ + Evaluate the result of a command with ResponsePolicy.ALL_SUCCEEDED + """ + first_successful_response = None + + if isinstance(res, dict): + for key, value in res.items(): + if value: + if first_successful_response is None: + first_successful_response = {key: value} + else: + return {key: False} + else: + for response in res: + if response: + if first_successful_response is None: + # Dynamically resolve type + first_successful_response = type(response)(response) + else: + return type(response)(False) + + return first_successful_response + + def set_default_node(self, node): """ Set the default node of the cluster. @@ -953,46 +1043,21 @@ def set_response_callback(self, command, callback): """Set a custom Response Callback""" self.cluster_response_callbacks[command] = callback - def _determine_nodes(self, *args, **kwargs) -> List["ClusterNode"]: - # Determine which nodes should be executed the command on. - # Returns a list of target nodes. - command = args[0].upper() - if len(args) >= 2 and f"{args[0]} {args[1]}".upper() in self.command_flags: - command = f"{args[0]} {args[1]}".upper() + def _determine_nodes(self, *args, request_policy: RequestPolicy) -> List["ClusterNode"]: + """ + Determines a nodes the command should be executed on. + """ + policy_callback = self._policies_callback_mapping[request_policy] - nodes_flag = kwargs.pop("nodes_flag", None) - if nodes_flag is not None: - # nodes flag passed by the user - command_flag = nodes_flag - else: - # get the nodes group for this command if it was predefined - command_flag = self.command_flags.get(command) - if command_flag == self.__class__.RANDOM: - # return a random node - return [self.get_random_node()] - elif command_flag == self.__class__.PRIMARIES: - # return all primaries - return self.get_primaries() - elif command_flag == self.__class__.REPLICAS: - # return all replicas - return self.get_replicas() - elif command_flag == self.__class__.ALL_NODES: - # return all nodes - return self.get_nodes() - elif command_flag == self.__class__.DEFAULT_NODE: - # return the cluster's default node - return [self.nodes_manager.default_node] - elif command in self.__class__.SEARCH_COMMANDS[0]: - return [self.nodes_manager.default_node] + if request_policy == RequestPolicy.DEFAULT_KEYED: + target_nodes = policy_callback(*args) else: - # get the node that holds the key's slot - slot = self.determine_slot(*args) - node = self.nodes_manager.get_node_from_slot( - slot, - self.read_from_replicas and command in READ_COMMANDS, - self.load_balancing_strategy if command in READ_COMMANDS else None, - ) - return [node] + target_nodes = policy_callback() + + if args[0].lower() == "ft.aggregate": + self._aggregate_nodes = target_nodes + + return target_nodes def _should_reinitialized(self): # To reinitialize the cluster on every MOVED error, @@ -1142,6 +1207,7 @@ def _internal_execute_command(self, *args, **kwargs): is_default_node = False target_nodes = None passed_targets = kwargs.pop("target_nodes", None) + command_policies = self._policy_resolver.resolve(args[0].lower()) if passed_targets is not None and not self._is_nodes_flag(passed_targets): target_nodes = self._parse_target_nodes(passed_targets) target_nodes_specified = True @@ -1160,9 +1226,24 @@ def _internal_execute_command(self, *args, **kwargs): try: res = {} if not target_nodes_specified: + if command_policies.request_policy == RequestPolicy.MULTI_SHARD: + commands = self._policies_callback_mapping[command_policies.request_policy](*args, **kwargs) + + for command in commands: + target_nodes = self.get_node_from_slot(*command['args']) + + if not target_nodes: + raise RedisClusterException( + f"No targets were found to execute {args} command on" + ) + + res[target_nodes[0].name] = self._execute_command(target_nodes[0], *command['args'], **command['kwargs']) + + return self._process_result(args[0], res, response_policy=command_policies.response_policy) + # Determine the nodes to execute the command on target_nodes = self._determine_nodes( - *args, **kwargs, nodes_flag=passed_targets + *args, request_policy=command_policies.request_policy ) if not target_nodes: raise RedisClusterException( @@ -1175,8 +1256,12 @@ def _internal_execute_command(self, *args, **kwargs): is_default_node = True for node in target_nodes: res[node.name] = self._execute_command(node, *args, **kwargs) + + if command_policies.response_policy == ResponsePolicy.ONE_SUCCEEDED: + break + # Return the processed result - return self._process_result(args[0], res, **kwargs) + return self._process_result(args[0], res, response_policy=command_policies.response_policy, **kwargs) except Exception as e: if retry_attempts > 0 and type(e) in self.__class__.ERRORS_ALLOW_RETRY: if is_default_node: @@ -1316,7 +1401,7 @@ def close(self) -> None: # RedisCluster's __init__ can fail before nodes_manager is set pass - def _process_result(self, command, res, **kwargs): + def _process_result(self, command, res, response_policy: ResponsePolicy, **kwargs): """ Process the result of the executed command. The function would return a dict or a single value. @@ -1328,13 +1413,13 @@ def _process_result(self, command, res, **kwargs): Dict """ if command in self.result_callbacks: - return self.result_callbacks[command](command, res, **kwargs) + res = self.result_callbacks[command](command, res, **kwargs) elif len(res) == 1: # When we execute the command on a single node, we can # remove the dictionary and return a single response - return list(res.values())[0] - else: - return res + res = list(res.values())[0] + + return self._policies_callback_mapping[response_policy](res) def load_external_module(self, funcname, func): """ diff --git a/redis/commands/policies.py b/redis/commands/policies.py index c61be47db7..bbfb56afec 100644 --- a/redis/commands/policies.py +++ b/redis/commands/policies.py @@ -4,513 +4,6 @@ from redis._parsers.commands import CommandPolicies, PolicyRecords, RequestPolicy, ResponsePolicy, CommandsParser STATIC_POLICIES: PolicyRecords = { - 'core': { - 'sinter': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lpushx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hexpiretime': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lrem': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zinter': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'decr': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'msetnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'fcall_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'xinfo': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'xinfo stream': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xinfo help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'xinfo groups': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xinfo consumers': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'keys': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'georadiusbymember_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'renamenx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'del': CommandPolicies(request_policy=RequestPolicy.MULTI_SHARD, response_policy=ResponsePolicy.AGG_SUM), - 'discard': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'bzpopmax': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zcount': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'rpoplpush': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'sadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'ltrim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'fcall': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'exec': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'getbit': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'geohash': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hexists': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'flushdb': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'xpending': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hincrbyfloat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xautoclaim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'readwrite': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'eval': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl genpass': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl users': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl cat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl load': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl getuser': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl dryrun': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl whoami': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl setuser': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'acl deluser': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'acl save': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'acl log': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'hgetall': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'geosearch': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'quit': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'hvals': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zunionstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'append': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xackdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'dump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'eval_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'hpexpiretime': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'cluster': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster set-config-epoch': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster delslots': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster nodes': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster count-failure-reports': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster flushslots': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster links': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster replicate': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster addslots': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster delslotsrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster addslotsrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster bumpepoch': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster slaves': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster replicas': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster myid': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster countkeysinslot': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster getkeysinslot': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster meet': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster setslot': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster saveconfig': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster slot-stats': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster myshardid': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster forget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster slots': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster keyslot': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster reset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster failover': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster shards': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'sort_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'waitaof': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.AGG_MIN), - 'hexpireat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'flushall': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'zinterstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'monitor': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'sunionstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'incr': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hmget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'type': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'publish': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'slaveof': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'hpttl': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hello': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'zrank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xtrim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'sync': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'replconf': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'llen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'command': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'command docs': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'command help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'command getkeysandflags': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'command list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'command count': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'command info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'command getkeys': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'sunion': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xsetid': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'georadiusbymember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lolwut': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'zrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hpexpireat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'readonly': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'pfmerge': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'getrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'bitpos': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'persist': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'object': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'object help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'object encoding': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'object idletime': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'object freq': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'object refcount': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hpersist': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'debug': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'script': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'script kill': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ONE_SUCCEEDED), - 'script debug': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'script exists': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.AGG_LOGICAL_AND), - 'script help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'script load': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'script flush': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'xreadgroup': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'mset': CommandPolicies(request_policy=RequestPolicy.MULTI_SHARD, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'brpoplpush': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'srem': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'getex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'geodist': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zrevrangebyscore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'sscan': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xclaim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lpos': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'expireat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'rpush': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'geopos': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'bitfield': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'touch': CommandPolicies(request_policy=RequestPolicy.MULTI_SHARD, response_policy=ResponsePolicy.AGG_SUM), - 'wait': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.AGG_MIN), - 'pttl': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'sinterstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'getset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'set': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'bitcount': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zpopmin': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'bzpopmin': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'psync': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'hgetdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zrevrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'scard': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zrevrank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xrevrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'multi': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'psubscribe': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'exists': CommandPolicies(request_policy=RequestPolicy.MULTI_SHARD, response_policy=ResponsePolicy.AGG_SUM), - 'select': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'decrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'unwatch': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'pfcount': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hkeys': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'smembers': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'watch': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zdiffstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'setex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'restore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'brpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zrevrangebylex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zlexcount': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'dbsize': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.AGG_SUM), - 'zincrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zrandmember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'setnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'bitop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lcs': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'expire': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'config': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'config get': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'config set': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'config help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'config resetstat': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'config rewrite': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'pexpiretime': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'spublish': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'pfdebug': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'setrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hsetex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'linsert': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'sdiffstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zrem': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'restore-asking': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xread': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'copy': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'ttl': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'asking': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'hscan': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'bgsave': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'blpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'substr': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hpexpire': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'migrate': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'module': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'module help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'module list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'module load': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'module loadex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'module unload': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'pfselftest': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'save': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'ssubscribe': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zdiff': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'lindex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zremrangebyrank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'slowlog': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'slowlog reset': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'slowlog get': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'slowlog help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'slowlog len': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.AGG_SUM), - 'replicaof': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'incrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'reset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'lmove': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'spop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'sdiff': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'evalsha_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'psetex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'client': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client no-evict': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client kill': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client no-touch': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client pause': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client setname': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'client caching': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client getredir': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client tracking': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client setinfo': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'client trackinginfo': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client getname': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client reply': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client unblock': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client unpause': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client id': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'evalsha': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'zscore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'strlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zremrangebylex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'blmove': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'failover': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'swapdb': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'zintercard': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'hexpire': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'pexpire': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'move': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'rpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'smismember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'getdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'get': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'pubsub': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'pubsub shardchannels': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'pubsub help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'pubsub channels': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'pubsub shardnumsub': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'pubsub numpat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'pubsub numsub': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'scan': CommandPolicies(request_policy=RequestPolicy.SPECIAL, response_policy=ResponsePolicy.SPECIAL), - 'smove': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zrangestore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zrangebyscore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'punsubscribe': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'unsubscribe': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'georadius': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'sintercard': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'time': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'xdelex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hstrlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zpopmax': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lmpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'latency': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'latency doctor': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.SPECIAL), - 'latency history': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.SPECIAL), - 'latency help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'latency histogram': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.SPECIAL), - 'latency reset': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.AGG_SUM), - 'latency latest': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.SPECIAL), - 'latency graph': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.SPECIAL), - 'bzmpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'xack': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'ping': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'zmpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'subscribe': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'lpush': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hrandfield': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xgroup': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'xgroup help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'xgroup create': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xgroup destroy': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xgroup setid': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xgroup createconsumer': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xgroup delconsumer': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'memory': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'memory doctor': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.SPECIAL), - 'memory purge': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'memory help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'memory usage': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'memory malloc-stats': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.SPECIAL), - 'memory stats': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.SPECIAL), - 'rpushx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'httl': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'georadius_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'role': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'geosearchstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'pexpireat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zscan': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'randomkey': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.SPECIAL), - 'shutdown': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'rename': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'mget': CommandPolicies(request_policy=RequestPolicy.MULTI_SHARD, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'expiretime': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zcard': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'sunsubscribe': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'setbit': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'unlink': CommandPolicies(request_policy=RequestPolicy.MULTI_SHARD, response_policy=ResponsePolicy.AGG_SUM), - 'hmset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'geoadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'bitfield_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'echo': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'zrangebylex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'incrbyfloat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'info': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.SPECIAL), - 'zremrangebyscore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hincrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'sort': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hsetnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'blmpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'hgetex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'function': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'function list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'function load': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'function dump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'function kill': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ONE_SUCCEEDED), - 'function help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'function flush': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'function delete': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'function stats': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.SPECIAL), - 'function restore': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'srandmember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lastsave': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'zunion': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'bgrewriteaof': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'auth': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'sismember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zmscore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'pfadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vsim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vinfo': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vcard': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vlinks': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vrandmember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vismember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vrem': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vdim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vgetattr': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vsetattr': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vemb': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - }, - 'topk': { - 'list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'query': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'incrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'add': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'count': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'reserve': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - }, - 'ts': { - 'get': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'add': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'alter': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'decrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'createrule': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'madd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'del': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'revrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'create': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'mrevrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'mget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'range': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'queryindex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'incrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'deleterule': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'mrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - }, - 'tdigest': { - 'min': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'create': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'byrevrank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'rank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'byrank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'quantile': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'add': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'cdf': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'reset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'trimmed_mean': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'merge': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'max': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'revrank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - }, - 'json': { - 'get': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'arrappend': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'numpowby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'numincrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'objkeys': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'arrtrim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'toggle': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'del': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'forget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'arrlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'mget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'arrindex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'arrpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'objlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'debug': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'type': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'arrinsert': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'mset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'clear': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'nummultby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'strlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'set': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'strappend': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'merge': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'resp': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - }, - 'bf': { - 'add': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'debug': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'insert': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'madd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'reserve': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'mexists': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'loadchunk': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'card': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'scandump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'exists': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - }, - 'cf': { - 'add': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'reserve': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'insert': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'insertnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'exists': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'scandump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'mexists': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'loadchunk': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'addnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'del': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'count': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'debug': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'compact': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - }, - 'cms': { - 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'initbydim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'initbyprob': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'query': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'incrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'merge': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - }, 'ft': { 'explaincli': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'suglen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), @@ -523,7 +16,7 @@ 'syndump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), '_dropindexifx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'add': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'create': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'create': CommandPolicies(request_policy=RequestPolicy.ANY_MASTER_SHARD, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'explain': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), '_aliasaddifnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), '_dropifx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), @@ -539,7 +32,7 @@ 'sugadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), '_aliasdelifx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'dictdump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cursor': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cursor': CommandPolicies(request_policy=RequestPolicy.SPECIAL, response_policy=ResponsePolicy.DEFAULT_KEYLESS), '_alterifnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'mget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'del': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), @@ -615,24 +108,6 @@ def with_fallback(self, fallback: "PolicyResolver") -> "PolicyResolver": pass -class DynamicPolicyResolver(BasePolicyResolver): - """ - Resolves policy dynamically based on the COMMAND output. - """ - def __init__(self, commands_parser: CommandsParser, fallback: Optional[PolicyResolver] = None) -> None: - """ - Parameters: - commands_parser (CommandsParser): COMMAND output parser. - fallback (Optional[PolicyResolver]): An optional resolver to be used when the - primary policies cannot handle a specific request. - """ - self._commands_parser = commands_parser - super().__init__(commands_parser.get_command_policies(), fallback) - - def with_fallback(self, fallback: "PolicyResolver") -> "PolicyResolver": - return DynamicPolicyResolver(self._commands_parser, fallback) - - class StaticPolicyResolver(BasePolicyResolver): """ Resolves policy from a static list of policy records. From 57da14e64c086b847b33c83bcb1fa1fb07696ad9 Mon Sep 17 00:00:00 2001 From: vladvildanov Date: Thu, 23 Oct 2025 11:15:05 +0300 Subject: [PATCH 07/13] Removed all policies except search (phase 1) --- redis/commands/policies.py | 519 ------------------------------------- 1 file changed, 519 deletions(-) diff --git a/redis/commands/policies.py b/redis/commands/policies.py index c61be47db7..a2f7f45924 100644 --- a/redis/commands/policies.py +++ b/redis/commands/policies.py @@ -4,531 +4,17 @@ from redis._parsers.commands import CommandPolicies, PolicyRecords, RequestPolicy, ResponsePolicy, CommandsParser STATIC_POLICIES: PolicyRecords = { - 'core': { - 'sinter': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lpushx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hexpiretime': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lrem': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zinter': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'decr': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'msetnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'fcall_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'xinfo': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'xinfo stream': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xinfo help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'xinfo groups': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xinfo consumers': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'keys': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'georadiusbymember_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'renamenx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'del': CommandPolicies(request_policy=RequestPolicy.MULTI_SHARD, response_policy=ResponsePolicy.AGG_SUM), - 'discard': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'bzpopmax': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zcount': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'rpoplpush': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'sadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'ltrim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'fcall': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'exec': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'getbit': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'geohash': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hexists': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'flushdb': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'xpending': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hincrbyfloat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xautoclaim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'readwrite': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'eval': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl genpass': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl users': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl cat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl load': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl getuser': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl dryrun': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl whoami': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'acl setuser': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'acl deluser': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'acl save': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'acl log': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'hgetall': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'geosearch': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'quit': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'hvals': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zunionstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'append': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xackdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'dump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'eval_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'hpexpiretime': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'cluster': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster set-config-epoch': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster delslots': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster nodes': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster count-failure-reports': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster flushslots': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster links': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster replicate': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster addslots': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster delslotsrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster addslotsrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster bumpepoch': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster slaves': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster replicas': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster myid': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster countkeysinslot': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster getkeysinslot': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster meet': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster setslot': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster saveconfig': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster slot-stats': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster myshardid': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster forget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster slots': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster keyslot': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster reset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster failover': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster shards': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cluster info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'sort_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'waitaof': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.AGG_MIN), - 'hexpireat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'flushall': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'zinterstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'monitor': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'sunionstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'incr': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hmget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'type': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'publish': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'slaveof': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'hpttl': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hello': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'zrank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xtrim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'sync': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'replconf': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'llen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'command': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'command docs': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'command help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'command getkeysandflags': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'command list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'command count': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'command info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'command getkeys': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'sunion': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xsetid': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'georadiusbymember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lolwut': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'zrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hpexpireat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'readonly': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'pfmerge': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'getrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'bitpos': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'persist': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'object': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'object help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'object encoding': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'object idletime': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'object freq': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'object refcount': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hpersist': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'debug': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'script': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'script kill': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ONE_SUCCEEDED), - 'script debug': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'script exists': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.AGG_LOGICAL_AND), - 'script help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'script load': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'script flush': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'xreadgroup': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'mset': CommandPolicies(request_policy=RequestPolicy.MULTI_SHARD, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'brpoplpush': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'srem': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'getex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'geodist': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zrevrangebyscore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'sscan': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xclaim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lpos': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'expireat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'rpush': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'geopos': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'bitfield': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'touch': CommandPolicies(request_policy=RequestPolicy.MULTI_SHARD, response_policy=ResponsePolicy.AGG_SUM), - 'wait': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.AGG_MIN), - 'pttl': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'sinterstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'getset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'set': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'bitcount': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zpopmin': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'bzpopmin': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'psync': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'hgetdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zrevrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'scard': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zrevrank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xrevrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'multi': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'psubscribe': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'exists': CommandPolicies(request_policy=RequestPolicy.MULTI_SHARD, response_policy=ResponsePolicy.AGG_SUM), - 'select': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'decrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'unwatch': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'pfcount': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hkeys': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'smembers': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'watch': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zdiffstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'setex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'restore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'brpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zrevrangebylex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zlexcount': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'dbsize': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.AGG_SUM), - 'zincrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zrandmember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'setnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'bitop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lcs': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'expire': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'config': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'config get': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'config set': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'config help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'config resetstat': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'config rewrite': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'pexpiretime': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'spublish': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'pfdebug': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'setrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hsetex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'linsert': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'sdiffstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zrem': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'restore-asking': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xread': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'copy': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'ttl': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'asking': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'hscan': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'bgsave': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'blpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'substr': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hpexpire': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'migrate': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'module': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'module help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'module list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'module load': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'module loadex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'module unload': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'pfselftest': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'save': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'ssubscribe': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zdiff': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'lindex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zremrangebyrank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'slowlog': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'slowlog reset': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'slowlog get': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'slowlog help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'slowlog len': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.AGG_SUM), - 'replicaof': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'incrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'reset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'lmove': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'spop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'sdiff': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'evalsha_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'psetex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'client': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client no-evict': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client kill': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client no-touch': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client pause': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client setname': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'client caching': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client getredir': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client tracking': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client setinfo': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'client trackinginfo': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client getname': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client reply': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client unblock': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client unpause': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'client id': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'evalsha': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'zscore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'strlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zremrangebylex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'blmove': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'failover': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'swapdb': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'zintercard': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'hexpire': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'pexpire': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'move': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'rpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'smismember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'getdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'get': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'pubsub': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'pubsub shardchannels': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'pubsub help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'pubsub channels': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'pubsub shardnumsub': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'pubsub numpat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'pubsub numsub': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'scan': CommandPolicies(request_policy=RequestPolicy.SPECIAL, response_policy=ResponsePolicy.SPECIAL), - 'smove': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zrangestore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zrangebyscore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'punsubscribe': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'unsubscribe': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'georadius': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'sintercard': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'time': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'xdelex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hstrlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zpopmax': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lmpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'latency': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'latency doctor': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.SPECIAL), - 'latency history': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.SPECIAL), - 'latency help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'latency histogram': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.SPECIAL), - 'latency reset': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.AGG_SUM), - 'latency latest': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.SPECIAL), - 'latency graph': CommandPolicies(request_policy=RequestPolicy.ALL_NODES, response_policy=ResponsePolicy.SPECIAL), - 'bzmpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'xack': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'ping': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'zmpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'subscribe': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'lpush': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hrandfield': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xgroup': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'xgroup help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'xgroup create': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xgroup destroy': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xgroup setid': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xgroup createconsumer': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'xgroup delconsumer': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'memory': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'memory doctor': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.SPECIAL), - 'memory purge': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'memory help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'memory usage': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'memory malloc-stats': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.SPECIAL), - 'memory stats': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.SPECIAL), - 'rpushx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'httl': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'georadius_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'role': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'geosearchstore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'pexpireat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zscan': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'randomkey': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.SPECIAL), - 'shutdown': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'rename': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'mget': CommandPolicies(request_policy=RequestPolicy.MULTI_SHARD, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'expiretime': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zcard': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'sunsubscribe': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'setbit': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'unlink': CommandPolicies(request_policy=RequestPolicy.MULTI_SHARD, response_policy=ResponsePolicy.AGG_SUM), - 'hmset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'geoadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'bitfield_ro': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'echo': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'zrangebylex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'incrbyfloat': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'info': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.SPECIAL), - 'zremrangebyscore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hincrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'sort': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'hsetnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'blmpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'hgetex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'function': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'function list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'function load': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'function dump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'function kill': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ONE_SUCCEEDED), - 'function help': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'function flush': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'function delete': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'function stats': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.SPECIAL), - 'function restore': CommandPolicies(request_policy=RequestPolicy.ALL_SHARDS, response_policy=ResponsePolicy.ALL_SUCCEEDED), - 'srandmember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'lastsave': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'zunion': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'bgrewriteaof': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'auth': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'sismember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'zmscore': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'pfadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vsim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vinfo': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vcard': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vlinks': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vrandmember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vismember': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vrem': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vdim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vgetattr': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vsetattr': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'vemb': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - }, - 'topk': { - 'list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'query': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'incrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'add': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'count': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'reserve': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - }, - 'ts': { - 'get': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'add': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'alter': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'decrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'createrule': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'madd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'del': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'revrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'create': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'mrevrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'mget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'range': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'queryindex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'incrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'deleterule': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'mrange': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - }, - 'tdigest': { - 'min': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'create': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'byrevrank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'rank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'byrank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'quantile': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'add': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'cdf': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'reset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'trimmed_mean': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'merge': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'max': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'revrank': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - }, - 'json': { - 'get': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'arrappend': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'numpowby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'numincrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'objkeys': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'arrtrim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'toggle': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'del': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'forget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'arrlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'mget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'arrindex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'arrpop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'objlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'debug': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'type': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'arrinsert': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'mset': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'clear': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'nummultby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'strlen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'set': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'strappend': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'merge': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'resp': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - }, - 'bf': { - 'add': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'debug': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'insert': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'madd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'reserve': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'mexists': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'loadchunk': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'card': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'scandump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'exists': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - }, - 'cf': { - 'add': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'reserve': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'insert': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'insertnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'exists': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'scandump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'mexists': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'loadchunk': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'addnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'del': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'count': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'debug': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'compact': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - }, - 'cms': { - 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'initbydim': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'initbyprob': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'query': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'incrby': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - 'merge': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - }, 'ft': { 'explaincli': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'suglen': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), 'profile': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'dropindex': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'synadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'aliasupdate': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'alter': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'aggregate': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'syndump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - '_dropindexifx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'add': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'create': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'explain': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - '_aliasaddifnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - '_dropifx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'get': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - '_createifnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'sugget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), 'dictdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'aliasadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), @@ -537,14 +23,9 @@ 'drop': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'sugadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), - '_aliasdelifx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'dictdump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'cursor': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - '_alterifnx': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'mget': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'del': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'search': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - '_list': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'tagvals': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'aliasdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'sugdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), From b2c72fcec3878be54241c05b0e5c04af9d1eed09 Mon Sep 17 00:00:00 2001 From: vladvildanov Date: Mon, 27 Oct 2025 12:36:09 +0200 Subject: [PATCH 08/13] Policy applied for normal and pipeline mode --- redis/_parsers/commands.py | 7 +- redis/cluster.py | 215 ++++++++++++++++++++++++--------- redis/commands/policies.py | 11 +- tests/test_cluster.py | 23 +++- tests/test_command_policies.py | 105 ++++++++++++++-- 5 files changed, 284 insertions(+), 77 deletions(-) diff --git a/redis/_parsers/commands.py b/redis/_parsers/commands.py index f41e3a1c0d..a5582c119d 100644 --- a/redis/_parsers/commands.py +++ b/redis/_parsers/commands.py @@ -11,11 +11,12 @@ class RequestPolicy(Enum): ALL_NODES = 'all_nodes' ALL_SHARDS = 'all_shards' - ANY_MASTER_SHARD = 'any_master_shard' + ALL_REPLICAS = 'all_replicas' MULTI_SHARD = 'multi_shard' SPECIAL = 'special' DEFAULT_KEYLESS = 'default_keyless' DEFAULT_KEYED = 'default_keyed' + DEFAULT_NODE = 'default_node' class ResponsePolicy(Enum): ONE_SUCCEEDED = 'one_succeeded' @@ -163,7 +164,9 @@ def get_keys(self, redis_conn, *args): for subcmd in command["subcommands"]: if str_if_bytes(subcmd[0]) == subcmd_name: command = self.parse_subcommand(subcmd) - is_subcmd = True + + if command['first_key_pos'] > 0: + is_subcmd = True # The command doesn't have keys in it if not is_subcmd: diff --git a/redis/cluster.py b/redis/cluster.py index 69d80a9ee4..c6e45acc6b 100644 --- a/redis/cluster.py +++ b/redis/cluster.py @@ -8,7 +8,7 @@ from copy import copy from enum import Enum from itertools import chain -from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union, Mapping +from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union from redis._parsers import CommandsParser, Encoder from redis._parsers.commands import RequestPolicy, CommandPolicies, ResponsePolicy @@ -18,7 +18,7 @@ from redis.client import EMPTY_RESPONSE, CaseInsensitiveDict, PubSub, Redis from redis.commands import READ_COMMANDS, RedisClusterCommands from redis.commands.helpers import list_or_args -from redis.commands.policies import PolicyResolver, StaticPolicyResolver, DynamicPolicyResolver +from redis.commands.policies import PolicyResolver, StaticPolicyResolver from redis.connection import ( Connection, ConnectionPool, @@ -533,7 +533,7 @@ def __init__( cache: Optional[CacheInterface] = None, cache_config: Optional[CacheConfig] = None, event_dispatcher: Optional[EventDispatcher] = None, - policy_resolver: Optional[PolicyResolver] = StaticPolicyResolver(), + policy_resolver: PolicyResolver = StaticPolicyResolver(), **kwargs, ): """ @@ -715,21 +715,29 @@ def __init__( ) self.result_callbacks = CaseInsensitiveDict(self.__class__.RESULT_CALLBACKS) + # For backward compatibility, mapping from existing policies to new one + self._command_flags_mapping: dict[str, Union[RequestPolicy, ResponsePolicy]] = { + self.__class__.RANDOM: RequestPolicy.DEFAULT_KEYLESS, + self.__class__.PRIMARIES: RequestPolicy.ALL_SHARDS, + self.__class__.ALL_NODES: RequestPolicy.ALL_NODES, + self.__class__.REPLICAS: RequestPolicy.ALL_REPLICAS, + self.__class__.DEFAULT_NODE: RequestPolicy.DEFAULT_NODE, + SLOT_ID: RequestPolicy.DEFAULT_KEYED, + } + self._policies_callback_mapping: dict[Union[RequestPolicy, ResponsePolicy], Callable] = { - RequestPolicy.DEFAULT_KEYLESS: lambda: [self.get_random_node()], - RequestPolicy.DEFAULT_KEYED: lambda *args: self.get_node_from_slot(*args), + RequestPolicy.DEFAULT_KEYLESS: lambda command_name: [self.get_random_primary_or_all_nodes(command_name)], + RequestPolicy.DEFAULT_KEYED: lambda command, *args: self.get_node_from_slot(command, *args), + RequestPolicy.DEFAULT_NODE: lambda: [self.get_default_node()], RequestPolicy.ALL_SHARDS: self.get_primaries, RequestPolicy.ALL_NODES: self.get_nodes, - RequestPolicy.ANY_MASTER_SHARD: lambda: [self.get_random_primary_node()], + RequestPolicy.ALL_REPLICAS: self.get_replicas, RequestPolicy.MULTI_SHARD: lambda *args, **kwargs: self._split_multi_shard_command(*args, **kwargs), RequestPolicy.SPECIAL: self.get_special_nodes, ResponsePolicy.DEFAULT_KEYLESS: lambda res: res, ResponsePolicy.DEFAULT_KEYED: lambda res: res, - ResponsePolicy.ONE_SUCCEEDED: lambda res: res, - ResponsePolicy.ALL_SUCCEEDED: lambda res: self._evaluate_all_succeeded(res) } - # Needs for a commands parser to successfully execute COMMAND self._policy_resolver = policy_resolver self.commands_parser = CommandsParser(self) @@ -797,6 +805,15 @@ def get_replicas(self): def get_random_node(self): return random.choice(list(self.nodes_manager.nodes_cache.values())) + def get_random_primary_or_all_nodes(self, command_name): + """ + Returns random primary or all nodes depends on READONLY mode. + """ + if self.read_from_replicas and command_name in READ_COMMANDS: + return self.get_random_node() + + return self.get_random_primary_node() + def get_nodes(self): return list(self.nodes_manager.nodes_cache.values()) @@ -826,7 +843,7 @@ def get_default_node(self): """ return self.nodes_manager.default_node - def get_node_from_slot(self, *args): + def get_node_from_slot(self, command: str, *args): """ Returns a list of nodes that hold the specified keys' slots. """ @@ -1043,21 +1060,40 @@ def set_response_callback(self, command, callback): """Set a custom Response Callback""" self.cluster_response_callbacks[command] = callback - def _determine_nodes(self, *args, request_policy: RequestPolicy) -> List["ClusterNode"]: + def _determine_nodes(self, *args, request_policy: RequestPolicy, **kwargs) -> List["ClusterNode"]: """ Determines a nodes the command should be executed on. """ + command = args[0].upper() + if len(args) >= 2 and f"{args[0]} {args[1]}".upper() in self.command_flags: + command = f"{args[0]} {args[1]}".upper() + + nodes_flag = kwargs.pop("nodes_flag", None) + if nodes_flag is not None: + # nodes flag passed by the user + command_flag = nodes_flag + else: + # get the nodes group for this command if it was predefined + command_flag = self.command_flags.get(command) + + if command_flag in self._command_flags_mapping: + request_policy = self._command_flags_mapping[command_flag] + policy_callback = self._policies_callback_mapping[request_policy] if request_policy == RequestPolicy.DEFAULT_KEYED: - target_nodes = policy_callback(*args) + nodes = policy_callback(command, *args) + elif request_policy == RequestPolicy.MULTI_SHARD: + nodes = policy_callback(*args, **kwargs) + elif request_policy == RequestPolicy.DEFAULT_KEYLESS: + nodes = policy_callback(args[0]) else: - target_nodes = policy_callback() + nodes = policy_callback() if args[0].lower() == "ft.aggregate": - self._aggregate_nodes = target_nodes + self._aggregate_nodes = nodes - return target_nodes + return nodes def _should_reinitialized(self): # To reinitialize the cluster on every MOVED error, @@ -1208,6 +1244,34 @@ def _internal_execute_command(self, *args, **kwargs): target_nodes = None passed_targets = kwargs.pop("target_nodes", None) command_policies = self._policy_resolver.resolve(args[0].lower()) + + if not command_policies: + command = args[0].upper() + if len(args) >= 2 and f"{args[0]} {args[1]}".upper() in self.command_flags: + command = f"{args[0]} {args[1]}".upper() + + # We only could resolve key properties if command is not + # in a list of pre-defined request policies + command_flag = self.command_flags.get(command) + if not command_flag: + # Fallback to default policy + if not self.get_default_node(): + keys = None + else: + keys = self._get_command_keys(*args) + if not keys or len(keys) == 0: + command_policies = CommandPolicies() + else: + command_policies = CommandPolicies( + request_policy=RequestPolicy.DEFAULT_KEYED, + response_policy=ResponsePolicy.DEFAULT_KEYED, + ) + else: + if command_flag in self._command_flags_mapping: + command_policies = CommandPolicies(request_policy=self._command_flags_mapping[command_flag]) + else: + command_policies = CommandPolicies() + if passed_targets is not None and not self._is_nodes_flag(passed_targets): target_nodes = self._parse_target_nodes(passed_targets) target_nodes_specified = True @@ -1226,24 +1290,9 @@ def _internal_execute_command(self, *args, **kwargs): try: res = {} if not target_nodes_specified: - if command_policies.request_policy == RequestPolicy.MULTI_SHARD: - commands = self._policies_callback_mapping[command_policies.request_policy](*args, **kwargs) - - for command in commands: - target_nodes = self.get_node_from_slot(*command['args']) - - if not target_nodes: - raise RedisClusterException( - f"No targets were found to execute {args} command on" - ) - - res[target_nodes[0].name] = self._execute_command(target_nodes[0], *command['args'], **command['kwargs']) - - return self._process_result(args[0], res, response_policy=command_policies.response_policy) - # Determine the nodes to execute the command on target_nodes = self._determine_nodes( - *args, request_policy=command_policies.request_policy + *args, request_policy=command_policies.request_policy, nodes_flag=passed_targets ) if not target_nodes: raise RedisClusterException( @@ -2240,6 +2289,7 @@ def __init__( retry: Optional[Retry] = None, lock=None, transaction=False, + policy_resolver: PolicyResolver = StaticPolicyResolver(), **kwargs, ): """ """ @@ -2278,6 +2328,31 @@ def __init__( PipelineStrategy(self) if not transaction else TransactionStrategy(self) ) + # For backward compatibility, mapping from existing policies to new one + self._command_flags_mapping: dict[str, Union[RequestPolicy, ResponsePolicy]] = { + self.__class__.RANDOM: RequestPolicy.DEFAULT_KEYLESS, + self.__class__.PRIMARIES: RequestPolicy.ALL_SHARDS, + self.__class__.ALL_NODES: RequestPolicy.ALL_NODES, + self.__class__.REPLICAS: RequestPolicy.ALL_REPLICAS, + self.__class__.DEFAULT_NODE: RequestPolicy.DEFAULT_NODE, + SLOT_ID: RequestPolicy.DEFAULT_KEYED, + } + + self._policies_callback_mapping: dict[Union[RequestPolicy, ResponsePolicy], Callable] = { + RequestPolicy.DEFAULT_KEYLESS: lambda command_name: [self.get_random_primary_or_all_nodes(command_name)], + RequestPolicy.DEFAULT_KEYED: lambda command, *args: self.get_node_from_slot(command, *args), + RequestPolicy.DEFAULT_NODE: lambda: [self.get_default_node()], + RequestPolicy.ALL_SHARDS: self.get_primaries, + RequestPolicy.ALL_NODES: self.get_nodes, + RequestPolicy.ALL_REPLICAS: self.get_replicas, + RequestPolicy.MULTI_SHARD: lambda *args, **kwargs: self._split_multi_shard_command(*args, **kwargs), + RequestPolicy.SPECIAL: self.get_special_nodes, + ResponsePolicy.DEFAULT_KEYLESS: lambda res: res, + ResponsePolicy.DEFAULT_KEYED: lambda res: res, + } + + self._policy_resolver = policy_resolver + def __repr__(self): """ """ return f"{type(self).__name__}" @@ -2856,6 +2931,35 @@ def _send_cluster_commands( # we figure out the slot number that command maps to, then from # the slot determine the node. for c in attempt: + command_policies = self._pipe._policy_resolver.resolve(c.args[0].lower()) + + if not command_policies: + command = c.args[0].upper() + if len(c.args) >= 2 and f"{c.args[0]} {c.args[1]}".upper() in self._pipe.command_flags: + command = f"{c.args[0]} {c.args[1]}".upper() + + # We only could resolve key properties if command is not + # in a list of pre-defined request policies + command_flag = self.command_flags.get(command) + if not command_flag: + # Fallback to default policy + if not self._pipe.get_default_node(): + keys = None + else: + keys = self._pipe._get_command_keys(*c.args) + if not keys or len(keys) == 0: + command_policies = CommandPolicies() + else: + command_policies = CommandPolicies( + request_policy=RequestPolicy.DEFAULT_KEYED, + response_policy=ResponsePolicy.DEFAULT_KEYED, + ) + else: + if command_flag in self._pipe._command_flags_mapping: + command_policies = CommandPolicies(request_policy=self._pipe._command_flags_mapping[command_flag]) + else: + command_policies = CommandPolicies() + while True: # refer to our internal node -> slot table that # tells us where a given command should route to. @@ -2866,7 +2970,7 @@ def _send_cluster_commands( target_nodes = self._parse_target_nodes(passed_targets) else: target_nodes = self._determine_nodes( - *c.args, node_flag=passed_targets + *c.args, request_policy=command_policies.request_policy, node_flag=passed_targets ) if not target_nodes: raise RedisClusterException( @@ -3029,7 +3133,7 @@ def _parse_target_nodes(self, target_nodes): ) return nodes - def _determine_nodes(self, *args, **kwargs) -> List["ClusterNode"]: + def _determine_nodes(self, *args, request_policy: RequestPolicy, **kwargs) -> List["ClusterNode"]: # Determine which nodes should be executed the command on. # Returns a list of target nodes. command = args[0].upper() @@ -3046,34 +3150,25 @@ def _determine_nodes(self, *args, **kwargs) -> List["ClusterNode"]: else: # get the nodes group for this command if it was predefined command_flag = self._pipe.command_flags.get(command) - if command_flag == self._pipe.RANDOM: - # return a random node - return [self._pipe.get_random_node()] - elif command_flag == self._pipe.PRIMARIES: - # return all primaries - return self._pipe.get_primaries() - elif command_flag == self._pipe.REPLICAS: - # return all replicas - return self._pipe.get_replicas() - elif command_flag == self._pipe.ALL_NODES: - # return all nodes - return self._pipe.get_nodes() - elif command_flag == self._pipe.DEFAULT_NODE: - # return the cluster's default node - return [self._nodes_manager.default_node] - elif command in self._pipe.SEARCH_COMMANDS[0]: - return [self._nodes_manager.default_node] + + if command_flag in self._pipe._command_flags_mapping: + request_policy = self._pipe._command_flags_mapping[command_flag] + + policy_callback = self._pipe._policies_callback_mapping[request_policy] + + if request_policy == RequestPolicy.DEFAULT_KEYED: + nodes = policy_callback(command, *args) + elif request_policy == RequestPolicy.MULTI_SHARD: + nodes = policy_callback(*args, **kwargs) + elif request_policy == RequestPolicy.DEFAULT_KEYLESS: + nodes = policy_callback(args[0]) else: - # get the node that holds the key's slot - slot = self._pipe.determine_slot(*args) - node = self._nodes_manager.get_node_from_slot( - slot, - self._pipe.read_from_replicas and command in READ_COMMANDS, - self._pipe.load_balancing_strategy - if command in READ_COMMANDS - else None, - ) - return [node] + nodes = policy_callback() + + if args[0].lower() == "ft.aggregate": + self._aggregate_nodes = nodes + + return nodes def multi(self): raise RedisClusterException( diff --git a/redis/commands/policies.py b/redis/commands/policies.py index a2f7f45924..7413f3f68d 100644 --- a/redis/commands/policies.py +++ b/redis/commands/policies.py @@ -24,12 +24,15 @@ 'info': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'sugadd': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), 'dictdump': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), - 'cursor': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + 'cursor': CommandPolicies(request_policy=RequestPolicy.SPECIAL, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'search': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'tagvals': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'aliasdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), 'sugdel': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED), 'spellcheck': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), + }, + 'core': { + 'command': CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS), } } @@ -69,7 +72,7 @@ def __init__(self, policies: PolicyRecords, fallback: Optional[PolicyResolver] = self._policies = policies self._fallback = fallback - def resolve(self, command_name: str) -> CommandPolicies: + def resolve(self, command_name: str) -> Optional[CommandPolicies]: parts = command_name.split(".") if len(parts) > 2: @@ -81,13 +84,13 @@ def resolve(self, command_name: str) -> CommandPolicies: if self._fallback is not None: return self._fallback.resolve(command_name) else: - raise ValueError(f"Module {module} not found") + return None if self._policies.get(module).get(command, None) is None: if self._fallback is not None: return self._fallback.resolve(command_name) else: - raise ValueError(f"Command {command} not found in module {module}") + return None return self._policies.get(module).get(command) diff --git a/tests/test_cluster.py b/tests/test_cluster.py index 2936bb0024..759c93ffc6 100644 --- a/tests/test_cluster.py +++ b/tests/test_cluster.py @@ -207,7 +207,28 @@ def cmd_init_mock(self, r): "first_key_pos": 1, "last_key_pos": 1, "step_count": 1, - } + }, + "cluster delslots": { + "name": "cluster delslots", + "flags": ["readonly", "fast"], + "first_key_pos": 0, + "last_key_pos": 0, + "step_count": 0, + }, + "cluster delslotsrange": { + "name": "cluster delslotsrange", + "flags": ["readonly", "fast"], + "first_key_pos": 0, + "last_key_pos": 0, + "step_count": 0, + }, + "cluster addslots": { + "name": "cluster delslotsrange", + "flags": ["readonly", "fast"], + "first_key_pos": 0, + "last_key_pos": 0, + "step_count": 0, + }, } cmd_parser_initialize.side_effect = cmd_init_mock diff --git a/tests/test_command_policies.py b/tests/test_command_policies.py index e2f69cfc77..c4eecc2100 100644 --- a/tests/test_command_policies.py +++ b/tests/test_command_policies.py @@ -1,11 +1,15 @@ -from unittest.mock import Mock +import random +from unittest.mock import Mock, patch import pytest +from redis import ResponseError + from redis._parsers import CommandsParser from redis._parsers.commands import CommandPolicies, RequestPolicy, ResponsePolicy from redis.commands.policies import DynamicPolicyResolver, StaticPolicyResolver - +from redis.commands.search.aggregation import AggregateRequest +from redis.commands.search.field import TextField, NumericField @pytest.mark.onlycluster class TestBasePolicyResolver: @@ -28,18 +32,15 @@ def test_resolve(self): with pytest.raises(ValueError, match="Wrong command or module name: foo.bar.baz"): dynamic_resolver.resolve('foo.bar.baz') - with pytest.raises(ValueError, match="Module foo not found"): - dynamic_resolver.resolve('foo.bar') - - with pytest.raises(ValueError, match="Command foo not found in module core"): - dynamic_resolver.resolve('core.foo') + assert dynamic_resolver.resolve('foo.bar') is None + assert dynamic_resolver.resolve('core.foo') is None # Test that policy fallback correctly static_resolver = StaticPolicyResolver() with_fallback_dynamic_resolver = dynamic_resolver.with_fallback(static_resolver) - assert with_fallback_dynamic_resolver.resolve('tdigest.min').request_policy == RequestPolicy.DEFAULT_KEYED - assert with_fallback_dynamic_resolver.resolve('tdigest.min').response_policy == ResponsePolicy.DEFAULT_KEYED + assert with_fallback_dynamic_resolver.resolve('ft.aggregate').request_policy == RequestPolicy.DEFAULT_KEYLESS + assert with_fallback_dynamic_resolver.resolve('ft.aggregate').response_policy == ResponsePolicy.DEFAULT_KEYLESS # Extended chain with one more resolver mock_command_parser = Mock(spec=CommandsParser) @@ -54,4 +55,88 @@ def test_resolve(self): with_fallback_static_resolver = static_resolver.with_fallback(another_dynamic_resolver) with_double_fallback_dynamic_resolver = dynamic_resolver.with_fallback(with_fallback_static_resolver) - assert with_double_fallback_dynamic_resolver.resolve('foo.bar') == foo_bar_policy \ No newline at end of file + assert with_double_fallback_dynamic_resolver.resolve('foo.bar') == foo_bar_policy + +@pytest.mark.onlycluster +class TestClusterWithPolicies: + def test_resolves_correctly_policies(self, r, monkeypatch): + # original nodes selection method + determine_nodes = r._determine_nodes + determined_nodes = [] + primary_nodes = r.get_primaries() + calls = iter(list(range(len(primary_nodes)))) + + def wrapper(*args, request_policy: RequestPolicy, **kwargs): + nonlocal determined_nodes + determined_nodes = determine_nodes(*args, request_policy=request_policy, **kwargs) + return determined_nodes + + # Mock random.choice to always return a pre-defined sequence of nodes + monkeypatch.setattr(random, "choice", lambda seq: seq[next(calls)]) + + with patch.object(r, '_determine_nodes', side_effect=wrapper, autospec=True): + # Routed to a random primary node + r.ft().create_index( + ( + NumericField("random_num"), + TextField("title"), + TextField("body"), + TextField("parent"), + ) + ) + assert determined_nodes[0] == primary_nodes[0] + + # Routed to another random primary node + info = r.ft().info() + assert info['index_name'] == 'idx' + assert determined_nodes[0] == primary_nodes[1] + + expected_node = r.get_node_from_slot('ft.suglen', *['FT.SUGLEN', 'foo']) + r.ft().suglen('foo') + assert determined_nodes[0] == expected_node[0] + + # Indexing a document + r.hset( + "search", + mapping={ + "title": "RediSearch", + "body": "Redisearch impements a search engine on top of redis", + "parent": "redis", + "random_num": 10, + }, + ) + r.hset( + "ai", + mapping={ + "title": "RedisAI", + "body": "RedisAI executes Deep Learning/Machine Learning models and managing their data.", # noqa + "parent": "redis", + "random_num": 3, + }, + ) + r.hset( + "json", + mapping={ + "title": "RedisJson", + "body": "RedisJSON implements ECMA-404 The JSON Data Interchange Standard as a native data type.", # noqa + "parent": "redis", + "random_num": 8, + }, + ) + + req = AggregateRequest("redis").group_by( + "@parent" + ).cursor(1) + cursor = r.ft().aggregate(req).cursor + + # Ensure that aggregate node was cached. + assert determined_nodes[0] == r._aggregate_nodes[0] + + r.ft().aggregate(cursor) + + # Verify that FT.CURSOR dispatched to the same node. + assert determined_nodes[0] == r._aggregate_nodes[0] + + # Error propagates to a user + with pytest.raises(ResponseError, match="Cursor not found, id: 0"): + r.ft().aggregate(cursor) \ No newline at end of file From 0668ef19873c06e267979937b680c0dd1779a8a1 Mon Sep 17 00:00:00 2001 From: vladvildanov Date: Mon, 27 Oct 2025 12:42:20 +0200 Subject: [PATCH 09/13] Added assertion with core command --- tests/conftest.py | 2 +- tests/test_command_policies.py | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 7eaccb1acb..9c174974ef 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -30,7 +30,7 @@ from tests.ssl_utils import get_tls_certificates REDIS_INFO = {} -default_redis_url = "redis://localhost:6379/0" +default_redis_url = "redis://localhost:16379/0" default_protocol = "2" default_redismod_url = "redis://localhost:6479" diff --git a/tests/test_command_policies.py b/tests/test_command_policies.py index c4eecc2100..69854219bb 100644 --- a/tests/test_command_policies.py +++ b/tests/test_command_policies.py @@ -139,4 +139,10 @@ def wrapper(*args, request_policy: RequestPolicy, **kwargs): # Error propagates to a user with pytest.raises(ResponseError, match="Cursor not found, id: 0"): - r.ft().aggregate(cursor) \ No newline at end of file + r.ft().aggregate(cursor) + + assert determined_nodes[0] == primary_nodes[2] + + # Core commands also randomly distributed across masters + r.randomkey() + assert determined_nodes[0] == primary_nodes[0] \ No newline at end of file From f6341dedea2af83bf7f2cffa84ddae42e28e4aa1 Mon Sep 17 00:00:00 2001 From: vladvildanov Date: Mon, 27 Oct 2025 12:49:08 +0200 Subject: [PATCH 10/13] Applied comments --- redis/_parsers/commands.py | 12 ++++++------ tests/test_command_policies.py | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/redis/_parsers/commands.py b/redis/_parsers/commands.py index a9b4fe67b0..a7571ac195 100644 --- a/redis/_parsers/commands.py +++ b/redis/_parsers/commands.py @@ -258,7 +258,7 @@ def get_command_policies(self) -> PolicyRecords: """ command_with_policies = {} - def extract_policies(data, command_name, module_name): + def extract_policies(data, module_name, command_name): """ Recursively extract policies from nested data structures. @@ -268,7 +268,7 @@ def extract_policies(data, command_name, module_name): """ if isinstance(data, (str, bytes)): # Decode bytes to string if needed - policy = data.decode() if isinstance(data, bytes) else data + policy = str_if_bytes(data.decode()) # Check if this is a policy string if policy.startswith('request_policy') or policy.startswith('response_policy'): @@ -291,12 +291,12 @@ def extract_policies(data, command_name, module_name): elif isinstance(data, list): # For lists, recursively process each element for item in data: - extract_policies(item, command_name, module_name) + extract_policies(item, module_name, command_name) elif isinstance(data, dict): # For dictionaries, recursively process each value for value in data.values(): - extract_policies(value, command_name, module_name) + extract_policies(value, module_name, command_name) for command, details in self.commands.items(): # Check whether the command has keys @@ -336,7 +336,7 @@ def extract_policies(data, command_name, module_name): # Process tips for the main command if tips: - extract_policies(tips, command_name, module_name) + extract_policies(tips, module_name, command_name) # Process subcommands if subcommands: @@ -366,7 +366,7 @@ def extract_policies(data, command_name, module_name): # Recursively extract policies from the rest of the subcommand details for subcommand_detail in subcommand_details[1:]: - extract_policies(subcommand_detail, subcmd_name, module_name) + extract_policies(subcommand_detail, module_name, subcmd_name) return command_with_policies diff --git a/tests/test_command_policies.py b/tests/test_command_policies.py index e2f69cfc77..c0d057f0b0 100644 --- a/tests/test_command_policies.py +++ b/tests/test_command_policies.py @@ -38,8 +38,8 @@ def test_resolve(self): static_resolver = StaticPolicyResolver() with_fallback_dynamic_resolver = dynamic_resolver.with_fallback(static_resolver) - assert with_fallback_dynamic_resolver.resolve('tdigest.min').request_policy == RequestPolicy.DEFAULT_KEYED - assert with_fallback_dynamic_resolver.resolve('tdigest.min').response_policy == ResponsePolicy.DEFAULT_KEYED + assert with_fallback_dynamic_resolver.resolve('ft.aggregate').request_policy == RequestPolicy.DEFAULT_KEYLESS + assert with_fallback_dynamic_resolver.resolve('ft.aggregate').response_policy == ResponsePolicy.DEFAULT_KEYLESS # Extended chain with one more resolver mock_command_parser = Mock(spec=CommandsParser) From b09e12cee7b7098a78f09180b8b1962027ebc585 Mon Sep 17 00:00:00 2001 From: vladvildanov Date: Wed, 29 Oct 2025 13:46:32 +0200 Subject: [PATCH 11/13] Added async support for Request/Responce policies --- redis/_parsers/commands.py | 175 ++++++++++++++++++- redis/asyncio/cluster.py | 176 ++++++++++++++++---- redis/cluster.py | 83 +++++---- redis/commands/policies.py | 101 ++++++++++- tests/test_asyncio/test_command_parser.py | 69 ++++++++ tests/test_asyncio/test_command_policies.py | 147 ++++++++++++++++ 6 files changed, 678 insertions(+), 73 deletions(-) create mode 100644 tests/test_asyncio/test_command_parser.py create mode 100644 tests/test_asyncio/test_command_policies.py diff --git a/redis/_parsers/commands.py b/redis/_parsers/commands.py index cff2296b27..f236d1523d 100644 --- a/redis/_parsers/commands.py +++ b/redis/_parsers/commands.py @@ -1,6 +1,6 @@ from dataclasses import dataclass from enum import Enum -from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, Union +from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, Union, Awaitable from redis.exceptions import RedisError, ResponseError, IncorrectPolicyType from redis.utils import str_if_bytes @@ -455,7 +455,9 @@ async def get_keys(self, *args: Any) -> Optional[Tuple[str, ...]]: for subcmd in command["subcommands"]: if str_if_bytes(subcmd[0]) == subcmd_name: command = self.parse_subcommand(subcmd) - is_subcmd = True + + if command['first_key_pos'] > 0: + is_subcmd = True # The command doesn't have keys in it if not is_subcmd: @@ -483,3 +485,172 @@ async def _get_moveable_keys(self, *args: Any) -> Optional[Tuple[str, ...]]: else: raise e return keys + + async def _is_keyless_command(self, command_name: str, subcommand_name: Optional[str]=None) -> bool: + """ + Determines whether a given command or subcommand is considered "keyless". + + A keyless command does not operate on specific keys, which is determined based + on the first key position in the command or subcommand details. If the command + or subcommand's first key position is zero or negative, it is treated as keyless. + + Parameters: + command_name: str + The name of the command to check. + subcommand_name: Optional[str], default=None + The name of the subcommand to check, if applicable. If not provided, + the check is performed only on the command. + + Returns: + bool + True if the specified command or subcommand is considered keyless, + False otherwise. + + Raises: + ValueError + If the specified subcommand is not found within the command or the + specified command does not exist in the available commands. + """ + if subcommand_name: + for subcommand in self.commands.get(command_name)['subcommands']: + if str_if_bytes(subcommand[0]) == subcommand_name: + parsed_subcmd = self.parse_subcommand(subcommand) + return parsed_subcmd['first_key_pos'] <= 0 + raise ValueError(f"Subcommand {subcommand_name} not found in command {command_name}") + else: + command_details = self.commands.get(command_name, None) + if command_details is not None: + return command_details['first_key_pos'] <= 0 + + raise ValueError(f"Command {command_name} not found in commands") + + async def get_command_policies(self) -> Awaitable[PolicyRecords]: + """ + Retrieve and process the command policies for all commands and subcommands. + + This method traverses through commands and subcommands, extracting policy details + from associated data structures and constructing a dictionary of commands with their + associated policies. It supports nested data structures and handles both main commands + and their subcommands. + + Returns: + PolicyRecords: A collection of commands and subcommands associated with their + respective policies. + + Raises: + IncorrectPolicyType: If an invalid policy type is encountered during policy extraction. + """ + command_with_policies = {} + + async def extract_policies(data, module_name, command_name): + """ + Recursively extract policies from nested data structures. + + Args: + data: The data structure to search (can be list, dict, str, bytes, etc.) + command_name: The command name to associate with found policies + """ + if isinstance(data, (str, bytes)): + # Decode bytes to string if needed + policy = str_if_bytes(data.decode()) + + # Check if this is a policy string + if policy.startswith('request_policy') or policy.startswith('response_policy'): + if policy.startswith('request_policy'): + policy_type = policy.split(':')[1] + + try: + command_with_policies[module_name][command_name].request_policy = RequestPolicy(policy_type) + except ValueError: + raise IncorrectPolicyType(f"Incorrect request policy type: {policy_type}") + + if policy.startswith('response_policy'): + policy_type = policy.split(':')[1] + + try: + command_with_policies[module_name][command_name].response_policy = ResponsePolicy( + policy_type) + except ValueError: + raise IncorrectPolicyType(f"Incorrect response policy type: {policy_type}") + + elif isinstance(data, list): + # For lists, recursively process each element + for item in data: + await extract_policies(item, module_name, command_name) + + elif isinstance(data, dict): + # For dictionaries, recursively process each value + for value in data.values(): + await extract_policies(value, module_name, command_name) + + for command, details in self.commands.items(): + # Check whether the command has keys + is_keyless = await self._is_keyless_command(command) + + if is_keyless: + default_request_policy = RequestPolicy.DEFAULT_KEYLESS + default_response_policy = ResponsePolicy.DEFAULT_KEYLESS + else: + default_request_policy = RequestPolicy.DEFAULT_KEYED + default_response_policy = ResponsePolicy.DEFAULT_KEYED + + # Check if it's a core or module command + split_name = command.split('.') + + if len(split_name) > 1: + module_name = split_name[0] + command_name = split_name[1] + else: + module_name = 'core' + command_name = split_name[0] + + # Create a CommandPolicies object with default policies on the new command. + if command_with_policies.get(module_name, None) is None: + command_with_policies[module_name] = {command_name: CommandPolicies( + request_policy=default_request_policy, + response_policy=default_response_policy + )} + else: + command_with_policies[module_name][command_name] = CommandPolicies( + request_policy=default_request_policy, + response_policy=default_response_policy + ) + + tips = details.get('tips') + subcommands = details.get('subcommands') + + # Process tips for the main command + if tips: + await extract_policies(tips, module_name, command_name) + + # Process subcommands + if subcommands: + for subcommand_details in subcommands: + # Get the subcommand name (first element) + subcmd_name = subcommand_details[0] + if isinstance(subcmd_name, bytes): + subcmd_name = subcmd_name.decode() + + # Check whether the subcommand has keys + is_keyless = await self._is_keyless_command(command, subcmd_name) + + if is_keyless: + default_request_policy = RequestPolicy.DEFAULT_KEYLESS + default_response_policy = ResponsePolicy.DEFAULT_KEYLESS + else: + default_request_policy = RequestPolicy.DEFAULT_KEYED + default_response_policy = ResponsePolicy.DEFAULT_KEYED + + subcmd_name = subcmd_name.replace('|', ' ') + + # Create a CommandPolicies object with default policies on the new command. + command_with_policies[module_name][subcmd_name] = CommandPolicies( + request_policy=default_request_policy, + response_policy=default_response_policy + ) + + # Recursively extract policies from the rest of the subcommand details + for subcommand_detail in subcommand_details[1:]: + await extract_policies(subcommand_detail, module_name, subcmd_name) + + return command_with_policies \ No newline at end of file diff --git a/redis/asyncio/cluster.py b/redis/asyncio/cluster.py index 4e0e06517d..f99143d29b 100644 --- a/redis/asyncio/cluster.py +++ b/redis/asyncio/cluster.py @@ -26,6 +26,7 @@ ) from redis._parsers import AsyncCommandsParser, Encoder +from redis._parsers.commands import RequestPolicy, ResponsePolicy, CommandPolicies from redis._parsers.helpers import ( _RedisCallbacks, _RedisCallbacksRESP2, @@ -51,6 +52,7 @@ parse_cluster_slots, ) from redis.commands import READ_COMMANDS, AsyncRedisClusterCommands +from redis.commands.policies import AsyncPolicyResolver, AsyncStaticPolicyResolver from redis.crc import REDIS_CLUSTER_HASH_SLOTS, key_slot from redis.credentials import CredentialProvider from redis.event import AfterAsyncClusterInstantiationEvent, EventDispatcher @@ -310,6 +312,7 @@ def __init__( protocol: Optional[int] = 2, address_remap: Optional[Callable[[Tuple[str, int]], Tuple[str, int]]] = None, event_dispatcher: Optional[EventDispatcher] = None, + policy_resolver: AsyncPolicyResolver = AsyncStaticPolicyResolver(), ) -> None: if db: raise RedisClusterException( @@ -422,7 +425,32 @@ def __init__( self.load_balancing_strategy = load_balancing_strategy self.reinitialize_steps = reinitialize_steps self.reinitialize_counter = 0 + + # For backward compatibility, mapping from existing policies to new one + self._command_flags_mapping: dict[str, Union[RequestPolicy, ResponsePolicy]] = { + self.__class__.RANDOM: RequestPolicy.DEFAULT_KEYLESS, + self.__class__.PRIMARIES: RequestPolicy.ALL_SHARDS, + self.__class__.ALL_NODES: RequestPolicy.ALL_NODES, + self.__class__.REPLICAS: RequestPolicy.ALL_REPLICAS, + self.__class__.DEFAULT_NODE: RequestPolicy.DEFAULT_NODE, + SLOT_ID: RequestPolicy.DEFAULT_KEYED, + } + + self._policies_callback_mapping: dict[Union[RequestPolicy, ResponsePolicy], Callable] = { + RequestPolicy.DEFAULT_KEYLESS: lambda command_name: [self.get_random_primary_or_all_nodes(command_name)], + RequestPolicy.DEFAULT_KEYED: self.get_node_from_slot, + RequestPolicy.DEFAULT_NODE: lambda: [self.get_default_node()], + RequestPolicy.ALL_SHARDS: self.get_primaries, + RequestPolicy.ALL_NODES: self.get_nodes, + RequestPolicy.ALL_REPLICAS: self.get_replicas, + RequestPolicy.SPECIAL: self.get_special_nodes, + ResponsePolicy.DEFAULT_KEYLESS: lambda res: res, + ResponsePolicy.DEFAULT_KEYED: lambda res: res, + } + + self._policy_resolver = policy_resolver self.commands_parser = AsyncCommandsParser() + self._aggregate_nodes = None self.node_flags = self.__class__.NODE_FLAGS.copy() self.command_flags = self.__class__.COMMAND_FLAGS.copy() self.response_callbacks = kwargs["response_callbacks"] @@ -618,6 +646,43 @@ def get_node_from_key( return slot_cache[node_idx] + def get_random_primary_or_all_nodes(self, command_name): + """ + Returns random primary or all nodes depends on READONLY mode. + """ + if self.read_from_replicas and command_name in READ_COMMANDS: + return self.get_random_node() + + return self.get_random_primary_node() + + def get_random_primary_node(self) -> "ClusterNode": + """ + Returns a random primary node + """ + return random.choice(self.get_primaries()) + + async def get_node_from_slot(self, command: str, *args): + """ + Returns a list of nodes that hold the specified keys' slots. + """ + # get the node that holds the key's slot + return [ + self.nodes_manager.get_node_from_slot( + await self._determine_slot(command, *args), + self.read_from_replicas and command in READ_COMMANDS, + self.load_balancing_strategy if command in READ_COMMANDS else None, + ) + ] + + def get_special_nodes(self) -> Optional[list["ClusterNode"]]: + """ + Returns a list of nodes for commands with a special policy. + """ + if not self._aggregate_nodes: + raise RedisClusterException('Cannot execute FT.CURSOR commands without FT.AGGREGATE') + + return self._aggregate_nodes + def keyslot(self, key: EncodableT) -> int: """ Find the keyslot for a given key. @@ -642,7 +707,7 @@ def set_response_callback(self, command: str, callback: ResponseCallbackT) -> No self.response_callbacks[command] = callback async def _determine_nodes( - self, command: str, *args: Any, node_flag: Optional[str] = None + self, command: str, *args: Any, request_policy: RequestPolicy, node_flag: Optional[str] = None ) -> List["ClusterNode"]: # Determine which nodes should be executed the command on. # Returns a list of target nodes. @@ -650,31 +715,22 @@ async def _determine_nodes( # get the nodes group for this command if it was predefined node_flag = self.command_flags.get(command) - if node_flag in self.node_flags: - if node_flag == self.__class__.DEFAULT_NODE: - # return the cluster's default node - return [self.nodes_manager.default_node] - if node_flag == self.__class__.PRIMARIES: - # return all primaries - return self.nodes_manager.get_nodes_by_server_type(PRIMARY) - if node_flag == self.__class__.REPLICAS: - # return all replicas - return self.nodes_manager.get_nodes_by_server_type(REPLICA) - if node_flag == self.__class__.ALL_NODES: - # return all nodes - return list(self.nodes_manager.nodes_cache.values()) - if node_flag == self.__class__.RANDOM: - # return a random node - return [random.choice(list(self.nodes_manager.nodes_cache.values()))] + if node_flag in self._command_flags_mapping: + request_policy = self._command_flags_mapping[node_flag] - # get the node that holds the key's slot - return [ - self.nodes_manager.get_node_from_slot( - await self._determine_slot(command, *args), - self.read_from_replicas and command in READ_COMMANDS, - self.load_balancing_strategy if command in READ_COMMANDS else None, - ) - ] + policy_callback = self._policies_callback_mapping[request_policy] + + if request_policy == RequestPolicy.DEFAULT_KEYED: + nodes = await policy_callback(command, *args) + elif request_policy == RequestPolicy.DEFAULT_KEYLESS: + nodes = policy_callback(command) + else: + nodes = policy_callback() + + if command.lower() == "ft.aggregate": + self._aggregate_nodes = nodes + + return nodes async def _determine_slot(self, command: str, *args: Any) -> int: if self.command_flags.get(command) == SLOT_ID: @@ -779,6 +835,31 @@ async def execute_command(self, *args: EncodableT, **kwargs: Any) -> Any: target_nodes_specified = True retry_attempts = 0 + command_policies = await self._policy_resolver.resolve(args[0].lower()) + + if not command_policies and not target_nodes_specified: + command_flag = self.command_flags.get(command) + if not command_flag: + # Fallback to default policy + if not self.get_default_node(): + slot = None + else: + slot = await self._determine_slot(*args) + if not slot: + command_policies = CommandPolicies() + else: + command_policies = CommandPolicies( + request_policy=RequestPolicy.DEFAULT_KEYED, + response_policy=ResponsePolicy.DEFAULT_KEYED, + ) + else: + if command_flag in self._command_flags_mapping: + command_policies = CommandPolicies(request_policy=self._command_flags_mapping[command_flag]) + else: + command_policies = CommandPolicies() + elif not command_policies and target_nodes_specified: + command_policies = CommandPolicies() + # Add one for the first execution execute_attempts = 1 + retry_attempts for _ in range(execute_attempts): @@ -794,7 +875,7 @@ async def execute_command(self, *args: EncodableT, **kwargs: Any) -> Any: if not target_nodes_specified: # Determine the nodes to execute the command on target_nodes = await self._determine_nodes( - *args, node_flag=passed_targets + *args, request_policy=command_policies.request_policy, node_flag=passed_targets ) if not target_nodes: raise RedisClusterException( @@ -805,10 +886,10 @@ async def execute_command(self, *args: EncodableT, **kwargs: Any) -> Any: # Return the processed result ret = await self._execute_command(target_nodes[0], *args, **kwargs) if command in self.result_callbacks: - return self.result_callbacks[command]( + ret = self.result_callbacks[command]( command, {target_nodes[0].name: ret}, **kwargs ) - return ret + return self._policies_callback_mapping[command_policies.response_policy](ret) else: keys = [node.name for node in target_nodes] values = await asyncio.gather( @@ -823,7 +904,7 @@ async def execute_command(self, *args: EncodableT, **kwargs: Any) -> Any: return self.result_callbacks[command]( command, dict(zip(keys, values)), **kwargs ) - return dict(zip(keys, values)) + return self._policies_callback_mapping[command_policies.response_policy](dict(zip(keys, values))) except Exception as e: if retry_attempts > 0 and type(e) in self.__class__.ERRORS_ALLOW_RETRY: # The nodes and slots cache were should be reinitialized. @@ -1739,6 +1820,7 @@ def __init__(self, position: int, *args: Any, **kwargs: Any) -> None: self.kwargs = kwargs self.position = position self.result: Union[Any, Exception] = None + self.command_policies: Optional[CommandPolicies] = None def __repr__(self) -> str: return f"[{self.position}] {self.args} ({self.kwargs})" @@ -1979,16 +2061,44 @@ async def _execute( nodes = {} for cmd in todo: passed_targets = cmd.kwargs.pop("target_nodes", None) + command_policies = await client._policy_resolver.resolve(cmd.args[0].lower()) + if passed_targets and not client._is_node_flag(passed_targets): target_nodes = client._parse_target_nodes(passed_targets) + + if not command_policies: + command_policies = CommandPolicies() else: + if not command_policies: + command_flag = client.command_flags.get(cmd.args[0]) + if not command_flag: + # Fallback to default policy + if not client.get_default_node(): + slot = None + else: + slot = await client._determine_slot(*cmd.args) + if not slot: + command_policies = CommandPolicies() + else: + command_policies = CommandPolicies( + request_policy=RequestPolicy.DEFAULT_KEYED, + response_policy=ResponsePolicy.DEFAULT_KEYED, + ) + else: + if command_flag in client._command_flags_mapping: + command_policies = CommandPolicies( + request_policy=client._command_flags_mapping[command_flag]) + else: + command_policies = CommandPolicies() + target_nodes = await client._determine_nodes( - *cmd.args, node_flag=passed_targets + *cmd.args, request_policy=command_policies.request_policy, node_flag=passed_targets ) if not target_nodes: raise RedisClusterException( f"No targets were found to execute {cmd.args} command on" ) + cmd.command_policies = command_policies if len(target_nodes) > 1: raise RedisClusterException(f"Too many targets for command {cmd.args}") node = target_nodes[0] @@ -2009,8 +2119,10 @@ async def _execute( for cmd in todo: if isinstance(cmd.result, (TryAgainError, MovedError, AskError)): try: - cmd.result = await client.execute_command( - *cmd.args, **cmd.kwargs + cmd.result = client._policies_callback_mapping[cmd.command_policies.response_policy]( + await client.execute_command( + *cmd.args, **cmd.kwargs + ) ) except Exception as e: cmd.result = e diff --git a/redis/cluster.py b/redis/cluster.py index c6e45acc6b..d739cf8203 100644 --- a/redis/cluster.py +++ b/redis/cluster.py @@ -1245,7 +1245,11 @@ def _internal_execute_command(self, *args, **kwargs): passed_targets = kwargs.pop("target_nodes", None) command_policies = self._policy_resolver.resolve(args[0].lower()) - if not command_policies: + if passed_targets is not None and not self._is_nodes_flag(passed_targets): + target_nodes = self._parse_target_nodes(passed_targets) + target_nodes_specified = True + + if not command_policies and not target_nodes_specified: command = args[0].upper() if len(args) >= 2 and f"{args[0]} {args[1]}".upper() in self.command_flags: command = f"{args[0]} {args[1]}".upper() @@ -1256,10 +1260,10 @@ def _internal_execute_command(self, *args, **kwargs): if not command_flag: # Fallback to default policy if not self.get_default_node(): - keys = None + slot = None else: - keys = self._get_command_keys(*args) - if not keys or len(keys) == 0: + slot = self.determine_slot(*args) + if not slot: command_policies = CommandPolicies() else: command_policies = CommandPolicies( @@ -1271,10 +1275,9 @@ def _internal_execute_command(self, *args, **kwargs): command_policies = CommandPolicies(request_policy=self._command_flags_mapping[command_flag]) else: command_policies = CommandPolicies() + elif not command_policies and target_nodes_specified: + command_policies = CommandPolicies() - if passed_targets is not None and not self._is_nodes_flag(passed_targets): - target_nodes = self._parse_target_nodes(passed_targets) - target_nodes_specified = True # If an error that allows retrying was thrown, the nodes and slots # cache were reinitialized. We will retry executing the command with # the updated cluster setup only when the target nodes can be @@ -2573,6 +2576,7 @@ def __init__(self, args, options=None, position=None): self.result = None self.node = None self.asking = False + self.command_policies: Optional[CommandPolicies] = None class NodeCommands: @@ -2933,33 +2937,6 @@ def _send_cluster_commands( for c in attempt: command_policies = self._pipe._policy_resolver.resolve(c.args[0].lower()) - if not command_policies: - command = c.args[0].upper() - if len(c.args) >= 2 and f"{c.args[0]} {c.args[1]}".upper() in self._pipe.command_flags: - command = f"{c.args[0]} {c.args[1]}".upper() - - # We only could resolve key properties if command is not - # in a list of pre-defined request policies - command_flag = self.command_flags.get(command) - if not command_flag: - # Fallback to default policy - if not self._pipe.get_default_node(): - keys = None - else: - keys = self._pipe._get_command_keys(*c.args) - if not keys or len(keys) == 0: - command_policies = CommandPolicies() - else: - command_policies = CommandPolicies( - request_policy=RequestPolicy.DEFAULT_KEYED, - response_policy=ResponsePolicy.DEFAULT_KEYED, - ) - else: - if command_flag in self._pipe._command_flags_mapping: - command_policies = CommandPolicies(request_policy=self._pipe._command_flags_mapping[command_flag]) - else: - command_policies = CommandPolicies() - while True: # refer to our internal node -> slot table that # tells us where a given command should route to. @@ -2968,7 +2945,38 @@ def _send_cluster_commands( passed_targets = c.options.pop("target_nodes", None) if passed_targets and not self._is_nodes_flag(passed_targets): target_nodes = self._parse_target_nodes(passed_targets) + + if not command_policies: + command_policies = CommandPolicies() else: + if not command_policies: + command = c.args[0].upper() + if len(c.args) >= 2 and f"{c.args[0]} {c.args[1]}".upper() in self._pipe.command_flags: + command = f"{c.args[0]} {c.args[1]}".upper() + + # We only could resolve key properties if command is not + # in a list of pre-defined request policies + command_flag = self.command_flags.get(command) + if not command_flag: + # Fallback to default policy + if not self._pipe.get_default_node(): + keys = None + else: + keys = self._pipe._get_command_keys(*c.args) + if not keys or len(keys) == 0: + command_policies = CommandPolicies() + else: + command_policies = CommandPolicies( + request_policy=RequestPolicy.DEFAULT_KEYED, + response_policy=ResponsePolicy.DEFAULT_KEYED, + ) + else: + if command_flag in self._pipe._command_flags_mapping: + command_policies = CommandPolicies( + request_policy=self._pipe._command_flags_mapping[command_flag]) + else: + command_policies = CommandPolicies() + target_nodes = self._determine_nodes( *c.args, request_policy=command_policies.request_policy, node_flag=passed_targets ) @@ -2976,6 +2984,7 @@ def _send_cluster_commands( raise RedisClusterException( f"No targets were found to execute {c.args} command on" ) + c.command_policies = command_policies if len(target_nodes) > 1: raise RedisClusterException( f"Too many targets for command {c.args}" @@ -3100,8 +3109,10 @@ def _send_cluster_commands( if c.args[0] in self._pipe.cluster_response_callbacks: # Remove keys entry, it needs only for cache. c.options.pop("keys", None) - c.result = self._pipe.cluster_response_callbacks[c.args[0]]( - c.result, **c.options + c.result = self._pipe._policies_callback_mapping[c.command_policies.response_policy]( + self._pipe.cluster_response_callbacks[c.args[0]]( + c.result, **c.options + ) ) response.append(c.result) diff --git a/redis/commands/policies.py b/redis/commands/policies.py index 7413f3f68d..ba2cc8968c 100644 --- a/redis/commands/policies.py +++ b/redis/commands/policies.py @@ -1,7 +1,9 @@ +import asyncio from abc import ABC, abstractmethod from typing import Optional -from redis._parsers.commands import CommandPolicies, PolicyRecords, RequestPolicy, ResponsePolicy, CommandsParser +from redis._parsers.commands import CommandPolicies, PolicyRecords, RequestPolicy, ResponsePolicy, CommandsParser, \ + AsyncCommandsParser STATIC_POLICIES: PolicyRecords = { 'ft': { @@ -39,7 +41,7 @@ class PolicyResolver(ABC): @abstractmethod - def resolve(self, command_name: str) -> CommandPolicies: + def resolve(self, command_name: str) -> Optional[CommandPolicies]: """ Resolves the command name and determines the associated command policies. @@ -64,6 +66,34 @@ def with_fallback(self, fallback: "PolicyResolver") -> "PolicyResolver": """ pass +class AsyncPolicyResolver(ABC): + + @abstractmethod + async def resolve(self, command_name: str) -> Optional[CommandPolicies]: + """ + Resolves the command name and determines the associated command policies. + + Args: + command_name: The name of the command to resolve. + + Returns: + CommandPolicies: The policies associated with the specified command. + """ + pass + + @abstractmethod + def with_fallback(self, fallback: "AsyncPolicyResolver") -> "AsyncPolicyResolver": + """ + Factory method to instantiate an async policy resolver with a fallback resolver. + + Args: + fallback: Fallback resolver + + Returns: + AsyncPolicyResolver: Returns a new policy resolver with the specified fallback resolver. + """ + pass + class BasePolicyResolver(PolicyResolver): """ Base class for policy resolvers. @@ -98,6 +128,40 @@ def resolve(self, command_name: str) -> Optional[CommandPolicies]: def with_fallback(self, fallback: "PolicyResolver") -> "PolicyResolver": pass +class AsyncBasePolicyResolver(AsyncPolicyResolver): + """ + Async base class for policy resolvers. + """ + def __init__(self, policies: PolicyRecords, fallback: Optional[AsyncPolicyResolver] = None) -> None: + self._policies = policies + self._fallback = fallback + + async def resolve(self, command_name: str) -> Optional[CommandPolicies]: + parts = command_name.split(".") + + if len(parts) > 2: + raise ValueError(f"Wrong command or module name: {command_name}") + + module, command = parts if len(parts) == 2 else ("core", parts[0]) + + if self._policies.get(module, None) is None: + if self._fallback is not None: + return await self._fallback.resolve(command_name) + else: + return None + + if self._policies.get(module).get(command, None) is None: + if self._fallback is not None: + return await self._fallback.resolve(command_name) + else: + return None + + return self._policies.get(module).get(command) + + @abstractmethod + def with_fallback(self, fallback: "AsyncPolicyResolver") -> "AsyncPolicyResolver": + pass + class DynamicPolicyResolver(BasePolicyResolver): """ @@ -130,4 +194,35 @@ def __init__(self, fallback: Optional[PolicyResolver] = None) -> None: super().__init__(STATIC_POLICIES, fallback) def with_fallback(self, fallback: "PolicyResolver") -> "PolicyResolver": - return StaticPolicyResolver(fallback) \ No newline at end of file + return StaticPolicyResolver(fallback) + +class AsyncDynamicPolicyResolver(AsyncBasePolicyResolver): + """ + Async version of DynamicPolicyResolver. + """ + def __init__(self, policy_records: PolicyRecords, fallback: Optional[AsyncPolicyResolver] = None) -> None: + """ + Parameters: + policy_records (PolicyRecords): Policy records. + fallback (Optional[AsyncPolicyResolver]): An optional resolver to be used when the + primary policies cannot handle a specific request. + """ + super().__init__(policy_records, fallback) + + def with_fallback(self, fallback: "AsyncPolicyResolver") -> "AsyncPolicyResolver": + return AsyncDynamicPolicyResolver(self._policies, fallback) + +class AsyncStaticPolicyResolver(AsyncBasePolicyResolver): + """ + Async version of StaticPolicyResolver. + """ + def __init__(self, fallback: Optional[AsyncPolicyResolver] = None) -> None: + """ + Parameters: + fallback (Optional[AsyncPolicyResolver]): An optional fallback policy resolver + used for resolving policies if static policies are inadequate. + """ + super().__init__(STATIC_POLICIES, fallback) + + def with_fallback(self, fallback: "AsyncPolicyResolver") -> "AsyncPolicyResolver": + return AsyncStaticPolicyResolver(fallback) \ No newline at end of file diff --git a/tests/test_asyncio/test_command_parser.py b/tests/test_asyncio/test_command_parser.py new file mode 100644 index 0000000000..da714a13d7 --- /dev/null +++ b/tests/test_asyncio/test_command_parser.py @@ -0,0 +1,69 @@ +import pytest + +from redis._parsers import AsyncCommandsParser +from redis._parsers.commands import RequestPolicy, ResponsePolicy +from tests.conftest import skip_if_server_version_lt + + +class TestAsyncCommandParser: + @skip_if_server_version_lt("7.0.0") + @pytest.mark.onlycluster + @pytest.mark.asyncio + async def test_get_command_policies(self, r): + commands_parser = AsyncCommandsParser() + await commands_parser.initialize(node=r.get_default_node()) + expected_command_policies = { + 'core': { + 'keys': ['keys', RequestPolicy.ALL_SHARDS, ResponsePolicy.DEFAULT_KEYLESS], + 'acl setuser': ['acl setuser', RequestPolicy.ALL_NODES, ResponsePolicy.ALL_SUCCEEDED], + 'exists': ['exists', RequestPolicy.MULTI_SHARD, ResponsePolicy.AGG_SUM], + 'config resetstat': ['config resetstat', RequestPolicy.ALL_NODES, ResponsePolicy.ALL_SUCCEEDED], + 'slowlog len': ['slowlog len', RequestPolicy.ALL_NODES, ResponsePolicy.AGG_SUM], + 'scan': ['scan', RequestPolicy.SPECIAL, ResponsePolicy.SPECIAL], + 'latency history': ['latency history', RequestPolicy.ALL_NODES, ResponsePolicy.SPECIAL], + 'memory doctor': ['memory doctor', RequestPolicy.ALL_SHARDS, ResponsePolicy.SPECIAL], + 'randomkey': ['randomkey', RequestPolicy.ALL_SHARDS, ResponsePolicy.SPECIAL], + 'mget': ['mget', RequestPolicy.MULTI_SHARD, ResponsePolicy.DEFAULT_KEYED], + 'function restore': ['function restore', RequestPolicy.ALL_SHARDS, ResponsePolicy.ALL_SUCCEEDED], + }, + 'json': { + 'debug': ['debug', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + 'get': ['get', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + }, + 'ft': { + 'search': ['search', RequestPolicy.DEFAULT_KEYLESS, ResponsePolicy.DEFAULT_KEYLESS], + 'create': ['create', RequestPolicy.DEFAULT_KEYLESS, ResponsePolicy.DEFAULT_KEYLESS], + }, + 'bf': { + 'add': ['add', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + 'madd': ['madd', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + }, + 'cf': { + 'add': ['add', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + 'mexists': ['mexists', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + }, + 'tdigest': { + 'add': ['add', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + 'min': ['min', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + }, + 'ts': { + 'create': ['create', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + 'info': ['info', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + }, + 'topk': { + 'list': ['list', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + 'query': ['query', RequestPolicy.DEFAULT_KEYED, ResponsePolicy.DEFAULT_KEYED], + } + } + + actual_policies = await commands_parser.get_command_policies() + assert len(actual_policies) > 0 + + for module_name, commands in expected_command_policies.items(): + for command, command_policies in commands.items(): + assert command in actual_policies[module_name] + assert command_policies == [ + command, + actual_policies[module_name][command].request_policy, + actual_policies[module_name][command].response_policy + ] \ No newline at end of file diff --git a/tests/test_asyncio/test_command_policies.py b/tests/test_asyncio/test_command_policies.py new file mode 100644 index 0000000000..ff54a531e0 --- /dev/null +++ b/tests/test_asyncio/test_command_policies.py @@ -0,0 +1,147 @@ +import random + +import pytest +from mock import patch + +from redis import ResponseError +from redis._parsers.commands import CommandPolicies, RequestPolicy, ResponsePolicy +from redis.asyncio import RedisCluster +from redis.commands.policies import AsyncDynamicPolicyResolver, AsyncStaticPolicyResolver +from redis.commands.search.aggregation import AggregateRequest +from redis.commands.search.field import NumericField, TextField + + +@pytest.mark.asyncio +@pytest.mark.onlycluster +class TestBasePolicyResolver: + async def test_resolve(self): + zcount_policy = CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED) + rpoplpush_policy = CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYED, response_policy=ResponsePolicy.DEFAULT_KEYED) + + dynamic_resolver = AsyncDynamicPolicyResolver({ + 'core': { + 'zcount': zcount_policy, + 'rpoplpush': rpoplpush_policy, + } + }) + assert await dynamic_resolver.resolve('zcount') == zcount_policy + assert await dynamic_resolver.resolve('rpoplpush') == rpoplpush_policy + + with pytest.raises(ValueError, match="Wrong command or module name: foo.bar.baz"): + await dynamic_resolver.resolve('foo.bar.baz') + + assert await dynamic_resolver.resolve('foo.bar') is None + assert await dynamic_resolver.resolve('core.foo') is None + + # Test that policy fallback correctly + static_resolver = AsyncStaticPolicyResolver() + with_fallback_dynamic_resolver = dynamic_resolver.with_fallback(static_resolver) + resolved_policies = await with_fallback_dynamic_resolver.resolve('ft.aggregate') + + assert resolved_policies.request_policy == RequestPolicy.DEFAULT_KEYLESS + assert resolved_policies.response_policy == ResponsePolicy.DEFAULT_KEYLESS + + # Extended chain with one more resolver + foo_bar_policy = CommandPolicies(request_policy=RequestPolicy.DEFAULT_KEYLESS, response_policy=ResponsePolicy.DEFAULT_KEYLESS) + + another_dynamic_resolver = AsyncDynamicPolicyResolver({ + 'foo': { + 'bar': foo_bar_policy, + } + }) + with_fallback_static_resolver = static_resolver.with_fallback(another_dynamic_resolver) + with_double_fallback_dynamic_resolver = dynamic_resolver.with_fallback(with_fallback_static_resolver) + + assert await with_double_fallback_dynamic_resolver.resolve('foo.bar') == foo_bar_policy + +@pytest.mark.onlycluster +@pytest.mark.asyncio +class TestClusterWithPolicies: + async def test_resolves_correctly_policies(self, r: RedisCluster, monkeypatch): + # original nodes selection method + determine_nodes = r._determine_nodes + determined_nodes = [] + primary_nodes = r.get_primaries() + calls = iter(list(range(len(primary_nodes)))) + + async def wrapper(*args, request_policy: RequestPolicy, **kwargs): + nonlocal determined_nodes + determined_nodes = await determine_nodes(*args, request_policy=request_policy, **kwargs) + return determined_nodes + + # Mock random.choice to always return a pre-defined sequence of nodes + monkeypatch.setattr(random, "choice", lambda seq: seq[next(calls)]) + + with patch.object(r, '_determine_nodes', side_effect=wrapper, autospec=True): + # Routed to a random primary node + await r.ft().create_index( + [ + NumericField("random_num"), + TextField("title"), + TextField("body"), + TextField("parent"), + ] + ) + assert determined_nodes[0] == primary_nodes[0] + + # Routed to another random primary node + info = await r.ft().info() + assert info['index_name'] == 'idx' + assert determined_nodes[0] == primary_nodes[1] + + expected_node = await r.get_node_from_slot('FT.SUGLEN', *['foo']) + await r.ft().suglen('foo') + assert determined_nodes[0] == expected_node[0] + + # Indexing a document + await r.hset( + "search", + mapping={ + "title": "RediSearch", + "body": "Redisearch impements a search engine on top of redis", + "parent": "redis", + "random_num": 10, + }, + ) + await r.hset( + "ai", + mapping={ + "title": "RedisAI", + "body": "RedisAI executes Deep Learning/Machine Learning models and managing their data.", # noqa + "parent": "redis", + "random_num": 3, + }, + ) + await r.hset( + "json", + mapping={ + "title": "RedisJson", + "body": "RedisJSON implements ECMA-404 The JSON Data Interchange Standard as a native data type.", # noqa + "parent": "redis", + "random_num": 8, + }, + ) + + req = AggregateRequest("redis").group_by( + "@parent" + ).cursor(1) + res = await r.ft().aggregate(req) + cursor = res.cursor + + # Ensure that aggregate node was cached. + assert determined_nodes[0] == r._aggregate_nodes[0] + + await r.ft().aggregate(cursor) + + # Verify that FT.CURSOR dispatched to the same node. + assert determined_nodes[0] == r._aggregate_nodes[0] + + # Error propagates to a user + with pytest.raises(ResponseError, match="Cursor not found, id: 0"): + await r.ft().aggregate(cursor) + + assert determined_nodes[0] == primary_nodes[2] + + # Core commands also randomly distributed across masters + await r.randomkey() + assert determined_nodes[0] == primary_nodes[0] \ No newline at end of file From 9600151cf895cfe8364c25b13f4b65e91a9edbec Mon Sep 17 00:00:00 2001 From: vladvildanov Date: Thu, 30 Oct 2025 11:00:44 +0200 Subject: [PATCH 12/13] Fixed method name --- redis/asyncio/cluster.py | 4 ++-- tests/test_asyncio/test_command_policies.py | 2 +- tests/test_command_policies.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/redis/asyncio/cluster.py b/redis/asyncio/cluster.py index f99143d29b..665e780038 100644 --- a/redis/asyncio/cluster.py +++ b/redis/asyncio/cluster.py @@ -438,7 +438,7 @@ def __init__( self._policies_callback_mapping: dict[Union[RequestPolicy, ResponsePolicy], Callable] = { RequestPolicy.DEFAULT_KEYLESS: lambda command_name: [self.get_random_primary_or_all_nodes(command_name)], - RequestPolicy.DEFAULT_KEYED: self.get_node_from_slot, + RequestPolicy.DEFAULT_KEYED: self.get_nodes_from_slot, RequestPolicy.DEFAULT_NODE: lambda: [self.get_default_node()], RequestPolicy.ALL_SHARDS: self.get_primaries, RequestPolicy.ALL_NODES: self.get_nodes, @@ -661,7 +661,7 @@ def get_random_primary_node(self) -> "ClusterNode": """ return random.choice(self.get_primaries()) - async def get_node_from_slot(self, command: str, *args): + async def get_nodes_from_slot(self, command: str, *args): """ Returns a list of nodes that hold the specified keys' slots. """ diff --git a/tests/test_asyncio/test_command_policies.py b/tests/test_asyncio/test_command_policies.py index ff54a531e0..2c0f0d2ddb 100644 --- a/tests/test_asyncio/test_command_policies.py +++ b/tests/test_asyncio/test_command_policies.py @@ -89,7 +89,7 @@ async def wrapper(*args, request_policy: RequestPolicy, **kwargs): assert info['index_name'] == 'idx' assert determined_nodes[0] == primary_nodes[1] - expected_node = await r.get_node_from_slot('FT.SUGLEN', *['foo']) + expected_node = await r.get_nodes_from_slot('FT.SUGLEN', *['foo']) await r.ft().suglen('foo') assert determined_nodes[0] == expected_node[0] diff --git a/tests/test_command_policies.py b/tests/test_command_policies.py index 69854219bb..ca3ecb1036 100644 --- a/tests/test_command_policies.py +++ b/tests/test_command_policies.py @@ -91,7 +91,7 @@ def wrapper(*args, request_policy: RequestPolicy, **kwargs): assert info['index_name'] == 'idx' assert determined_nodes[0] == primary_nodes[1] - expected_node = r.get_node_from_slot('ft.suglen', *['FT.SUGLEN', 'foo']) + expected_node = r.get_nodes_from_slot('ft.suglen', *['FT.SUGLEN', 'foo']) r.ft().suglen('foo') assert determined_nodes[0] == expected_node[0] From bc297b9408d0c022a5798e61d29a88b9cd51b5f0 Mon Sep 17 00:00:00 2001 From: vladvildanov Date: Fri, 31 Oct 2025 11:46:54 +0200 Subject: [PATCH 13/13] Updated async to sync --- redis/_parsers/commands.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/redis/_parsers/commands.py b/redis/_parsers/commands.py index f236d1523d..bb1d92d0c7 100644 --- a/redis/_parsers/commands.py +++ b/redis/_parsers/commands.py @@ -542,7 +542,7 @@ async def get_command_policies(self) -> Awaitable[PolicyRecords]: """ command_with_policies = {} - async def extract_policies(data, module_name, command_name): + def extract_policies(data, module_name, command_name): """ Recursively extract policies from nested data structures. @@ -576,12 +576,12 @@ async def extract_policies(data, module_name, command_name): elif isinstance(data, list): # For lists, recursively process each element for item in data: - await extract_policies(item, module_name, command_name) + extract_policies(item, module_name, command_name) elif isinstance(data, dict): # For dictionaries, recursively process each value for value in data.values(): - await extract_policies(value, module_name, command_name) + extract_policies(value, module_name, command_name) for command, details in self.commands.items(): # Check whether the command has keys @@ -621,7 +621,7 @@ async def extract_policies(data, module_name, command_name): # Process tips for the main command if tips: - await extract_policies(tips, module_name, command_name) + extract_policies(tips, module_name, command_name) # Process subcommands if subcommands: @@ -651,6 +651,6 @@ async def extract_policies(data, module_name, command_name): # Recursively extract policies from the rest of the subcommand details for subcommand_detail in subcommand_details[1:]: - await extract_policies(subcommand_detail, module_name, subcmd_name) + extract_policies(subcommand_detail, module_name, subcmd_name) return command_with_policies \ No newline at end of file