Announcement Announcement Module
Collapse
No announcement yet.
Disordered MessageGroupQueue Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Disordered MessageGroupQueue

    Hi

    Just use a QueueChannel(with in-memory HSQLDB message store support).
    The message in is ok, but I found the message out sequence is incorrect.
    I checked the JdbcMessageStore polling method,
    Code:
    Message<?> message = this.messageGroupStore.pollMessageFromGroup(groupId);
    SELECT MESSAGE_ID, CREATED_DATE from INT_MESSAGE_GROUP where GROUP_KEY=? and REGION=? order by UPDATED_DATE
    I suspect the "order by updated_date" may be unprecise for message polling because of the in-memory HSQLDB database is very fast, which may not guarantee the dequeue sequence.

    please help to check this issue.

    Code:
    <int:channel id="A-05-outbound-channel">
    		<int:queue message-store="messageStore"/>
    </int:channel>
    
    <int-jdbc:message-store id="messageStore"
    		data-source="hsqldb-dataSource" />
    
    <jdbc:embedded-database id="hsqldb-dataSource">
    		<jdbc:script location="classpath:script/schema-hsqldb.sql" />
    </jdbc:embedded-database>



    Regards
    Shawn

  • #2
    I did a small test and here's the reasoning to the behavior you pointed out.
    I sent 10 messages with payload numbered from 0 to 9.

    When the message store is queried for the first time, all's well and the first message retrieved is the one with payload 0.
    I debugged the JDBCMessageStore.pollMessageFromGroup method and on the first iteration, the data in the tables looks like this

    Message Payload: 1, Updated Time: 2012-04-28 16:33:23.014, Created Time: 2012-04-28 16:33:22.969
    Message Payload: 2, Updated Time: 2012-04-28 16:33:23.021, Created Time: 2012-04-28 16:33:22.969
    Message Payload: 3, Updated Time: 2012-04-28 16:33:23.028, Created Time: 2012-04-28 16:33:22.969
    Message Payload: 4, Updated Time: 2012-04-28 16:33:23.037, Created Time: 2012-04-28 16:33:22.969
    Message Payload: 5, Updated Time: 2012-04-28 16:33:23.048, Created Time: 2012-04-28 16:33:22.969
    Message Payload: 6, Updated Time: 2012-04-28 16:33:23.061, Created Time: 2012-04-28 16:33:22.969
    Message Payload: 7, Updated Time: 2012-04-28 16:33:23.073, Created Time: 2012-04-28 16:33:22.969
    Message Payload: 8, Updated Time: 2012-04-28 16:33:23.086, Created Time: 2012-04-28 16:33:22.969
    Message Payload: 9, Updated Time: 2012-04-28 16:33:23.101, Created Time: 2012-04-28 16:33:22.969

    So far looks ok, but, now this message with payload is removed from the group and this gets invoked

    this.removeMessage(messageToRemove.getHeaders().ge tId());
    this.updateMessageGroup(groupKey);
    from JDBCMessageStore.removeMessageFromGroup
    This now updates the UPDATED_DATE of all the records to the same value and the contents of the table on second iteration looks
    like this
    Message Payload: 2, Updated Time: 2012-04-28 16:34:24.711, Created Time: 2012-04-28 16:33:22.969
    Message Payload: 4, Updated Time: 2012-04-28 16:34:24.711, Created Time: 2012-04-28 16:33:22.969
    Message Payload: 1, Updated Time: 2012-04-28 16:34:24.711, Created Time: 2012-04-28 16:33:22.969
    Message Payload: 6, Updated Time: 2012-04-28 16:34:24.711, Created Time: 2012-04-28 16:33:22.969
    Message Payload: 8, Updated Time: 2012-04-28 16:34:24.711, Created Time: 2012-04-28 16:33:22.969
    Message Payload: 9, Updated Time: 2012-04-28 16:34:24.711, Created Time: 2012-04-28 16:33:22.969
    Message Payload: 5, Updated Time: 2012-04-28 16:34:24.711, Created Time: 2012-04-28 16:33:22.969
    Message Payload: 3, Updated Time: 2012-04-28 16:34:24.711, Created Time: 2012-04-28 16:33:22.969
    With the message with payload 7 being read this time in my case.

    i'll suggest you raise a JIRA for this here http://jira.springsource.org/browse/INT as the behavior of the QueueChannel is FIFO, or, at least this should be mentioned in the reference manual.

    To address your problem, if you do care about the ordering, you can have a resequencer downstream.

    Hope that helps..

    Comment


    • #3
      It's the fact that the created times are identical, not the update to the update time, that's causing the problem.

      Amol, I think you were just "lucky" that you got row 0 first.

      It does look like a problem, but I am curious as to whether HSQLDB is just being used in test cases, or for production. If production, what is the purpose? Why can't you use a simple QueueChannel (which stores the messages in memory).

      If it's for test only, you can simply re-declare your queue channel (in test config) with no message-store, as a work around. Presumably you are re-declaring your datasource; you would redeclare the channel in the same way.

      Comment


      • #4
        Amol, I think you were just "lucky" that you got row 0 first.
        I always get the message with payload 0 as the first message. The reason being, when the messages are put in the Message group, their "updated time" is the time it was inserted and hence i get the message with payload 0 with a minimum value for "updated time", however, its only for the first read. Subsequently all messages get the "updated time" as the time last message read was deleted from the group.

        It does look like a problem, but I am curious as to whether HSQLDB is just being used in test cases, or for production.
        Haven't tried any other database, but based on the logic above, this behavior will be seen across any database.

        Comment


        • #5
          Oops; you are correct, sorry - I misread the OP; I just assumed we'd sort on the created date (not updated date) when fetching; that said, it still wouldn't work with a high speed database where the creation dates for a bunch of rows coule be equal.

          Comment


          • #6
            Even if the message inserts separated by significant difference, the create date of the message group will always be the same (which the method getGroupCreatedDate returns). So create times will not work in any case.
            To overcome the problem, i think a resequencer downstream will be ok (provided there are no more QueueChannel backed by a persistent message store downstreams). WDYT?

            Comment


            • #7
              Yes, a resequencer might be a work-around, depending on the polling strategy - for example 'max messages per poll = 1' would not be a good strategy because it will take a number of polls before the messages will be resequenced.

              All I was trying to say was that pollMessageFromGroup executes LIST_MESSAGES_BY_GROUP_KEY.

              If that query was changed to use the created date, it still would not work for the case where we have n rows with the same created timestamp.

              We already have an open JIRA to make improvements in this method https://jira.springsource.org/browse/INT-2200, but it doesn't specifically address this issue.

              Comment


              • #8
                Originally posted by Amol Nayak View Post
                I did a small test and here's the reasoning to the behavior you pointed out.
                I sent 10 messages with payload numbered from 0 to 9.

                When the message store is queried for the first time, all's well and the first message retrieved is the one with payload 0.
                I debugged the JDBCMessageStore.pollMessageFromGroup method and on the first iteration, the data in the tables looks like this




                So far looks ok, but, now this message with payload is removed from the group and this gets invoked



                from JDBCMessageStore.removeMessageFromGroup
                This now updates the UPDATED_DATE of all the records to the same value and the contents of the table on second iteration looks
                like this


                With the message with payload 7 being read this time in my case.

                i'll suggest you raise a JIRA for this here http://jira.springsource.org/browse/INT as the behavior of the QueueChannel is FIFO, or, at least this should be mentioned in the reference manual.

                To address your problem, if you do care about the ordering, you can have a resequencer downstream.

                Hope that helps..


                Thanks, Amol. It's very helpful, this issue confused me all the morming. because it's a queue channel which should support FIFO as we know.

                Originally posted by Gary Russell View Post
                It does look like a problem, but I am curious as to whether HSQLDB is just being used in test cases, or for production. If production, what is the purpose? Why can't you use a simple QueueChannel (which stores the messages in memory).
                I'd like to use messageStore to prevent message lost(transactional poller).

                I think it's better to raise a JIRA to report this issue since FIFO need guaranteed for queue channel even with messageStore support.

                Comment


                • #9
                  I'd like to use messageStore to prevent message lost(transactional poller).
                  Yes, but an in-memory HSQLDB won't help you there. Like I said, if you are only using it for testing it's one thing (and you can use a simple queue channel for unit/integration testing), but an in-memory DB doesn't solve message loss.

                  I think it's better to raise a JIRA...
                  We agree - we're just trying to give you a work-around in the meantime - the fix will likely need a schema change.

                  The resequencer should work for you until the problem is corrected.

                  Comment

                  Working...
                  X