Skip to content
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

Add NX/XX/GT/LT options to EXPIRE command group #2795

Merged
merged 8 commits into from
Aug 2, 2021

Conversation

sunng87
Copy link
Contributor

@sunng87 sunng87 commented Oct 3, 2015

Add NX, XX, GT, and LT flags to EXPIRE, PEXPIRE, EXPIREAT, PEXAPIREAT.

  • NX - only modify the TTL if no TTL is currently set
  • XX - only modify the TTL if there is a TTL currently set
  • GT - only increase the TTL (considering non-volatile keys as infinite expire time)
  • LT - only decrease the TTL (considering non-volatile keys as infinite expire time)
    return value of the command is 0 when the operation was skipped due to one of these flags.

Just some quick work to add an NX option to expire commands. This allows expiration to be set for only once, just like setnx. In our application, we have some zsets and hashes that update frequently, but expire at a fixed time defined at its creation.

Searched issue history, I also found some others who had similar requirements: #1840

This is just the first commit. If you think it's OK I will add docs and tests for this feature. Thanks!

EDIT: spelling

@ptaoussanis
Copy link

+1, this would be handy

@yoav-steinberg
Copy link
Contributor

@sunng87 like this. Can you rebase and add a test.
@oranagra @itamarhaber WDYT?

@yoav-steinberg yoav-steinberg added the state:needs-test-code the PR is missing test code label Jul 15, 2021
@itamarhaber
Copy link
Member

Definitely useful for saving a 7-liner scriprt - I'm for it.

My only beef is the naming - NX means "if not exists" elsewhere in Redis, whereas here we're talking about "if no TTL/expiry". So, mebbe NE or NT?

@oranagra
Copy link
Member

I agree this would be nice to have.
In addition to the NX feature, maybe it would also be useful to gave GT and LT (grater than / less than) feature.
My other concern is that as soon as e add these argument flags, it would mean that we can't change the command to be variadic in the future (taking multiple key names).
Also, looking at the linked issue, there was a request to return the TTL rather than 0 / 1.
@redis/core-team please share your thoughts.

@sunng87
Copy link
Contributor Author

sunng87 commented Jul 18, 2021

Can you rebase and add a test.

No problem. Let me catch up

@sunng87
Copy link
Contributor Author

sunng87 commented Jul 18, 2021

My only beef is the naming - NX means "if not exists" elsewhere in Redis, whereas here we're talking about "if no TTL/expiry". So, mebbe NE or NT?

NX here means if a TTL not exists. I just followed previous attempts of this feature for naming. And I'm pretty open for other suggestions.

In addition to the NX feature, maybe it would also be useful to gave GT and LT (grater than / less than) feature.

For now I don't have a use case for GT and LT but the code base is open for adding more flags here. I just realized LT is to fix same issue with my NX.

My other concern is that as soon as e add these argument flags, it would mean that we can't change the command to be variadic in the future (taking multiple key names). Also, looking at the linked issue, there was a request to return the TTL rather than 0 / 1.

These two tasks can be done via pipeline as a workaround (pipelining multiple expire and ttl command). So for now I think it's not very urgent.

Signed-off-by: Ning Sun <[email protected]>
@oranagra
Copy link
Member

@sunng87 you mean that LT would fix your problem the same way that NX does, but there are probably use cases that will benefit from one and not from the other.
In fact, now that i think of it, there are probably also use cases for XX (modify only if already volatile).

@sunng87
Copy link
Contributor Author

sunng87 commented Jul 18, 2021

I agree and there are always possibilities. But before we have real scenario I would suggest to keep the code simple and open for new options.

@yossigo
Copy link
Member

yossigo commented Jul 18, 2021

@oranagra I think that having smarter EXPIRE is more useful than having it variadic, which I believe has very little value over pipelining.

@sunng87
Copy link
Contributor Author

sunng87 commented Jul 19, 2021

The patch is ready for review.

@oranagra
Copy link
Member

I think we wanna take this opportunity to add all the other useful options.
and we still need to conclude if we can / want to change the response type when any of these options are used (as requested in the linked issue).
maybe that's valid to do similarly as how SPOP changes return value when COUNT is added, or maybe we can add a GETTTL argument.
let's wait for further feedback..

@yoav-steinberg
Copy link
Contributor

LT/GT/XX sound good to me.
Regarding return value, if I'm correct 0 can still be a valid value telling us the key expired or never existed while anything larger than 0 will give us the current TTL (this will need to be adjusted to unixtime for AT variants and millisecs for P variants). This seems like a relatively small compatibility break, so I'm for it.

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.

thank you for the efforts.
i added a few comments. some are suggestion for improvements, others are open for discussion, let me know what you think.

src/expire.c Outdated
if (flag & FLAG_NX) {
current_expire = getExpire(c->db, key);
if (current_expire != -1) {
addReply(c,shared.czero);
Copy link
Member

Choose a reason for hiding this comment

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

the docs say that 0 is returned when the key doesn't exist.
i suppose it makes sense to at least let the caller distinguish between non-existing key and a skipped operation due to flag.
one option could have been to return -1 in these cases, but considering that this is inconsistent with the -1 and -2 values returned by the TTL command, maybe that's not a wise idea.

maybe like the linked issue asks for, we better add a way to just return the TTL.
it's true that the user can pipeline a TTL command right after this one, but i suppose it'll be more convenient to let them use this in one go.

I suggest to add a GET flag, which will change the return value from 0/1 to the same return value TTL command group has (see ttlGenericCommand). i.e. it would be relative/absolute and ms/sec depending on the EXPIRE variant that was used, and we'll have to also return -2 and -1 in the appropriate places.

p.s. another wild idea is to also support an INCR flag (for the non-absolute expire variants, when basetime is not 0), in which case we increment the existing expiration time (similarly to the ZADD feature).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I still suggest not to use the return value of EXPIRE commands for TTL. It introduces additional complexity for various clients to distinguish return code and value for this write operation, that defined by an optional flag.

And also I think returning 0 makes sense for this new scenario. We can extend its meaning along with these new features. The 0 means nothing changed with this write operation, it can be a key not exist or the operation is skipped.

Copy link
Member

Choose a reason for hiding this comment

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

ok. we can stop here. already a big step forward.
GET and INCR arguments can be added later if we wish (nothing here that prevents that)

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.

LGTM.. few minor suggestions for improvement.

@sunng87
Copy link
Contributor Author

sunng87 commented Jul 25, 2021

@oranagra All issues resolved. Thanks for your patient and great suggestions.

@oranagra
Copy link
Member

@sunng87 thanks..
can you also make a PR for https://github.com/redis/redis-doc/pulls ?

@oranagra oranagra linked an issue Jul 26, 2021 that may be closed by this pull request
@oranagra
Copy link
Member

@sunng87 please merge my indentation fixes suggestions (it seems this PR doesn't let me edit the code)
@redis/core-team please approve the new flags for the EXPIRE group commands.

@oranagra oranagra changed the title (feat) added nx option to expire commands Add NX/XX/GT/LT options to EXPIRE command group Jul 26, 2021
@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 labels Jul 26, 2021
yossigo
yossigo previously approved these changes Jul 26, 2021
Copy link
Member

@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.

LGTM, added a few minor typo/formatting comments.

@sunng87 sunng87 force-pushed the expire-nx branch 2 times, most recently from 4bca6c0 to ff3d321 Compare July 26, 2021 13:00
@sunng87
Copy link
Contributor Author

sunng87 commented Jul 26, 2021

Doc changes created at redis/redis-doc#1613

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.

API and code LGTM.

@oranagra oranagra merged commit f74af0e into redis:unstable Aug 2, 2021
JackieXie168 pushed a commit to JackieXie168/redis that referenced this pull request Sep 8, 2021
Add NX, XX, GT, and LT flags to EXPIRE, PEXPIRE, EXPIREAT, PEXAPIREAT.
- NX - only modify the TTL if no TTL is currently set 
- XX - only modify the TTL if there is a TTL currently set 
- GT - only increase the TTL (considering non-volatile keys as infinite expire time)
- LT - only decrease the TTL (considering non-volatile keys as infinite expire time)
return value of the command is 0 when the operation was skipped due to one of these flags.

Signed-off-by: Ning Sun <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Add 'NX' option to 'EXPIRE' command set
8 participants