4 Replies Latest reply on May 21, 2010 8:13 PM by Richard Berman

    Is BlockOnAcknowledge supposed to be honored by ClientConsumerImpl?

    Richard Berman Newbie

      I'm using the trunk and updated this evening.  I'm only using Core features.


      It looks to me like calling setBlockOnAcknowledge(true) on my ClientSessionFactory is not sufficient to block ClientMessage.acknowledge while the ack is processed.  Shouldn't it?


      The Javadoc for the session factory says that the consumers created from the factory will block on acknowledge.  Stepping thru the code in the debugger shows me that ClientMessageImpl immediately delegates to the ClientConsumerImp.  However, that class doesn't appear to know that the session is set to block on ack.  It updates ackBytes and then checkes to see if ackBytes is greater than ackBatchSize.  If not, it just remembers the message in lastAckedMessage.


      I have a couple of work arounds.  One of the simplest is to just close the ClientConsumer after each ack.  That goes against the best practice of reusing the ClientConsumer.  Another idea would be to set the ackBatchSize pretty small.


      I do see the ClientSessionImpl checking blockOnAcknowledge and sending immediately (and waiting) if it got the ack at all.  The buffering in the consumer seems to be the one not honoring the configuration.


      I'm attaching a bit of code that can be used to see the issue.  It's a derivitive of the core embedded server example as that allows for it to be self contained in one class.  My 'real' configuration is multiple processes and multiple config files but the effect is exactly the same.


      I haven't reduced it to a unit test.  To see it fail wth my exmple code, you need to kill the VM after calling acknowlege and before calling consumer.close() since this will flush the acks.  Having killed it as suggested, run it again and don't kill anything. This time two message will be found on the queue (the one from run #1 and a second from run #2).  If it's run a 3rd time (and the second is not killed midstream) there will only be 1 message received and consumed.


      I put a multi-line comment at the point where the code should exit ungracefully.  Look for "kill the JVM at this point".


      Please don't let my blunt method to reproduce this be a distraction.  I'm not proposing that would happen (much) in a production environment.  I was more trying to explore the behavior of block on ack as there are parts of my message flow that I expect to need the blocking behavior.



        • 1. Re: Is BlockOnAcknowledge supposed to be honored by ClientConsumerImpl?
          Tim Fox Master

          The way you are creating the session has an ack-batch-size of 1 MiB (the default).


          If you are batching acks they are not sent to the server until the batch size has been reached.


          If you don't want to batch acks just specify ack-batch-size of zero to get the behaviour you want.

          • 2. Re: Is BlockOnAcknowledge supposed to be honored by ClientConsumerImpl?
            Richard Berman Newbie



            Thanks for the quick response.


            I have a couple of concerns about your suggestion.


            #1) The Javadoc for ClientSessionFactory.setAckBatchSize(int) says "Value must be greater than 0".


            Setting the ack batch size was my first thought (once observing that BlockOnAcknowledge wasn't sufficient) until I saw the prohibition on 0.  Having looked more at the code, I don't see any issue with setting it to 0 and I agree it would give the effect I'm looking for.  Was the Javadoc trying to say it needed to be greater than 0 to get batching?  Or some other qualification on when it needed to be greater than 0?


            #2) The Javadoc for ClientSessionFactory.setBLockOnAcknowledge(boolean) says "Sets whether consmers created thru this factoery will block while sending message acknowledgements...".


            I interpret this to mean that I shouldn't have to do anything more.  I'd suggest the Javadoc wording be made more specific that the blocking aspect is only for the portion of sending an ack that occurs in the session.  The reference to the consumer in the Javadoc comment is a problem as it's not true.


            However, my real preference is that this very clearly & explicitly named option should mean what it says.  ackBatchSize is already being passed from the session to the consumer so the blockOnAck value could be as well.  Or, maybe the ackBatchSize should be set to 0 when passed to the consumer if that's the best way to achieve the blockOnAck behavior.


            Meanwhile, I've set the ackBatchSize to 0 in addition to the blockOnAck and it's working as I need it to.


            Thanks again!

            • 3. Re: Is BlockOnAcknowledge supposed to be honored by ClientConsumerImpl?
              Clebert Suconic Master

              #1 - We will fix the javadoc. (I remember Jeff Mesnil did some change around it.. maybe it was fixed already.. but I will double check anyway)



              #2 - This just means that the message to the server is done asynchronously. i.e. you will have guarantee of delivery of the ACK.

              • 4. Re: Is BlockOnAcknowledge supposed to be honored by ClientConsumerImpl?
                Richard Berman Newbie

                For #2...


                If "this just means that the message to the server is done asynchronously" (or synchronously if set to true), then I think the javadoc comment is misleading. It specifically references "consumers" and says that they "will block while sending message acknowledgements".  (Both quoted phrases are literal quotes from the setBlockOnAcknowledge method comment on the head of the trunk -- checked again moments ago).


                I hate to seem like  a "language lawyer" on this.  It just seems like a significant difference.


                Thanks for the help.