nsqio / go-nsq

The official Go package for NSQ
MIT License
2.59k stars 444 forks source link

consumer: LogFailedMessage behavior #302

Closed Joevychow closed 4 years ago

Joevychow commented 4 years ago

When HandleMessage handlers a message and returns an error, the message will requeue by default. But when HandleMessage return errrors five times(default MaxAttempts), why requeue again and then triggler LogFailedMessage instead of triggler immediately?

ploxiln commented 4 years ago

When a message is "failed", the way further attempts are prevented is with message.Finish(). The message attempts policy is checked and enforced by the consumers, not by nsqd, and nsqd can't really tell the difference between final failures and final successes.

        if r.shouldFailMessage(message, handler) {
            message.Finish()
            continue
        }

(The optional LogMessageFailed method is called at the same time, from shouldFailMessage().)

As you noticed, this is checked just before calling the actual message handling function, instead of just after. So after the last time the message is actually processed, it is requeued once more, then redelivered once more, and then failed/finished. The reason why it is done this way is: