Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ImmediateAcknowledgeAmqpException keeps the message in the queue #2607

Closed
alexey-anufriev opened this issue Jan 27, 2024 · 10 comments
Closed

Comments

@alexey-anufriev
Copy link
Contributor

alexey-anufriev commented Jan 27, 2024

In what version(s) of Spring AMQP are you seeing this issue?

3.1.1

Describe the bug

When ImmediateAcknowledgeAmqpException is thrown from the code of the listener
it is expected that the message that has just been consumed by the listener
will be automatically acknowledged and removed from the queue.

To Reproduce

Clone https://github.com/alexey-anufriev/spring-amqp-immediate-ack
Run ./mvnw clean test

Expected behavior

Queue is empty

Sample

https://github.com/alexey-anufriev/spring-amqp-immediate-ack

@artembilan
Copy link
Member

Apparently that doesn't work for container.setAcknowledgeMode(AcknowledgeMode.MANUAL);:

boolean ackRequired = !this.acknowledgeMode.isAutoAck() && !this.acknowledgeMode.isManual();

So, instead of throwing that exception from your @RabbitListener, you have to do channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);.
Technically those are exactly the same, but since you are in a manual mode, you cannot rely on auto-ack: just doesn't match according to the logic.

Closed as Works as Designed

@artembilan artembilan closed this as not planned Won't fix, can't repro, duplicate, stale Jan 31, 2024
@alexey-anufriev
Copy link
Contributor Author

This scenario I shared is a simple version of the problem, but what if I want to immediate-ack from the Error Handler? For example, I have a custom Error Handler that has to map business exceptions into AQMP-ones. I have already successfully used AmqpRejectAndDontRequeueException but now want to use ImmediateAcknowledgeAmqpException there as well.

What should I do in this case?

@artembilan
Copy link
Member

The MANUAL ack mode means that you handle errors in your listener method.
The error handler on the listener is not aware of the Channel.

@alexey-anufriev
Copy link
Contributor Author

alexey-anufriev commented Jan 31, 2024

Thank you @artembilan for the explanation!

@alexey-anufriev
Copy link
Contributor Author

@artembilan, one last question: how can I handle errors that happen in the post-processor but still within the listener method?

@artembilan
Copy link
Member

Yeah...
I see your point:

			if (this.afterReceivePostProcessors != null) {
				for (MessagePostProcessor processor : this.afterReceivePostProcessors) {
					message = processor.postProcessMessage(message);
					if (message == null) {
						throw new ImmediateAcknowledgeAmqpException(
								"Message Post Processor returned 'null', discarding message");
					}
				}
			}

This way it does not reach listener method yet.
We probably need to relax the mention logic in the commitIfNecessary() and call this.channel.basicAck(deliveryTag, true); independently of the ack mode...
Or make a soft change to call this ack here instead of deferring to the exception flow control.

Reopening as this sounds like valid request.

Thanks

@alexey-anufriev
Copy link
Contributor Author

@artembilan, thanks again for your help.

@artembilan
Copy link
Member

So, the fix is in.
Now SimpleMessageListenerContainer has a new option enforceImmediateAckForManual you can set to true - and those ImmediateAcknowledgeAmqpException will trigger and ack on the message even if AcknowledgeMode.MANUAL.
Feel free to pull 3.1.2-SNAPSHOT for testing on your side.

Thanks

@alexey-anufriev
Copy link
Contributor Author

@artembilan, thank you for your effort! I will take a look at the snapshot version. I hope this will be included in the next Spring Boot release (we usually bring it all together).

@artembilan
Copy link
Member

Correct. We have it scheduled for February, 19th.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants