Jak uniknac uruchomienia Mono switchIfEmpty

0

Mam do zaimplementowania taki flow w Spring Gateway

  • pobieram jakis rekord z bazy danych
  • jezeli ten rekord istnieje, jest z nim zwiazana jakas logika biznesowa, ktora w jednym z przypadkow moze zakonczyc sie tym np. zwracam jakis error
  • jezeli ten rekord nie istnieje to nie robie nic, po prostu wolam kolejny filtr

Wyglada to w ten sposob, logika w doSomethingIfDbHasResult jest calkowicie przypadkowa, w rzeczywistosci tutaj dzieje sie x innych rzeczy

    GatewayFilter gatewayFilterImpl() {
        return ((exchange, chain) ->
                queryDb()
                    .flatMap(res -> doSomethingIfDbHasResult(exchange, res))
                    .switchIfEmpty(doNothingIfDbHasNoResults(exchange, chain)));
    }

    private Mono<String> queryDb() {
        return Mono.just("Some string from reactive DB - this may be Mono.empty() as well");
    }

    private Mono<Void> doSomethingIfDbHasResult(ServerWebExchange exchange, String dbResult) {
        exchange.getResponse().setStatusCode(HttpStatus.CONFLICT);
        exchange.getResponse().getHeaders().add("x-custom-header", dbResult);
        return exchange.getResponse().setComplete();
    }

    private Mono<Void> doNothingIfDbHasNoResults(ServerWebExchange exchange, GatewayFilterChain chain) {
        return Mono.defer(() -> chain.filter(exchange));
    }

Niestety, powyzszy kod nie dziala tak jak chce. Gdy w bazie faktycznie brakuje danego rekordu, to od razu lecimy do switchIfEmpty i jest ok, jezeli jednak w bazie jest ren rekord, odpala sie zawartosc flatMap - to jest ok, ale rezultatem jest znow Mono<Void>, poniewaz tego wymaga GatewayFilter. W efekcie, switchIfEmpty i tak sie uruchamia co jest oczywiscie niepozadane w tym przypadku.

Pytanie wiec, jak to obsluzyc?

Jezeli wynik z bazy danych nie bylby reaktywny, to zrobilbym po prostu

        return ((exchange, chain) ->
                Optional.ofNullable("Query DB result")
                    .map(res -> doSomethingIfDbHasResult(exchange, res))
                    .orElseGet(() -> doNothingIfDbHasNoResults(exchange, chain)));

Niestety nie wiem jak takie cos osiagnac w przypadku Mono

0

Przestaw kolejność switchIfEmpty z flatMapą

0

@artur52: Wtedy switchIfEmpty wymaga zeby ta funkcja zwracala Mono<? extends String>, a w moim przypadku zwracany typ to bedzie Mono<Void>, tego nie przeskocze bo takie cos jest zwracane z GatewayFilterChain::filter

0

Musiałbym pokombinować, na szybko możesz użyć onErrorXXX, żeby odpalić fallback na jakiś błąd.

EDIT: Jeżeli chcesz przerwać filter chain, to nawet naturalniej byłoby zwrócić jakieś Mono.error

1 użytkowników online, w tym zalogowanych: 0, gości: 1