These question are about the request_policy and response_policy fields in the command tips. I'd appreciate clarifications about the intention behind these values, and I'd also love to hear from client developers what was their interpretation of these tips.
-
SCAN's request_policy isspecial, without any explanation of what it means. My interpretation is that the client should iterate through the primary nodes, as if they were a list of list of keys, and flatten the results. This involves a lot of internal state - the client will need to keep the latest estimate of how many keys are in each node, and to map the user's count to an index into the current node. Essentially, making this command behave in a way which is similar to CMD is quite complex. Is this the intended interpretation of the command? -
LATENCY GRAPH | HISTOGRAM | HISTORY | DOCTOR | LATEST,FUNCTION STATS,MEMORY MALLOC-STATS | DOCTOR | STATS,INFOall havespecialresponse type, without any explanation of what it means. Most of these commands return ASCII art, and it isn't clear that the responses can be a combined in a way which maintains the same response type as in CMD. I think that they should be returned as a map, from each node's identifier to the output of each node. Is this close to the intended response? -
SLOWLOG GET,RANDOMKEY,KEYS,MGET,SCANhave a statedrequest_policybut noresponse_policy. I assume that this means "use your best judgment" on how to aggregate the results. These are my interpretations, I'd appreciate your opinion. 3.1.SLOWLOG GETshould behave like thespecialcases, and return a map from each node's identifier to the output of that node. 3.2.RANDOMKEYshould return the first value it finds. Ignore all empty replies, 3.3.KEYS,MGETandSCAN- I assume the arrays that are returned from each node can be combined (inMGET, in a way that matches the order of given keys) into a single array. -
All of these special cases require hand-tailored behavior. If I run
COMMANDon a cluster that uses novel modules, or runs a newer Redis version than the one that my client is aware of, is there some common-sense way of handling commands withspecialpolicies, or with missingresponse_policy?
Thanks!
Comment From: oranagra
This area is a bit obscure, and maybe also incomplete, I'll do my best to help.
special basically means that the hint system can't help you with this command. we attempted to provide hints about common handling of many commands, so that some generic handling code can be written and it'll implicitly support future commands (or module commands), but with some commands we simply can't help, and the client library may have to write dedicated code to handle them, route them, and aggregate the results.
so comparing the situation you had before these tips were created, were you had to decide how to handle each command or map them into groups on your own, at least now the majority of the commands can be handled in a generic way. but for some there's no remedy and you need to look at each separately and conclude what to do. the tips can't help you with these.
- specifically about SCAN there's an active discussion in #2702, and other than that all i can suggest is to see how it's already handled in cluster aware clients, or shift the problem to the caller somehow.
- you obviously can't aggregate the reply form the ascii-art ones, unless you put them into an array, this means shifting the problem to the caller (same as providing a mechanism to call them directly on a specific node). for some others (INFO, LATENCY [HISTOGRAM, LATEST, HISTORY], MEMORY MALLOC-STATS, FUNCTION STATS: it is possible in theory to write specific code to aggregate their responses. e.g. summing some fields, doing max or logical and / or on others, etc. but considering that the majority of these commands are admin related commands, i don't expect an APP to need them, so maybe a cluster client doesn't need to support them, or handle them in the same way we discussed for the ascii-art ones.
- the documentation explicitly states what it means when the response policy is missing. this usually applies to commands that return an array, or a map.
- SLOWLOG GET - just combine the responses into a single array (as documented in the above link).
- what you suggested seems right. i think maybe this command should be changed to
RESPONSE_POLICY:SPECIAL - MGET and KEYS should behave as documented in the above link (combine into a single array)
- i think we should change SCAN to
RESPONSE_POLICY:SPECIAL. or maybe document that REQUEST_POLICY:SPECIAL also implies RESPONSE_POLICY:SPECIAL.
- yes, that's the idea that they require special code. i think you can assume that newer versions are always backwards compatible with older versions, so a "special" command in a newer version will not break your special code, even if we create a new policy (unrecognized by the client) some day and assign it to the command. new commands (or module commands) with
specialthat are not explicitly supported by the client should probably just not be handled. i hope people will not create more special commands, and try to adhere to something that's easier to map and handle.
Comment From: nihohit
Thanks for the answer!
If special commands require specialized code, could the hint system or the command description in the site also contain some kind of expectation of behavior of that code? So that if I come to implement the special response to command X, I'll at least have some inkling of how you intended it to behave, and have a better chance of matching the behavior of other clients?
Comment From: oranagra
i think that in some cases it's obvious, and in other cases (like the ascii-art, or other debug related commands) it's either impossible or very extremely hard to figure out. if there's a specific command that you think something needs to be documented, feel free to make a PR to https://github.com/redis/redis-doc/pulls, or suggest something specific.
Comment From: nihohit
Right, so I would request that anything which is either impossible or hard to figure out will be explicitly documented as such, instead of only implicitly so. For example, if you agree with my suggestion to create a map for results that can't be aggregated, then let's make this official - IMO without Redis official wording, the different clients will not agree on the same behavior.
Another option is to ask clients to ask the users for specific routing - that is, instead of routing ASCII art requests to all nodes, only routing it to a single node and making this explicitly visible to the user. If a request can't be aggregated, then it can't be fanned-out in the first place.
Comment From: nihohit
Also, MSETNX is defined as atomic - "MSETNX will not perform any operation at all even if just a single key already exists.". This means that while it is easy to pass it and aggregate the results, its core promise is hard to implement.
The aggregate function that is suggested - agg_min - implies that it isn't atomic on a cluster - if you receive some 0s and some 1s, you hide the 1s from the user and return 0 - so the user isn't aware of the fact that some values were set.
Comment From: oranagra
@nihohit you're right regarding MSETNX. i think the request_policy of that command should be left empty (meaning it cannot be routed to more than one node). can you make a PR to fix it? and also take this opportunity to change SCAN and RANDOMKEY to have RESPONSE_POLICY:SPECIAL
Comment From: nihohit
https://github.com/redis/redis/pull/12417
I still would appreciate a more verbose explanation for the special policies. If I'll write such suggestions, can I open PRs to add them? if so, where should they appear?
Comment From: oranagra
i think it's either a more detailed general explanation in https://github.com/redis/redis-doc/blob/master/docs/reference/command-tips.md, or a specific explanation on specific commands at https://github.com/redis/redis-doc/tree/master/commands
Comment From: nihohit
and another thing that was pointed out to me - the multi-shard request tip should be called multi-slot, since if you only split the commands according to target shard, you might get CROSSSLOTS error. You need to split the commands according to slots. Can I fix the name of the tip, and / or the documentation?
Comment From: oranagra
we can't fix the name now. but let's make it clear in the docs. can you make a PR?
Comment From: nihohit
https://github.com/redis/redis-doc/pull/2493