1 2 Previous Next 18 Replies Latest reply on Feb 25, 2009 3:02 AM by Tim Fox

    DeliveryCount & ACKs

    Clebert Suconic Master

      I 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?



        1 2 Previous Next