Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

compose with vertx for sequential code

Tags:

vert.x

I have two operations step_1() and step_2() and want to execute step_2() AFTER step_1().

With normal java this would be:

step_1();
step_2();

With vertx I have to use vertx-compose(). Am I right?

According to https://groups.google.com/forum/#!topic/vertx/FuvlPLpoGOA, I dont need Futures for sequential code.

"If you want to do each request sequencially you dont need futures."

So how can I do that without using futures?

I dont know, if this matters: My Vertx from which this code is executed is a "Worker"-Verticle.

@Override
public void start(Future<Void> fut) throws IOException {

Future<Void> step_1 = Future.future();
    step_1.compose(res -> {
        // If the future succeeded
        Future<Void> step_2 = step_1();

        step_2.compose(res2 -> {
            step_2();

        }, Future.future().setHandler(handler -> {
            // If the future failed
        }));

        //I dont need that
    }, Future.future().setHandler(handler -> {
        // If the future failed
    }));

}

public void step_1(){
..
}

public void step_2(){
..
}

Is this the right and shortest (!) way?

like image 643
nimo23 Avatar asked Dec 23 '22 17:12

nimo23


2 Answers

Below is an example of chaining of Future, I have made the example very trivial nonetheless it showcases the concept.

@RunWith(VertxUnitRunner.class)
public class Chaining {
    private Vertx vertx = Vertx.vertx();

    @Test
    public void futures_chaining(TestContext context) throws Exception {
        Async async = context.async();

        firstOperation()
                .compose((outcome) -> {
                    System.out.println(outcome);

                    return secondOperation();
                })
                .compose(outcome -> {
                    System.out.println(outcome);

                    /*
                      For stopping unit test we are returning this future                                                                                                                                                              
                      for production use-case this would be Future.succeededFuture 
                      or Future.failedFuture depending on your method outcomes
                     */
                    return Future.future(handle -> async.complete());
                });
    }

    private Future<String> firstOperation() {
        Future<String> future = Future.future();

        vertx.setTimer(1000, delay -> future.complete("First Operation Complete"));

        return future;
    }

    private Future<String> secondOperation() {
        Future<String> future = Future.future();

        vertx.setTimer(1000, delay -> future.complete("Second Operation Complete"));

        return future;
    }
}
like image 132
y ramesh rao Avatar answered Jan 25 '23 01:01

y ramesh rao


"If you want to do each request sequencially you dont need futures."

No, it's not. In asynchronous frameworks like Vert.x, input/output operations are non-blocking. It means, that if you call few asynchronous operations, they'll start working simultaneously. And if you want to do few requests sequentially, then you should use futures or callbacks to execute new request only after previous one finished successfully.

Check this code with futures, newer version with RxJava 2 and article about project.

@Override
public Future<Optional<Todo>> getCertain(String todoID) {
    Future<Optional<Todo>> result = Future.future();
    redis.hget(Constants.REDIS_TODO_KEY, todoID, res -> {
        if (res.succeeded()) {
            result.complete(Optional.ofNullable(
                res.result() == null ? null : new Todo(res.result())));
        } else
            result.fail(res.cause());
    });
    return result;
}

@Override
public Future<Todo> update(String todoId, Todo newTodo) {
    return this.getCertain(todoId).compose(old -> {
        if (old.isPresent()) {
            Todo fnTodo = old.get().merge(newTodo);
            return this.insert(fnTodo)
                .map(r -> r ? fnTodo : null);
        } else {
            return Future.succeededFuture();
        }
    });
}
like image 34
berserkk Avatar answered Jan 25 '23 01:01

berserkk