Как правильно вызвать внешнюю службу (API) в реактивном приложении Quarkus с использованием vertx и Mutiny?

Я новичок в реактивном программировании с помощью vertx и muntiny (quarkus). У меня есть следующее требование:

Структура: возврат вызова внешнего API -> Ответ.

      class Response {String abc; List<AnotherClass> another; ...}
class AnotherClass { List<Role>> roles ...}

Возврат вызова БДUni<List<RoleFromDB>> rolesDB

Я хочу, чтобы приведенный ниже вызов выполнялся реактивным образом в цепочке. Может кто-нибудь, пожалуйста, подскажите мне, как правильно это сделать.

  1. Вызов внешнего API.2. Вызовите БД (postgres с реактивным Hibernate и Panache) с некоторым значением идентификатора, полученным от API.3. Добавьте результат запроса к БД к результату из API и верните как новыйUni<Response>

Также не могли бы вы показать мне пример реактивного вызова внешнего API? Я не могу найти в Интернете подходящего материала для этого.

Это то, чем я сейчас занимаюсь.

       Uni<List<RolesfromDB>> roles == db call returning Uni<List<RoleFromDB>>
    
roles.chain(role -> {
    Response res = Unirest.get(url).header(...);
//Is calling external endpoint this way fine?

  Uni<Response> uniRes = Uni.createFrom().item(res);
//do some operation with uniRes to assign role to the response object and return a new Uni<Response> ...
    });

Правильно ли это, или мне нужно использовать другие средства, например

          io.vertx.axle.ext.web.client.WebClient?

Мы будем очень признательны за пример правильного вызова внешнего API.

1 ответ

Я бы рекомендовал два подхода.

  1. использование реактивного клиента REST

При использовании реактивного клиента REST (см. https://quarkus.io/guides/rest-client-reactive) вы создаете интерфейс Java, который абстрагирует взаимодействия HTTP. Прокси-сервер генерируется автоматически, поэтому вам не нужен низкоуровневый HTTP-клиент. Этот реактивный клиент поддерживает как блокировку, так и неблокировку. Итак, в вашем случае у вас будет что-то вроде:

      @GET
Uni<Response> invokeMyService(Role role)

И затем в своем конвейере вы делаете:

      roles.chain(role -> client.invokeMyService(role));
  1. с помощью веб-клиента Vert.x

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

      public MyClass(Vertx vertx) {  // io.vertx.mutiny.core.Vertx
    this.client = WebClient.create(vertx); // io.vertx.mutiny.ext.web.client.WebClient
}

// ...
roles.chain(role -> {
   var req = this.client.getAbs(url); // using GET, use the method you need
   // Add headers and so on
   return req.send()
      .map(resp -> resp.bodyAsJsonObject().mapTo(Response.class);
    });