Синхронный вызов в Vertx - PullRequest
0 голосов
/ 03 мая 2018

Мы пытаемся реорганизовать наш проект с сервлета на vertx3.x. И мы хотим повторно использовать слой DAO, который отвечает за данные запроса:

interace Adapter {
    List<Feature> query(String layer);
}

class DataBaseAdapter implements Adapter {

}

class FileAdapter implements Adapter {

}

class HttpVertx extends AbstractVertx {
    void start() {
        HttpServer server = vertx.createHttpServer();
        Router router = Router.router(vertx);
        router.route().handler((h->{
            List<Feature> r=new ArrayList();
            String[] layers=getLayerFromRequest(h.request());
            layers.forEach(l->{
                h.vertx().executeBlocking(future->{
                    future.complete(getAdapter(l).query(l));
                },false,res->{
                    List<Feature> data=res.result();
                    r.addAll(data);
                    //now how can I know that the loop have ended, and I can send the `r` to the client?
                });
            });

        }));
        server.requestHandler(router::accept).listen(8080);
    }

    Adapter getAdapter(String layer){
        //return database or file adapter accordingly
        return null;
    }
}

Как показано, все исходные запросы adapter являются блочной операцией, и когда я выполняю их в цикле, я не знаю, когда они все выполнили.

Кроме того, я не уверен, нужно ли проводить рефакторинг DatabaseAdapter с использованием vertx-jdbc? Если да, мне придется изменить сигнатуру метода интерфейса Adapter на синхронную, но FileAdapter не поддерживает это.

Каково правильное решение рефактора?

Ответы [ 2 ]

0 голосов
/ 05 мая 2018

Во-первых, не используйте executeBlocking(). Это ломает всю идею Vert.x
Во-вторых, я бы порекомендовал переписать ваш DAO для возврата Future. Это потребует некоторой работы, но работа будет довольно простой.

На высоком уровне это должно выглядеть примерно так:

// Use map(), as it returns value
List<Future> futures = layers.map((l) -> {
   return getAdapter(l).query(l);
});

CompositeFuture.all(futures).setHandler((r) -> {
   if (r.succeeded()) {
    // Continue here
   }
});
0 голосов
/ 03 мая 2018
  1. попробуйте переместить циклическую логику в блок executeBlocking и изменить тип обработчика на Handler<List<Feature>>

  2. нет, это не является абсолютно необходимым, поскольку перенос этих вызовов в executeBlocking уже выполняет дорогостоящую работу взаимодействия с вашей базой данных в рабочем пуле Verticle.

...