Skip to content

Add DELIFEQ command #1975

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

Merged
merged 1 commit into from
May 22, 2025
Merged

Add DELIFEQ command #1975

merged 1 commit into from
May 22, 2025

Conversation

LinusU
Copy link
Contributor

@LinusU LinusU commented Apr 18, 2025

Please also pick #2120.

This feature introduces a new command: DELIFEQ key value.

The command deletes the given key only if its current value is equal to the provided value. It returns:

  • 1 if the key was removed (i.e., it existed and matched the value),
  • 0 otherwise (key did not exist, or the value did not match).

This command complements SET key value IFEQ match-value, added in #1324.

The problem/use-case that the feature addresses

A very common operation when synchronizing distributed locks is to remove a key, but only if the value matches a specific string. This pattern is frequently used in distributed locking algorithms like Redlock. The conditional delete prevents a client from inadvertently releasing a lock it doesn’t own—e.g., when a timeout or retry causes overlapping or stale attempts.

Today, this logic is typically implemented using a small Lua script like:

if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

However, using scripts adds a layer of complexity and overhead. Having this logic as a built-in Redis command improves simplicity, reliability, and performance. It also complements SET key IFEQ value very nicely.

Example:

SET foo test
DELIFEQ foo test   # returns 1, key is deleted

SET foo nope
DELIFEQ foo test   # returns 0, key remains

@xbasel
Copy link
Member

xbasel commented Apr 21, 2025

IMO consider adding a more generic command eg. DELIF key EQ value. This allows future extensions like NE, TYPE (eg. del if hash), etc.

Also worth considering a more general CMPSET command for compare-and-delete and compare-and-set.

@sarthakaggarwal97
Copy link
Contributor

I don't have a better alternative but I agree having DEL IFEQ where IFEQ is a subcommand would be confusing. Agree @xbasel's suggestion tho, if we are introducing a new command we should make it as generic as possible.

@zuiderkwast
Copy link
Contributor

I think DELIFEQ is a good idea, especially with the motivation that it's useful in the locking algorithm.

I agree we can't use DEL IFEQ. It's would be a breaking change. It already means Delete the key named "IFEQ", so we can't do that.

@xbasel I also thought about DELIF key EQ value that can be extended with GT, LT, NE in the future if we ever need that. I don't know if there is a use case for those extra conditions though. Maybe not? Maybe DELIFEQ is enough forever?

Copy link

codecov bot commented Apr 24, 2025

Codecov Report

Attention: Patch coverage is 84.61538% with 2 lines in your changes missing coverage. Please review.

Project coverage is 71.24%. Comparing base (1531b44) to head (d1c0433).
Report is 3 commits behind head on unstable.

Files with missing lines Patch % Lines
src/t_string.c 84.61% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           unstable    #1975      +/-   ##
============================================
- Coverage     71.24%   71.24%   -0.01%     
============================================
  Files           122      122              
  Lines         66030    66043      +13     
============================================
+ Hits          47045    47050       +5     
- Misses        18985    18993       +8     
Files with missing lines Coverage Δ
src/commands.def 100.00% <ø> (ø)
src/server.h 100.00% <ø> (ø)
src/t_string.c 96.46% <84.61%> (-0.30%) ⬇️

... and 10 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@zuiderkwast zuiderkwast moved this to Idea in Roadmap Apr 24, 2025
@zuiderkwast zuiderkwast added the major-decision-pending Major decision pending by TSC team label Apr 28, 2025
@LinusU
Copy link
Contributor Author

LinusU commented Apr 28, 2025

Thanks everyone for taking the time to look at this! 🙏

I'm very open to making changes. Do you want me to update the code to DELIF key EQ val directly here? Or should we first reach consensus if we want that structure or not?

I would love some help with the test failures as well. The codecoverage feels wrong, since the reported untested line is the only line that returns 1, and I have a test that asserts that the answer is 1.

The other test failure, "External Server Tests", I'm a bit unsure of. Would love some pointers on where to start!

@xbasel
Copy link
Member

xbasel commented Apr 28, 2025

I don't know if there is a use case for those extra conditions though. Maybe not? Maybe DELIFEQ is enough forever?

@zuiderkwast
Probably most real-world cases (like locks) only need IFEQ, so DELIFEQ would work fine today.
But making it generic (DELIF key OP value) costs almost nothing now and avoids future regrets, for example, deleting expired sessions (eg last_access_time < now) might benefit from LT and atomicity...

Copy link
Contributor

@zuiderkwast zuiderkwast left a comment

Choose a reason for hiding this comment

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

Don't change to DELIF yet. I guess DELIFEQ is more likely to be chosen. We will need to take a core team decision about the command and syntax. Until that's done, there is no hurry to update the details of the PR.

@zuiderkwast zuiderkwast moved this from Idea to Implementation in Roadmap May 5, 2025
@madolson
Copy link
Member

madolson commented May 5, 2025

@PingXie @enjoy-binbin @soloestoy We discussed it in the core meeting with the other 3 TSC folks. We were all aligned, will one of you 👍 so we mark this as an approved decision.

@soloestoy
Copy link
Member

I'm OK with adding a new command, the current command's name is not the best, but I cannot come up with a better name 😅 .

@zuiderkwast zuiderkwast added release-notes This issue should get a line item in the release notes major-decision-approved Major decision approved by TSC team needs-doc-pr This change needs to update a documentation page. Remove label once doc PR is open. client-changes-needed Client changes may be required for this feature and removed major-decision-pending Major decision pending by TSC team labels May 6, 2025
@zuiderkwast zuiderkwast removed this from Roadmap May 7, 2025
@zuiderkwast zuiderkwast moved this to In Progress in Valkey 9.0 May 7, 2025
@zuiderkwast
Copy link
Contributor

@LinusU Will you address the comments so we can finish this up and get it merged?

@LinusU
Copy link
Contributor Author

LinusU commented May 20, 2025

@zuiderkwast thanks for all the pointers! 🙏

I've:

  • rebased on latest unstable
  • fixed lastkey value
  • changed since to 9.0.0
  • added WRONGTYPE error (with test case)
  • fixed swapped description in reply schema

Please let me know if there is anything else you want me to do!

@LinusU LinusU force-pushed the lu-delifeq branch 2 times, most recently from d4e0be8 to 76b2fd4 Compare May 20, 2025 16:54
Copy link
Contributor

@zuiderkwast zuiderkwast left a comment

Choose a reason for hiding this comment

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

LGTM

@LinusU
Copy link
Contributor Author

LinusU commented May 20, 2025

✅ Removed KEYSPACE


test failure looks unrelated?

!!! WARNING The following tests failed:

*** [err]: UNLINK can reclaim memory in background in tests/unit/lazyfree.tcl
Expected 17944320 > 18783952+1000000 (context: type eval line 11 cmd {assert {$peak_mem > $orig_mem+1000000}} proc ::test)
Cleanup: may take some time... OK

@zuiderkwast
Copy link
Contributor

Yeah the CI error is unrelated. Don't worry about it.

@zuiderkwast
Copy link
Contributor

Apparently you need to make and commit commands.def again after modifying the json file.

Signed-off-by: Linus Unnebäck <linus@folkdatorn.se>
@LinusU
Copy link
Contributor Author

LinusU commented May 22, 2025

Apparently you need to make and commit commands.def again after modifying the json file.

Sorry, must have missed that the last time 🙈

I've rebased on latest unstable again, and fixed the outdated commands.def file ✅

@zuiderkwast zuiderkwast changed the title [NEW] Add DELIFEQ command Add DELIFEQ command May 22, 2025
@zuiderkwast zuiderkwast merged commit 0012ca7 into valkey-io:unstable May 22, 2025
52 checks passed
@github-project-automation github-project-automation bot moved this from In Progress to Done in Valkey 9.0 May 22, 2025
@zuiderkwast
Copy link
Contributor

Thanks Linus, can you make a doc PR too? https://github.com/valkey-io/valkey-doc

The README file should provide most of what you need to know. If not, just reach out.

enjoy-binbin added a commit to enjoy-binbin/valkey that referenced this pull request May 22, 2025
DELIFEQ was added in valkey-io#1975 but had some issues.

Do some refactoring to reduce the number of lines of code,
write commands need to increment dirty and we can propagate
it as DEL command.

Signed-off-by: Binbin <binloveplay1314@qq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
client-changes-needed Client changes may be required for this feature major-decision-approved Major decision approved by TSC team needs-doc-pr This change needs to update a documentation page. Remove label once doc PR is open. release-notes This issue should get a line item in the release notes
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

6 participants