[ 
https://issues.apache.org/jira/browse/AMQ-2552?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Dejan Bosanac updated AMQ-2552:
-------------------------------

    Fix Version/s:     (was: 5.4.2)
                   5.5.0

> Automatic message expiration may not occur on a queue with no (or slow) 
> consumers.
> ----------------------------------------------------------------------------------
>
>                 Key: AMQ-2552
>                 URL: https://issues.apache.org/jira/browse/AMQ-2552
>             Project: ActiveMQ
>          Issue Type: Bug
>          Components: Broker
>    Affects Versions: 5.3.1
>         Environment: ActiveMQ 5.3.1 Snapshot r893661
>            Reporter: Stirling Chow
>             Fix For: 5.5.0
>
>         Attachments: AMQTest.java
>
>
> Symptom
> ========
> If a queue is loaded with 400+ messages that never expire, and then a message 
> that does expire is added to the end of the queue, the added message will not 
> be processed by the Broker's expiration logic until some of the 400+ 
> unexpired messages are consumed.  A unit test is provided to demonstrate this 
> issue.
> These test cases worked for AMQ 5.3, but not for AMQ 5.3.1-SNAPSHOT r893661.
> Motivation
> ========
> Our application uses message expiration to trigger actions when messages are 
> left in a queue for too long a period.  In many cases, there are no consumers 
> on the queue containing the messages that might expire.  Prior versions of 
> AMQ only expired messages when an attempt was made to dispatch them to a 
> consumer, but AMQ-1112 introduced the notion of periodic, automatic 
> expiration of pending messages (see the expireMessagesPeriod policy).  With 
> this periodic expiration, our expectation is that expired messages will be 
> detected and processed in a timely fashion, regardless of the presence of 
> consumers on the queue.
> Cause
> ======
> AMQ-2481 removed forced paging from the periodically-called expireMessages() 
> method:
> >>
>         doBrowse(true, browsedMessages, this.getMaxExpirePageSize());
> <<
>         doBrowse(browsedMessages, this.getMaxExpirePageSize());
> The purpose of the change was to limit the number of messages that would be 
> paged into memory from the message store.  The side effect is that only the 
> first 400 messages in the queue are ever inspected by expireMessages().  If 
> these 400 messages do not contain the messages that are expiring and there 
> are no active consumers to move the expiring messages forward, then 
> expiration will never occur.  With AMQ 5.3, successive calls to 
> expireMessages() would eventually pull all messages into the page so they 
> could be checked for expiration.
> It should also be noted that the test cases can be modified so there is a 
> consumer (with a selector that doesn't choose any of the messages), and they 
> still fail showing that the issue is not purely the result of having *no* 
> consumers.
> Resolution
> =========
> I don't think the browse idiom works very well for the automated expiration 
> task.  It was my initial assumption (and expectation) that the 
> expireMessagesPeriod task would process *all* expired messages in the queue 
> *each time* the task fired.  A related issue to limiting the number of 
> messages that are examined during each expiration task is that expiring 
> messages at the end of the queue will not be handled in a timely fashion 
> since they must wait for multiple firings of the expiration task (this is on 
> 5.3 code; 5.3.1 code will never get to those messages).
> If the desire/need is to scan all messages to determine which have expired, 
> the existing paging strategy is limited because it would require all messages 
> to be brought from store into memory, thus defeating the whole point of 
> paging.  An alternative might be to have a sliding page window that would 
> allow batches of messages to be brought in while clearing out the previous 
> batch.
> Another solution might be to have the expiration task page in directly from 
> the store, but this is problematic since non-persistent messages would still 
> have to come in from the pending message cursor.  In addition, a complete 
> scan of the store might be non-performant for large queues.
> I think the most satisfactory solution for minimizing unnecessary processing 
> and providing timely expiration of messages is to implement a proper heap 
> that indexes messages with expiration values and allows immediate access to 
> *only* the messages that have expired.  The references to these expired 
> messages could then be used to remove the messages directly from the cursors 
> and the store rather than having to iterate over these structures.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to