muleesbmulesoftmule4anypoint-mq

Mule 4 with Anypoint MQ -Delivery attempts before reroute Vs maxRedeliveryCount in redelivery-policy


This queston is related to the one asked earlier here

Using Anypoint MQ with Mule Runtime 4.4

Have a subscriber which will consume messages from a normal queue .

This queue has a DLQ configured . The queue has this Delivery attempts before reroute = 5

Max Redelivery count = 2

Acknowledgement mode = Auto

Here is the code :

    <flow name="test-DLQ-flow" >
    <anypoint-mq:subscriber doc:name="Employee Updates Topic Listener" config-ref="Anypoint_MQ_Config" destination="${aemployee-queue}">
        <redelivery-policy maxRedeliveryCount="2" />
        <anypoint-mq:subscriber-type >
            <anypoint-mq:prefetch maxLocalMessages="1" />
        </anypoint-mq:subscriber-type>
    </anypoint-mq:subscriber>

    <set-variable value="#[1/0]" doc:name="Creating an error "  variableName="xyz"/>

    <error-handler >
        <on-error-propagate enableNotifications="true" logException="true" doc:name="On Error Propogate" type="MULE:REDELIVERY_EXHAUSTED">
            <logger level="INFO" doc:name="Logger" />
        </on-error-propagate>
    </error-handler>
</flow>

<anypoint-mq:config name="AP_MQ_Config" doc:name="AP MQ Config"  >
    <anypoint-mq:connection 
        url="some_url" 
        clientId="abcd" 
        clientSecret="xyz" />
</anypoint-mq:config>

Am purposefully generating an error at the first instance by dividing with 0 and can see that redelivery is attempted twice and then it throws a MULE:REDELIVERY_EXHAUSTED exception , which is caught in exception handler and logged .

As per answer to the linked question am using on-error-propogate So the exception is again thrown . Now my expectation was that since max number of retries is exceeded maxRedeliveryCount defined in redelivery-policy should cause the message to be moved to DLQ

However what I can see is that the message keeps throwing REDELIVERY_EXHAUSTED till attributes.deliveryCount reaches the value of 5 ( which was configured in Anypoint MQ while setting up the queue )

So the message arrives on the queue normally ( 1 time ) and is retried ( 2 times ) ( attributes.deliveryCount = 3 ) and then we get the MULE:REDELIVERY_EXHAUSTED 2 times ( attributes.deliveryCount = 5 now ) Now the message goes to DLQ

Questions : So does this mean that when we have Delivery attempts before reroute ( 5 ) and maxRedeliveryCount in redelivery-policy ( 2 ) configured , then it is Delivery attempts before reroute which is getting enforced ( if the error is rethrown )

so for maxRedeliveryCount in redelivery-policy to take precedence over Delivery attempts before reroute , looks like I need to change on-error-propagate. to on-error-continue and since am no longer throwing an error and using Ack = Auto , will need to manually publish to DLQ Does that look like a correct approach ?


Solution

  • You are mixing two different functionalities. The re-delivery policy at the flow source level is independent from Anypoint MQ Queue (or any other kind of source for that matter). It is used to basically "reject" same messages after it has reached your mule app if the same message has previously failed multiple times. This will work even with non-queue sources, for example HTTP requests (in fact it makes sense to you with non-queue sources only IMO). Therefore, it is not related to any DLQ and any logic to send a message to DLQ needs to be handled using proper error handling (i.e. on-error-continue or on-error-propogate) and then the message also needs to be deleted from the main queue (a.k.a ACK in Anypoint MQ)

    On the other hand, the Max Delivery Count / Delivery attempts before reroute at the Anypoint MQ level is the OOTB functionality that enables you to automatically send the message to an assigned DLQ if the same message is sent to a consumer n number of times.

    Ideally you should not be configuring a redelivery policy for Queue based sources like MQ and use their OOTB functionality to send the message to DLQ after certain number of delivery attempts. So, you would want to remove the redelivery-policy from your code for MQ subscribers and only use the Delivery attempts before reroute that is configured at Queue level

    What is happening in your case is that you are not explicitly sending the message to the DLQ from your erorr handling of REDELIVERY_EXHAUSTED error in your mule code. And therefore after the configured maxRedeliveryCount, which is 2 in your case, the mule source still consumes the message 3 more times until the Delivery attempts before reroute is exhausted and the message is sent to DLQ by Anypoint MQ (not via redelivery policy).