XNACK would remove a message from PEL and mark it as not-processed so it goes to the next consumer. A consumer which called XNACK could be possibly selected again for processing this very message in the next cycle, for example:

STREAM              Consumers

Message A ---------> Consumer A
          <- XNACK - Consumer A
Message A ---------> Consumer B
          <- XNACK - Consumer B
Message A ---------> Consumer A

Use-cases are any systems with pre-process checks. For example, background job processing where a worker could deny an incoming job for some purposes, leaving the opportunity of handling it to other workers in the same consumer group.

NACK exits in RabbitMQ.

Comment From: edgurgel

Yeah to me it makes more sense to XNACK pending jobs that were not executed properly than XCLAIM them.

Why?

Because the process that is recovering messages from the stream does not need to decide which other consumer will claim them. The messages would just go back to be processed by some consumer that is actively fetching messages to be consumed.

Comment From: guybe7

note: this feature might be a bit problematic because XREADGROUP relies on the fact the each entry that was read is either in some PEL or has been processed and ACKed (i.e. the group struct keep a last_id member which is the last_id read. it only start reading new messages starting from this one) if we want to implement this feature we would need to keep a rax of all NACKed messaged and have a XREADGROUP get a NACKED modifier so it would read only from the NACKed rax

Comment From: guybe7

maybe a better option would be to add a "reject" field to the NACK struct and have XREJECT command plus REJECTED modifier to XREADGROUP that will scan the entire group PEL and "read" only rejected entries (should be capped by COUNT)

this approach aligns with the XREADGROUP IDLE approach from https://github.com/redis/redis/issues/7649

Comment From: guybe7

@vladfaust @edgurgel i have a workaround for this issue: 1. every time you read a message and want to reject it, use XCLAIM in order to transfer it to some nacked_messages_consumer 2. every once in a while use XPENDING on nacked_messages_consumer and XCLAIM those messages to a "real" consumer

so far we can't find a proper way to handle this issue (much like #7649) so i though this workaround could provide some relief in the meanwhile

Comment From: be-hase

+1 I want XNACK command.

Comment From: qsqnk

+1 that would be very convenient

Comment From: prakharbirla-ng

+1