简体   繁体   中英

Mutiny - Propagate completion to parent multi / polling

I am writing a little polling mechanism using Mutiny, part of me learning the library and i am kinda stuck in cancelling the polling when result is found. I tried using the tick() and what i came up with looks like

Multi.createFrom().ticks().every(Duration.ofSeconds(5))
    .onItem().transformToMultiAndMerge(tick -> {
      System.out.println("Tick:" + tick);
      return Multi.createFrom()
          .<Transaction>emitter(
              emitter -> {
                service.getTransactions().toMulti()
                    .onItem().transformToMultiAndMerge(
                        transactions -> Multi.createFrom().iterable(transactions))
                    .subscribe().with(transaction -> {
                      if (!verification.isOngoing()) {
                        emitter.fail(new TransactionVerificationException());
                      } else {
                        boolean transactionFound = transaction.getAmount().stream().anyMatch(
                            amount -> amount.getQuantity()
                                .equals("test"));
                        if (transactionFound) {
                          emitter.emit(transaction);
                          emitter.complete();
                        } 
                      }
                    });
              });
    })
    .subscribe()
    .with(transaction -> log.info(transaction),
        x -> x.printStackTrace());

Problem here is that the Multi from ticks() is running forever and the only way i think of to cancel it would be to propagate somehow that the emitter has completed. The case here is that i want to emit, and process only if certain conditions are met.

You approach is almost correct, though,

  • there is no need to create a custom MultiEmitter out of an existing Multi (or transformed Uni ) as you can leverage the different Multi operators on top of your source service#getTransaction result
  • you missed the EmptyMulti source which will automatically complete downstream subscriber chain and which you can use to signal an absence of valid item (ie Transaction )
  • you need to select the first valid item (being non-null) then transform your Multi to Uni which will result in the upstream subscription being cancelled automatically once an item is received

Here down what the stream pipeline would look like:

Multi.createFrom()
        .ticks()
        .every(Duration.ofSeconds(5))
        .onItem()
        // flat map the ticks to the `service#getTransactions` result
        .transformToMultiAndMerge(tick -> service.getTransactions()
                .toMulti()
                .onItem()
                // flatten Collection<Transaction> to Multi<Transaction>
                .transformToIterable(Function.identity())
                .onItem()
                .transformToMultiAndMerge(transaction -> {
                    if (!verification.isOngoing()) {
                        return Multi.createFrom().failure(new TransactionVerificationException());
                    } else {
                        boolean transactionFound = transaction.getAmount()
                                .stream()
                                .anyMatch(amount -> amount.getQuantity().equals("test"));
                        if (transactionFound) {
                            return Multi.createFrom().item(transaction);
                        } else {
                            return Multi.createFrom().empty();
                        }
                    }
                })
        )
        .select()
        .first(Objects::nonNull)
        .toUni()
        .subscribe()
        .with(transaction -> log.info(transaction), x -> x.printStackTrace());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM