DeliveryCount & ACKs
clebert.suconic Feb 17, 2009 2:54 PMI have been working with https://jira.jboss.org/jira/browse/JBMESSAGING-1294, and this is the current scenario:
- The MessageReference.deliveryCount is only updated after ACKs.
Say, if you:
- received a message
- called message.acknowledge
- called rollback
When you receive that same message again, the deliveryCounter will be incremented, as the ACK will have it incremented:
Class: ServerConsumerImpl { ... Method acknowledge(final boolean autoCommitAcks, final Transaction tx, final long messageID) { ... if (autoCommitAcks) { ref.getQueue().acknowledge(ref); } else { ref.getQueue().acknowledge(tx, ref); // Del count is not actually updated in storage unless it's // cancelled ref.incrementDeliveryCount(); } }
If you are using AUTO_ACK (In JMS Terms that means non-transacted), that means you won't ever need to increment the DeliveryCount, as the message will be committed as soon as you called ack.
However if you are using MessageListener, that's not true. If you receive a message and an exception was thrown, the counter should be incremented also. But the ClientConsumer can't call ACK, as that would remove it from the Queue.
So, that means that Acknowledge requires a different semantic when an exception is caught on JMSMessageListenerWrapper.
One way to fix this, would be to change the ACK call signature on ClientSessionInternal:
void acknowledge(long consumerID, long messageID) throws MessagingException; // Maybe I would leave this void acknowledge(long consumerID, long messageID, boolean autoACK) throws MessagingException;
And have the JMSMessageListenerWrapper doing:
catch (RuntimeException e) { if (!transactedOrClientAck) { try { consumer.acknowledge(jbm.getCoreMessage(), false); session.getCoreSession().rollback(); session.setRecoverCalled(true); } catch (Exception e2) { log.error("Failed to recover session", e2); } } }
With that, the AutoACK property would aways be sent on SessionAcknowledgeMessage, leaving the AutoACK to be controlled from the client.
(I could extend the packet if the boolean is considered a problem, & if this solution is acceptable).
The only problem I found on this solution, is requiring a type-cast to ClientConsumerInternal on JBossMessageConsumer.
Any thoughts?