-
Notifications
You must be signed in to change notification settings - Fork 24.4k
SRANDMEMBER RESP3 return should be Array, not Set #8504
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
431c81d to
dc9c86d
Compare
dc9c86d to
291e23f
Compare
src/t_set.c
Outdated
| addReplySetLen(c,count); | ||
| /* if the count was negative, return as array type since the reply | ||
| may contain duplicate element */ | ||
| !uniq ? addReplyArrayLen(c,count) : addReplySetLen(c,count); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although I don't think this is technically wrong, I think this ternary operator is uncommon usage in C
| !uniq ? addReplyArrayLen(c,count) : addReplySetLen(c,count); | |
| if (!uniq) | |
| addReplyArrayLen(c,count); | |
| else | |
| addReplySetLen(c,count) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed, thank you
|
hrandfield and zrandmember can also return distinct arrays, should we be returning them as sets? I don't see a conversation on the original PR #8297 |
|
the response type for HRANDFIELD etc was discussed here: #8297 (comment) one would say that It might be too late to fix now due to backwards compatibility, but of course fixing if for a negative COUNT is a must (no debate about that). note this part of the spec:
in the non-unique (negative count) variant of these RAND* commands we also guarantee random order, not just random selection. so the @redis/core-team please share your thoughts. |
|
the next question would be if we wanna backport that fix to 6.0? |
|
"Normally Set replies should not contain the same element emitted multiple times, but the protocol does not enforce that: client libraries should try to handle such case, and in case of repeated elements, do some effort to avoid returning duplicated data, at least if some form of hash is used in order to return the reply. Otherwise when returning an array just reading what the protocol contains, duplicated items if present could be passed by client libraries to the caller. Many implementations will find it very natural to avoid duplicates. For instance they'll try to add every read element in some Map or Hash or Set data type, and adding the same element again will either replace the old copy or will fail silently, retaining the old copy." Also from the spec, which clearly outlines the current negative count behavior is OK, so I don't really trust the spec. Still, the spec doesn't require the items be unordered, so I think the current behavior is fine. It's a little odd we go through the work to order the response and then immediately throw away the ordering. https://redis.io/commands/srandmember documentation is also wrong. No mention of a set reply in Redis 6, which seems to be a pervasive issue with type changes in the docs. |
|
I would vote to fix the negative count, backport it to 6, and do nothing else. |
|
@madolson i'm not sure i understand what you meant with that quote from the spec, and then saying "the current negative count behavior is OK" And again, the spec does say the items in the set are unordered (meaning the client library can store them in a dict and lose the ordering), which makes it a bad fit for the negative count, in which we want to provide random order. |
|
@oranagra The spec says that clients should handle set replies with duplicate items. I agree that we should fix the negative count case, I wasn't arguing about that. The positive count case though, I think changing it is unnecessary backwards breaking change. There is nothing in the spec that says that set replies must be random. Unordered collection does not imply that the order is random. I think the response is fine. |
|
Negative fix & backport: aye. |
|
I think we should always return an array, it's more uniform and better describes what we're returning even if technically a set could fit. In a more general tone, given the other RESP3 bugs we've seen I think we need to give more weight to fixing for correctness rather than maintaining backwards compatibility. |
@madolson The spec says the client should handle that by removing these duplicate items if found. i'll put it like this: I agree with Yossi, RESP3 is "beta", and we want to fix these bugs rather than keep them for eternity, and given its low adoption, i hope it won't cause much harm. the only question in my eyes is if this should be backported to redis 6.0 or not. |
|
@oranagra I think it should be backported, we should accept some RESP3 pain but get things right rather than leave things awkward forever or have fixes diverge across versions. |
|
@oranagra I concede that if we started from scratch, I think using arrays for both positive and negative count makes the most sense. I'm against backwards incompatible changes, and I don't think that returning a set type for positive count is so wrong that we should break the contract for that. It looks like there is already a majority in favor of doing that though, so I'm fine with committing to that approach. @hwware, do you want to update the PR to return an array type for both positive and negative count values? |
|
I strongly feel that we wanna fix this (for positive count too) rather than live with the bug forever. But we said we're not gonna introduce breaking changes in patch level releases, so this means that in some cases we avoid fixing a bug if it causes compatibility issues, and let that old version remain buggy. In retrospect maybe we shouldn't even have fixed #8266 in 6.0.10, and should have let 6.0 keep that bug. The special consideration in both this PR and the one in #8266, is that we think the bug is in code that's not yet widely used, in which case we want to fix it ASAP before people use it, but i suppose we can take the safe approach and not backport this fix. |
|
turns out changing the response type of CASE2 wasn't so easy since the code redirected the call to |
|
Since it was decided to always return an array, should similar commands like SPOP also be changed to return an array? |
|
@Harrison88 i thought about it too, but i don't think SPOP needs to change. |
SRANDMEMBER with negative count (non unique) can return the same member multiple times, and the order of elements in the returned collection matters. For these reasons returning a RESP3 Set type is not valid for the negative count, but also not really valid for the positive (unique) variant either (the command returns an array of random picks, not a set) This PR also contains a minor optimization for SRANDMEMBER, HRANDFIELD, and ZRANDMEMBER, to avoid the temporary dict from being rehashed while it grows. Co-authored-by: Oran Agra <oran@redislabs.com>
see: * redis/redis#8391 * redis/redis#8504 Co-authored-by: Oran Agra <oran@redislabs.com>
SRANDMEMBER with negative count (non unique) can return the same member
multiple times, and the order of elements in the returned collection matters.
For these reasons returning a RESP3 Set type is not valid for the negative
count, but also not really valid for the positive (unique) variant either (the
command returns an array of random picks, not a set)
This PR also contains a minor optimization for SRANDMEMBER, HRANDFIELD,
and ZRANDMEMBER, to avoid the temporary dict from being rehashed while it grows.
Fixes #8503