Skip to content

Conversation

@jonahharris
Copy link
Contributor

@jonahharris jonahharris commented Sep 24, 2020

Add ZRANGESTORE command, and improve ZSTORE command to deprecated Z[REV]RANGE[BYSCORE|BYLEN].

Syntax for the new ZRANGESTORE command:
ZRANGESTORE [BYSCORE | BYLEX] [REV] [LIMIT offset count]

New syntax for ZRANGE:
ZRANGE [BYSCORE | BYLEX] [REV] [WITHSCORES] [LIMIT offset count]

Old syntax for ZRANGE:
ZRANGE [WITHSCORES]

Other ZRANGE commands remain unchanged.

The implementation uses common code for all of these, by utilizing a consumer interface that in one
command response to the client, and in the other command stores a zset key.

@oranagra
Copy link
Member

@jonahharris thank you for this PR.
As i stated earlier i think the approach you took is good.
It reduces duplicate code and make it easier to maintain (decreasing chance for inconsistencies between the various similar commands and chance for bugs that are unspotted)

However, this PR is quite impossible to review (and merge), it looks like your editor re-formatted all the code, so every line is changed.
For instance compare zslFree to it's old version (indentation, line breaks etc).

The obvious problems with this are:

  1. harder to review the changes
  2. harder to later track the history of the code in the blame log
  3. will create merge conflicts with any other PR or fork.

Besides, this is not the redis style, although it may not be to anyone's liking, it's better to have consistent style across the project.

It also looks like you changed the structure of the file (although i can't be sure), please avoid unnecessary changes, for an easier review.

I know it would be complicated to change it at this stage, but it would be a necessary effort in order to move forward.
I also know that even without this re-formatting many functions were refactored to share code, so the code review will be hard anyway, but the formatting changes need to be undone.

one other request, please copy most the detailed description of the change that you posted in the issue to the PR's top comment, i'll use that as the commit comment when i squash-merge this.

Thanks again for the efforts.

@jonahharris
Copy link
Contributor Author

jonahharris commented Sep 25, 2020

Yeah. I mentioned the formatting stuff in the issue. I'm happy to copy the changes into the normal Redis format - I just can't work with that format when I'm adding functionality as it's not very clean/organized. I'll get that updated and resubmitted shortly.

@jonahharris
Copy link
Contributor Author

Merged changes and made most formatting changes. Still need to correct indentation for new code.

@oranagra
Copy link
Member

@jonahharris I saw some question about function prototypes in my email but I can't find it here, maybe you deleted it.
IMO these should be at the top of the file, unless they're not needed (if the functions are ordered that way).
So for new code you can order it (put them near the top), but I'd like to avoid moving exiting code (don't generate a diff on code that didn't change), so in these cases please put the prototypes near the top.

@jonahharris
Copy link
Contributor Author

I deleted it as I reordered everything to not really need them, but the one I couldn’t remove will go to the top. Now that the diff is readable, let me know what else you’d like changed and I’ll try to get to it ASAP.

Copy link
Member

@oranagra oranagra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jonahharris i reviewed all the code and added many comments.
some are about styling, and if you prefer not to deal with it, i can make a quick sweep to change it before merging.

other comments are about the implementation and bugs.

but most important one is about the command syntax, i think we had some misunderstanding, if my comment makes sense to you, please revise the code, if not, we should open it for a wider discussion..

lastly, we'll need to add some test coverage and documentation for the new commands, but we can deal with it later.

@oranagra oranagra added release-notes indication that this issue needs to be mentioned in the release notes state:major-decision Requires core team consensus state:needs-doc-pr requires a PR to redis-doc repository state:needs-test-code the PR is missing test code labels Sep 26, 2020
@oranagra oranagra added this to the Redis 6.2 milestone Sep 26, 2020
@oranagra oranagra self-assigned this Sep 26, 2020
@oranagra
Copy link
Member

oranagra commented Oct 5, 2020

@jonahharris just want to confirm that the ball is at your court.
i.e. i'm waiting for you to implement the remaining suggested changes (most importantly the command syntax).
right?

@jonahharris
Copy link
Contributor Author

jonahharris commented Oct 6, 2020

Hey @oranagra - yes, I'm currently working on that. I only had a few consecutive days I could work on it and now I'm back to piecemeal. I'm almost done with all the changes you requested and hope to have that up in the next day or so.

@jonahharris
Copy link
Contributor Author

@oranagra assuming all goes well, what would you predict the release timeline looks like? I want to make sure this doesn't fall off and, with that timeline in mind, I'll figure out how to devote time to it. I probably have only an hour or so left, but have been pretty busy. I'll try to get to it this weekend, but will rebalance the stuff on my plate to ensure it does if I need to.

@oranagra
Copy link
Member

@jonahharris we aim to release 6.2 at the end of the year, or at least have release candidate.
big things better be merged ahead of time so they get to stabilize in unstable.
so you still have plenty of time, but considering you only have a few hours left, better nail it while it's fresh.
Also IIRC you had some GEORADIUS related PR you wanted to make after it which can also fit into 6.2.

@oranagra oranagra linked an issue Oct 19, 2020 that may be closed by this pull request
@oranagra oranagra removed this from the Next minor backlog milestone Oct 19, 2020
@oranagra
Copy link
Member

@jonahharris, friendly reminder: we have about a month before putting out a release candidate.
hope you can find the time to push this through.
thanks.

@oranagra
Copy link
Member

oranagra commented Dec 2, 2020

@jonahharris we probably missed the mark of 6.2 RC1, but maybe these changes can still make it to RC2.
do you wanna try to pick this up, or maybe someone else can take over?

@jonahharris
Copy link
Contributor Author

Damn. Time flies. I will definitely get this done by EOW.

@oranagra
Copy link
Member

@jonahharris gentle nudge about this. in case you want someone else to try and pick this up from where you left it.

@oranagra
Copy link
Member

i'm picking this up. (posting to avoid collision)

@oranagra
Copy link
Member

@redis/core-team please approve a new ZRANGESTORE command and improvements to ZRANGE (see top comment)

@oranagra oranagra added approval-needed Waiting for core team approval to be merged state:to-be-merged The PR should be merged soon, even if not yet ready, this is used so that it won't be forgotten and removed state:needs-test-code the PR is missing test code labels Dec 31, 2020
@oranagra
Copy link
Member

oranagra commented Jan 1, 2021

initial draft for the documentation PR: redis/redis-doc#1482
note that i'm not very comfortable with how it came out.
documenting all the nuances and instructions of BYSCORE / BYLEX / BYRANK in one page can make it quite complex.
instead i added a note to refer to the documentation of the deprecated commands for details (which sounds like a bad idea).
maybe that's a hint that this change is all wrong?
i.e. there are a lot of details about inclusive / exclusive searches and how the lexicographic ordering works, maybe unifying them into one command is wrong?

@jonahharris
Copy link
Contributor Author

I don't know. It all makes sense to me and seems easy enough to understand. Most people I know who look at the Redis docs tend to just copy the examples and tailor them to their own case. As long as there are examples with the descriptions, as there are for the current commands, I don't see how it's any different.

itamarhaber
itamarhaber previously approved these changes Jan 5, 2021
madolson
madolson previously approved these changes Jan 6, 2021
Copy link
Contributor

@madolson madolson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor comment, API LGTM

@oranagra oranagra dismissed stale reviews from madolson and itamarhaber via 7fd0943 January 6, 2021 07:23
madolson
madolson previously approved these changes Jan 6, 2021
yossigo
yossigo previously approved these changes Jan 7, 2021
Copy link
Collaborator

@yossigo yossigo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API LGTM, only had a quick look at the code.

Co-authored-by: Yossi Gottlieb <yossigo@gmail.com>
@oranagra oranagra dismissed stale reviews from yossigo and madolson via 3e76af4 January 7, 2021 08:47
@oranagra oranagra merged commit b5029df into redis:unstable Jan 7, 2021
@oranagra oranagra mentioned this pull request Jan 10, 2021
addReplyBulkCBuffer(c,ln->ele,sdslen(ln->ele));
if (withscores) addReplyDouble(c,ln->score);
handler->emitResultFromCBuffer(handler, ln->ele, sdslen(ln->ele),
((withscores) ? ln->score : ln->score));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oranagra ((withscores) ? ln->score : ln->score) Shouldn't it be changed to ln->score

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're right, the ternary op can be dropped. but at least that's not a bug.
the store variant always passes true for withscores, and the non-store variant ignores the score if it wasn't requested.

break;
}

if (opt_withscores || store) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oranagra I read the zunionInterDiffGenericCommand function, it should be similar, when there is a flag store, only the number of results will be replied, without specific data.
If there is a store flag, zrangeResultHandlerScoreEmissionEnable should not effect.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm not sure what you mean by this comment.
in case store is set, the call to zrangeResultHandlerScoreEmissionEnable is in some way redundant. since the two variables it sets are only used by the non-store variant handlers, so we can remove the || store from the above condition, and this function will never be called.

there's something a bit ugly in my final changes to this PR, is that i added the store argument to this function.
in theory, the handler should know what to do.
but i wanted to give syntax error on the WITHSCORES argument on the store variant, and added that store argument, that's where the mess started.

Copy link
Collaborator

@sundb sundb Jan 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

struct zrange_result_handler {
    zrange_consumer_type                 type;
    client                              *client;
    robj                                *dstkey;
    robj                                *dstobj;
    void                                *userdata;
    int                                  withscores;
    int                                  should_emit_array_length;
    int                                  store; <- here what I add
    zrangeResultBeginFunction            beginResultEmission;
    zrangeResultFinalizeFunction         finalizeResultEmission;
    zrangeResultEmitCBufferFunction      emitResultFromCBuffer;
    zrangeResultEmitLongLongFunction     emitResultFromLongLong;
};

Your idea should be exactly what I am trying to do. zrange_result_handler should know what it should do.

Copy link
Member

@oranagra oranagra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sundb thanks for this review.
if i understand you correctly, you're suggesting some cleanups (not reporting bugs or improvements).

since this one is merged already, feel free to open a PR for these.

addReplyBulkCBuffer(c,ln->ele,sdslen(ln->ele));
if (withscores) addReplyDouble(c,ln->score);
handler->emitResultFromCBuffer(handler, ln->ele, sdslen(ln->ele),
((withscores) ? ln->score : ln->score));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're right, the ternary op can be dropped. but at least that's not a bug.
the store variant always passes true for withscores, and the non-store variant ignores the score if it wasn't requested.

break;
}

if (opt_withscores || store) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm not sure what you mean by this comment.
in case store is set, the call to zrangeResultHandlerScoreEmissionEnable is in some way redundant. since the two variables it sets are only used by the non-store variant handlers, so we can remove the || store from the above condition, and this function will never be called.

there's something a bit ugly in my final changes to this PR, is that i added the store argument to this function.
in theory, the handler should know what to do.
but i wanted to give syntax error on the WITHSCORES argument on the store variant, and added that store argument, that's where the mess started.

JackieXie168 pushed a commit to JackieXie168/redis that referenced this pull request Mar 2, 2021
Add ZRANGESTORE command, and improve ZSTORE command to deprecated Z[REV]RANGE[BYSCORE|BYLEX].

Syntax for the new ZRANGESTORE command:
ZRANGESTORE [BYSCORE | BYLEX] [REV] [LIMIT offset count]

New syntax for ZRANGE:
ZRANGE [BYSCORE | BYLEX] [REV] [WITHSCORES] [LIMIT offset count]

Old syntax for ZRANGE:
ZRANGE [WITHSCORES]

Other ZRANGE commands remain unchanged.

The implementation uses common code for all of these, by utilizing a consumer interface that in one
command response to the client, and in the other command stores a zset key.

Co-authored-by: Oran Agra <oran@redislabs.com>
oranagra added a commit that referenced this pull request Feb 24, 2022
…10337)

Avoid deferred array reply on genericZrangebyrankCommand() when consumer type is client.
I.e. any ZRANGE / ZREVRNGE (when tank is used).
This was a performance regression introduced in #7844 (v 6.2) mainly affecting pipelined workloads.

Co-authored-by: Oran Agra <oran@redislabs.com>
oranagra added a commit that referenced this pull request Apr 27, 2022
…10337)

Avoid deferred array reply on genericZrangebyrankCommand() when consumer type is client.
I.e. any ZRANGE / ZREVRNGE (when tank is used).
This was a performance regression introduced in #7844 (v 6.2) mainly affecting pipelined workloads.

Co-authored-by: Oran Agra <oran@redislabs.com>
(cherry picked from commit 1dc89e2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approval-needed Waiting for core team approval to be merged release-notes indication that this issue needs to be mentioned in the release notes state:major-decision Requires core team consensus state:needs-doc-pr requires a PR to redis-doc repository state:to-be-merged The PR should be merged soon, even if not yet ready, this is used so that it won't be forgotten

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request, zrevrangebyscore with STORE option

6 participants