1

I'm having trouble to identify a way to delay message level in SpringAMQP. I call a Webservice if the service is not available or if it throws some exception I store all the requests into RabbitMQ queue and i keep retry the service call until it executes successfully. If the service keeps throwing an error or its not available the rabbitMQ listener keeps looping.( Meaning Listener retrieves the message and make service call if any error it re-queue the message)

I restricted the looping until X hours using MessagePostProcessor however i wanted to enable delay on message level and every time it tries to access the service. For example 1st try 3000ms delay and second time 6000ms so on until i try x number of time.

It would be great if you provide a few examples.

Could you please provide me some idea on this?

sea
  • 113
  • 8

2 Answers2

1

Well, it isn't possible the way you do that.

Message re-queuing is fully similar to transaction rallback, where the system returns to the state before an exception. So, definitely you can't modify a message to return to the queue.

Probably you have to take a look into Spring Retry project for the same reason and poll message from the queue only once and retries in memory until successful answer or retry policy exhausting. In the end you can just drop message from the queue or move it into DLQ.

See more info in the Reference Manual.

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • Hi Artem, Thanks for the response. I achieved this using MessagePostProcessor and CustomExchange. @Bean CustomExchange delayExchange() { Map args = new HashMap<>(); args.put("x-delayed-type", "direct"); return new CustomExchange("cos-delayed-exchange", "x-delayed-message", true, false, args); } – sea Jul 08 '16 at 02:50
  • Ok. If found it as good one, you can share it here as an answer to your own question. Just ping me here in comment to pay attention to that one – Artem Bilan Jul 08 '16 at 02:54
  • if (message.getMessageProperties().getHeaders().get("x-delay") == null) { message.getMessageProperties().setHeader("x-delay", 10000); } else { Integer integer = (Integer) message.getMessageProperties().getHeaders().get("x-delay"); if (integer < 60000) { integer = integer + 10000; message.getMessageProperties().setHeader("x-delay", integer); } } – sea Jul 08 '16 at 02:57
1
I added CustomeMessage delay exchange

    @Bean
    CustomExchange delayExchange() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange("delayed-exchange", "x-delayed-message", true, false, args);
    }

Added MessagePostProcessor

  if (message.getMessageProperties().getHeaders().get("x-delay") == null) {
            message.getMessageProperties().setHeader("x-delay", 10000);
        } else {

            Integer integer = (Integer) message.getMessageProperties().getHeaders().get("x-delay");
            if (integer < 60000) {
                integer = integer + 10000;
                message.getMessageProperties().setHeader("x-delay", integer);
            }
        }

First time it delays 30 seconds and adds 10seconds each time till it reaches 600 seconds.This should be configurable.

And finally send the message to 

    rabbitTemplate.convertAndSend("delayed-exchange", queueName,message, rabbitMQMessagePostProcessor);
sea
  • 113
  • 8
  • Ok. Looks interesting, but I find it as an overhead to make the full journey to the broker just for retry... – Artem Bilan Jul 08 '16 at 03:18
  • Yes, but this way we don't loose any messages and the retry continues until x minutes then move the message to a different queue. – sea Jul 08 '16 at 03:22
  • 1
    We don't lose them with Spring Retry as well , just because we don't acknowledge it on broker. And yes we can send it to different queue as well. See docs I've pointed in my answer. – Artem Bilan Jul 08 '16 at 03:26
  • You can accept your answer anyway. Just in case to close the thread and let people to know that there is a solution. And some choice – Artem Bilan Jul 08 '16 at 03:38