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 ZREMBYSCORE command?

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?