My idea is to allow for BLPOP (and other blocking commands) to gracefully end before it's timeout (which can be infinite) by adding an option to WATCH for keys that should stop it.
This is useful for example (when having an unknown number of consumers): 1. You want to change the list of keys you listen to (let's say a dynamic priority implementation when a new priority has been created). 2. You want to gracefully stop all blocking commands for shutdown of their threads.
This can be implemented by piggybacking on existing WATCH command, with a different behavior for BLPOP when not inside a MULTI command: - If one of the WATCHed keys was modified before BLPOP's timeout (which can be infinite) it will unblock the client and return an empty bulk response (just like timeout).
Then there are 2 behavior options (because someone can do a WATCH, then BLPOP, then MULTI): - clear the client dirty bit after BLPOP exits because of WATCH (and thus BLPOP works like MULTI/EXEC), but this will effect if you MULTI afterwards without WATCHing again. - don't clear the client dirty bit, and make the client explicitly UNWATCH and WATCH again after each BLPOP with WATCH semantics. (but in MULTI case it will behave the same).
This should be a very simple implementation (unlike adding a new WATCHBLPOP and other commands and data structures).
Comment From: yossigo
@tzickel Blocked clients can already be released using CLIENT UNBLOCK. If I understand correctly, what you're suggesting is basically to enhance this capability to unblock clients based on other criteria rather than explicitly specifying their IDs. Is that correct? I think the use of WATCH for additional purposes may be confusing and error prone.
Comment From: tzickel
I'm not sure CLIENT UNBLOCK (which did not exist back in march 2018) will be useful for all scenarios.
It's not atomic (i.e. what if between looking at the client list, and unblocking all of the relevant clients, another one joins in?), and it's polling instead of pushing (the WATCH mechanism will automatically invalidate all the blocked clients just when needed).
But maybe today I think there might be sufficient new commands (like BZPOPMIN) to implement dynamic priority queues.
As for WATCH being confusing for this, it all depends on what solution clients need (a BLOCKINGWATCH command can be used instead if it's less confusing).
Back in 2018 I needed a priority system and because of this limitation (and not wanting a blocking with timeout + polling solution), I went with a static priority scheme instead of a dynamic one.