Zygmuntix
Zygmuntix

Reputation: 359

How should I implement Vertx resiliency with retrying until some condition is met?

I would like to implement in my Vertx application resiliency. The case is that I have 2 application instances (primary and secondary) and I would like to try to send messages from primary to secondary as long as some condition is not met. In this way I want to implement resiliency - when there is no internet on primary's network - try sending the same message over and over. Let's say it is some boolean flag. I would like to achieve something like that (in pseudocode):

while(condition not met)
boolean messageSendingSuccess = tryToSendMessage(secondaryAddress);
if(messageSendingSuccess) return;

In reality I would like to create the whole queue of messages and implement the solution for the whole queue of messages (until the first message is sent - wait. when first message is sent - start trying to send new message etc.), but this is the scenario for one message.

How can I achieve that? I know that CircuitBreaker will not help me here https://vertx.io/docs/vertx-circuit-breaker/java/ because it is trying to reconnect given number of times. I do not want to stop trying after given number of times or after some time - I would like to stop trying when some condition is met. The solution from this webpage looks interesting: https://blog.axway.com/product-insights/amplify-platform/application-integration/vert-x-how-to-handle-retry-with-the-eventbus but I think this solution is only for communicating inside the application (not to communicate through the network) - I do not see where could I point out the network address where I should send the message in this code?

public class RetryWithHandlerVerticle extends AbstractVerticle {
      @Override
      public void start() throws Exception {
         vertx.eventBus() // (1)
              .send("hello.handler.failure.retry", // (2) 
                    "Hello", // (3) 
                     new Handler<AsyncResult<Message<String>>>() { // (4)
                        private int count = 1;
                        @Override
                        public void handle(final AsyncResult<Message<String>> aResult) {
                           if (aResult.succeeded()) { // (5)
                              System.out.printf("received: \"%s\"\n", aResult.result().body()); 
                           } else if (count < 3) { // (6)
                              System.out.printf("retry count %d, received error \"%s\"\n", 
                                                count, aResult.cause().getMessage());
                              vertx.eventBus().send("hello.handler.failure.retry", "Hello", this); // (7)
                              count = count + 1;
                           } else {
                              aResult.cause().printStackTrace(); // (8)
                           }
                        }
              });
        }
    }

Upvotes: 0

Views: 695

Answers (1)

tsegismont
tsegismont

Reputation: 9128

The Vert.x Event Bus does not store messages and thus does not offer any guarantee about delivery. In other words, when doing point-to-point messaging, it is the same as making an HTTP request: if you don't get an acknowledgement by the receiver, you don't know if the requests succeeded.

Consequently, you have to deal with it as with an HTTP interaction: design your system with commands that are idempotent. Then if you receive an error (failure or timeout), you can retry until the command is processed and acknowledged.

The Vert.x Circuit breaker has builtin retry policies, but it is your job to design the commands and implement the receiver side for idempotency.

Upvotes: 1

Related Questions