The problem/use-case that the feature addresses
You use a sorted set a priority queue. You fetch some elements with ZRANGEBYSCORE and loop over the pairs of (score, member). You queue some work for the member in the pair. And you want to delete the member with the score. Currently only zrem is available.
fetch = ZRANGEBYSCORE myset -inf now WITHSCORES
while (score, member) in fetch
service.queueWorkFor(member)
ZREM myset member
The problem with this is, my queued work can update myset faster than my call for zrem myset member. So the member could be deleted after it was updated by the work (e.g. re-scheduling the work for a future time by the work itself).
Description of the feature
I suggest adding a command named ZREMWITHSCORE that only deletes a member if the score of the member matches that of provided:
fetch = ZRANGEBYSCORE myset -inf now WITHSCORES
while (score, member) in fetch
service.queueWorkFor(member)
// only deletes if the member has the score:
ZREMWITHSCORE member score
If my work for the member updated the score faster than the call for zremwithscore member score, the latter call will be no-op, which is great.
Alternatives you've considered I have to resort to a less elegant remove-before-service-call approach:
fetch = ZRANGEBYSCORE myset -inf now WITHSCORES
while (score, member) in fetch
ZREM myset member
try
service.queueWorkFor(member)
catch Exception
// couldn't queue the work, back in the set to try again later
ZADD myset score member
Comment From: itamarhaber
Hello @bbyk
I must be missing the obvious, but have you considered using the existing ZREMBYSCORE command?
Comment From: bbyk
Hello @bbyk
I must be missing the obvious, but have you considered using the existing
ZREMBYSCOREcommand?
Under one score you can have multiple items e.g.
127.0.0.1:6379> zadd myzset 1 foo
(integer) 1
127.0.0.1:6379> zadd myzset 1 bar
(integer) 1
127.0.0.1:6379> zrangebyscore myzset 1 1
1) "bar"
2) "foo"
127.0.0.1:6379> zremrangebyscore myzset 1 1
(integer) 2
127.0.0.1:6379> zrangebyscore myzset 1 1
(empty list or set)
but what if I meant to delete foo but not bar?