0

We are using Spring Cloud Reactive Streams with RabbitMQ.

Spring Reactive Stream appears to acknowledge the message as soon as it pulls it off the queue. So any errors unhandled exceptions that happens during the message processing need to be handled in the application (which is a different than a non-reactive stream where unhandled exceptions can be thrown and a message would be rejected, thus sending it to a dead letter queue).

How are we supposed to deal with a sudden shutdown in an application when a message is in flight?

For instance:

  • Application pulls message off of queue
  • Application marks message as acknowledged
  • Application starts message processing
  • Application is shut down before message processing is complete

When this happens, the message appears to be lost completely, since it is off of the queue but the application is stopped. How can we recover these messages?

nosson
  • 1

1 Answers1

1

You need to use manual acknowledgments and defer the acks until processing is asynchronously completed. To do that, you need to consume the whole message:

    @Bean
    public Consumer<Flux<Message<String>>> async() {
        return inbound -> inbound

                ...

                .map(msg -> {
                    try {
                        msg.getHeaders().get(AmqpHeaders.CHANNEL, Channel.class)
                                .basicAck(msg.getHeaders().get(AmqpHeaders.DELIVERY_TAG, Long.class), false);
                    }
                    catch (IOException e) {
                        e.printStackTrace();
                    }
                    return msg.getPayload();
                })
                .subscribe(System.out::println);
    }
spring:
  cloud:
    stream:
      function.definition: async
      bindings:
        async-in-0:
          destination: testtock
          group: async
      rabbit:
        bindings:
          async-in-0:
            consumer:
              acknowledge-mode: MANUAL
              prefetch: 10

Use basicReject to requeue or send to the DLQ.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • Also, keep in mind that unlike imperative style message handlers where unit of processing is a single Message, in reactive the unit is the entire stream. We have absolutely no control of individual Messages aside from exposing some hooks as Gary showed. – Oleg Zhurakousky Apr 10 '20 at 06:13