scenario: client A is blocking on a stream with XREADGROUP:
127.0.0.1:6379> XADD x * f v
"1581590417017-0"
127.0.0.1:6379> XGROUP create x grp $
OK
127.0.0.1:6379> XREADGROUP group grp con block 0 streams x >
after client A is blocked, client B deletes the stream:
127.0.0.1:6379> DEL x
(integer) 1
127.0.0.1:6379>
i would expect that in that very moment client A will be unblocked with NOGROUP the consumer group this client was blocked on no longer exists (because that DEL deleted the stream along with all the groups it had) but it remains blocked. the only way to unblock it is to revive the stream:
client B:
127.0.0.1:6379> XADD x * f v
"1581590682436-0"
127.0.0.1:6379>
client A:
127.0.0.1:6379> XREADGROUP group grp con block 0 streams x >
(error) NOGROUP the consumer group this client was blocked on no longer exists
(219.57s)
127.0.0.1:6379>
i'm not sure if this is by design (maybe we don't want to signalKeyAsReady when a stream is deleted? a bit counter-intuitive) or a bug (current behavior does seem a bit weird)
Comment From: guybe7
@antirez any input on this one?
Comment From: Morgul
Another weird practicality thing here, is that it's not possible to know which message kicked you out of your blocking state, so you have no idea what message should actually be where you start if you recreate your consumer group... leading to a missed message. If the error contained the id of the message that unblocked us, we could use that to correctly restart without losing messages. As it is, I don't see any way to do avoid that without potentially reprocessing messages.
Comment From: enjoy-binbin
I think this is a bug...
i see when we delete a group (XGROUP destroy), we will call signalKeyAsReady.
so maybe we can call signalKeyAsReady too when we delete a stream.
but another problem is that in handleClientsBlockedOnKeys, we will call lookupKeyReadWithFlags,
and we are not able lookup the key since we DEL the key in DELCOMMAND.
Comment From: guybe7
i suppose that in this case we should unblock the client with "-UNBLOCKED key was deleted"
Comment From: enjoy-binbin
there are also some weird cases like (doesn't matter):
client1: brpop key 0
client2: set key value ... etc
i suppose stream can have groups, make it different. it feel like we will need to touch a lot of codes to "fix" it
Comment From: guybe7
I've started working on this issue and I'm having second thoughts...
let's assume call signalModifiedKey whenever we delete a stream. imagine this scenario:
stream does not exist
c1:
XREAD block 0 streams x $
c2:
MULTI
XADD x * f v
DEL x
EXEC
in this case, c1 will be unblocked with -UNBLOCKED key was deleted but if we apply the same scenario while using a list or a set, the client will remain blocked (seems to be by design, see test "$pop, LPUSH + DEL should not awake blocked client")
it makes me think that maybe we should consider this issue as a known limitation, for which there's a workaround: in the top comment, if client B didn't use:
127.0.0.1:6379> XADD x * f v
"1581590682436-0"
but rather:
127.0.0.1:6379> XGROUP create x grp $ MKSTREAM
OK
127.0.0.1:6379> XADD x * f v
"1581590682436-0"
then client A would have been unblocked as expected:
127.0.0.1:6379> XREADGROUP group grp con block 0 streams x >
1) 1) "x"
2) 1) 1) "1581590682436-0"
2) 1) "f"
2) "v"
Comment From: guybe7
@itamarhaber @yossigo thoughts?
Comment From: itamarhaber
IMO a DEL should unblock any XREADGROUPs, per the top comment, and I can't imagine someone trying to "unblock" a consumer by recreating the stream. Conversely, I don't think XREADs should be unblocked due to DELs.
Comment From: guybe7
@itamarhaber implemented your approach in #10306, please review