4 Replies Latest reply on Nov 9, 2005 10:02 AM by Tim Fox

    Channel.getFist()

    Ovidiu Feodorov Master

      I noticed that MessageCallbackHandler has been rewritten so now when a client receive()s, the client thread is used to invoke getMessage() on the server. While executing getMessage(), the server consumer delegate actively pulls a message from the channel using getFirst().

      The whole idea so far was to have the server consumer delegate (or any reciever, for that matter) register with the channel and notify the channel that is ready to process messages. If there is a message, the channel will push it to the server consumer delegate, which will asynchronously send it to the client. Otherwise the consumer will stay in a "ready" state until a message arrives to the channel and the channel forwards it to it.

      The channel must always push the message to the consumer, a Channel.getFist() method IS NOT OK. A channel that hands over a message MUST receive a Delivery instance back. This is required in order to insure message recoverability. At any moment, the channel must have either the message or the delivery, and getFirst() allows a situation in which it has none. Channel.addDelivery() is also unnecessary.

      If things are not done this way and the VM crashes immediately after Channel.getFirst() returns, the message is lost without being ever delivered to the client. The reliability promise goes away.

        • 1. Re: Channel.getFist()
          Tim Fox Master

           

          "ovidiu.feodorov@jboss.com" wrote:
          I noticed that MessageCallbackHandler has been rewritten so now when a client receive()s, the client thread is used to invoke getMessage() on the server. While executing getMessage(), the server consumer delegate actively pulls a message from the channel using getFirst().

          The whole idea so far was to have the server consumer delegate (or any reciever, for that matter) register with the channel and notify the channel that is ready to process messages. If there is a message, the channel will push it to the server consumer delegate, which will asynchronously send it to the client. Otherwise the consumer will stay in a "ready" state until a message arrives to the channel and the channel forwards it to it.

          The channel must always push the message to the consumer, a Channel.getFist() method IS NOT OK.


          A way of synchonrously getting a the first message from the channel is necessary for receiveNoWait semantics at the least.
          We discussed this deeply last week.


          A channel that hands over a message MUST receive a Delivery instance back. This is required in order to insure message recoverability. At any moment, the channel must have either the message or the delivery, and getFirst() allows a situation in which it has none. Channel.addDelivery() is also unnecessary.

          If things are not done this way and the VM crashes immediately after Channel.getFirst() returns, the message is lost without being ever delivered to the client. The reliability promise goes away.


          getFirst() and Channel.addDelivery can easily be combined into a message that ensures the channel either has a delivery or a message. Hence the reliability promise is not lost.

          • 2. Re: Channel.getFist()
            Tim Fox Master

             

            "timfox" wrote:

            .... can easily be combined into a *message* that...


            I mean "method" of course :)

            • 3. Re: Channel.getFist()
              Ovidiu Feodorov Master

              void Channel.deliver(Receiver receiver) implementation:

               void deliver(Receiver receiver)
               {
              
               // grab the first message from the state
              
               // and push it to the receiver *on the same thread*
               Delivery d = receiver.handle(message, ....);
              
               // deal with Delivery
               }
              



              public Message ServerConsumerDelegate.receiveNoWait() implementation:

               public Message receiveNoWait()
               {
               try
               {
               reentrantLock.lock();
              
               channel.deliver(this);
              
               if (delivery != null)
               {
               // my message was already synchronously delivered by the channel
               // I created and returned a delivery for this
               // that delivery is stored in the my 'delivery' variable
               // which will be used for acknowledgment
               return delivery.getMessage();
               }
               else
               {
               return null;
               }
               }
               finally
               {
               reentrantLock.release();
               }
               }
              


              There is no need to change the Channel's interface.

              • 4. Re: Channel.getFist()
                Tim Fox Master

                 

                "ovidiu.feodorov@jboss.com" wrote:
                void Channel.deliver(Receiver receiver) implementation:

                 void deliver(Receiver receiver)
                 {
                
                 // grab the first message from the state
                
                 // and push it to the receiver *on the same thread*
                 Delivery d = receiver.handle(message, ....);
                
                 // deal with Delivery
                 }
                



                public Message ServerConsumerDelegate.receiveNoWait() implementation:

                 public Message receiveNoWait()
                 {
                 try
                 {
                 reentrantLock.lock();
                
                 channel.deliver(this);
                
                 if (delivery != null)
                 {
                 // my message was already synchronously delivered by the channel
                 // I created and returned a delivery for this
                 // that delivery is stored in the my 'delivery' variable
                 // which will be used for acknowledgment
                 return delivery.getMessage();
                 }
                 else
                 {
                 return null;
                 }
                 }
                 finally
                 {
                 reentrantLock.release();
                 }
                 }
                


                There is no need to change the Channel's interface.


                True, that would work too.

                It seems we have two alternatives that accomplish the same goal.

                Judging that we've now agreed to shelve the delivery list, I'm happy to go with this.