Vert.x: Обработчик Verticle custom startFuture всегда переписывается

Vert.x v3.5.1. Есть мой обычай start Метод Вертикали:

@Override
public void start(Future<Void> startFuture) throws Exception {
    startFuture.setHandler(event -> {
        if (event.succeeded()) {
            logger.info("Server started on port: {}", 8080);
        } else {
            logger.warn("Failed to start: {}", event.cause());
        }
    });
    vertx.createHttpServer()
            .requestHandler(router()::accept)
            .listen(8080, event -> {
                if (event.succeeded()) {
                    startFuture.complete();
                } else {
                    startFuture.fail(event.cause());
                }
            });
}

Я ожидаю, что мой пользовательский обработчик будет вызван, когда будущее завершится. Но это не так! В режиме отладки я вижу, что FutureImpl::setHandler вызывается дважды: один раз с моим пользовательским обработчиком, а затем с DeploymentManagerОбработчик во время doDeploy, Так что применяется последний обработчик.

Вопрос: можно ли указать собственный обратный вызов для запуска Verticle? Если да, как я могу это сделать?

Заранее спасибо.

2 ответа

Решение

Вы не должны изменять обработчик startFuture, поскольку он принадлежит вызывающей стороне. Проще говоря, не делайте этого:) Будущее используется, чтобы сигнализировать, что вы закончили с вашим стартовым кодом, а не определять, что должно быть сделано, когда вы закончите.

В вашем конкретном примере было бы лучше записать журналы, как только http-сервер загрузился, а затем указать startFuture, что вы закончили с выполнением кода.

@Override
public void start(Future<Void> startFuture) throws Exception {
    vertx.createHttpServer()
         .requestHandler(router()::accept)
         .listen(8080, event -> {
            if (event.succeeded()) {
                logger.info("Server started on port: {}", 8080);
                startFuture.complete();
            } else {
                logger.warn("Failed to start: {}", event.cause());
                startFuture.fail(event.cause());
            }
         });
}

Сначала напишите свою вертикалку как расширение AbstractVerticle. И не переопределять start(Future) метод. Вместо этого используйте start() метод. Будет вызываться из AbstractVerticle.start(Future)и вы можете указать это будущее в Vertx.deployVerticle(verticle, options, future) метод.

Например:

У тебя есть какая-то вертикаль. Делай в нем start() Метод только инициализации задач:

@Override
public void start() throws Exception {
    vertx.eventbus().consume(address, m -> {
       // consumer code skipped
    });
}

и вертикальная регистрация:

final DeploymentOptions opts = new DeploymentOptions().setWorker(true);
vertx.deployVerticle(verticle, opts, event -> {
    if (event.succeeded()) {
        log.info("Verticle successfully deployed. DeploymentId: " + event.result());
    } else {
        log.error("Verticle failed to deploy. Cause: " + event.cause().getMessage(), event.cause());
    }
});

Это все:)

Другие вопросы по тегам