CodeFactory.DEV
CodeFactory.DEV

Reputation: 470

How do I implement a branching logic in Reactor that performs a conditional database logic?

The logic im trying to perform

    1. fetch db item 1
    2. fetch db item 2
    3. flag db item 1 as SUCCESS if db item 2 is found

Alternative Path:
    3.B. flag db item 1 as FAILURE if db item 2 was not found
    4.B. throw an exception upstream

Heres my code:

//MyService.java

Datastore datastore;

public Mono<Void> doTheThing(Long someId) {
   Mono<Item1> item1 = datastore
     .findItem1(someId)
     .cache();

   return item1
     .flatMap(it -> datastore.findItem2(it.getItem2Id())
     .then(item1.map(it -> it.withStatus("SUCCESS").flatMap(datastore::save))
      
      //HOW do i catch the error and persist item1 with "FAILED" status?
      //.doOnError(NoItem2Exception.class, item1.map(it -> it.withStatus("FAILURE").flatMap(datastore::save)) 
      // ^--- i have no clue what to do here
    
      .onErrorMap(NoItem1Exception.class, (e) -> new BusinessException(e))   

     .then();
}

Its dependency:

//Datastore.java

class Datastore {

   Mono<Item1> findItem1(Long item1Id) {
     return Mono.just(new Item1()); //not important
   }

   Mono<Item1> save(Item1 item1) { //not impt, just saves the item }

   Mono<Item2> findItem2(Long item2Id) {
      return db2.findById(item2Id)
        .switchIfEmpty(Mono.error(new NoItem2Exception());
   }
  
}

In the Service code, how do i branch out the logic when an exception is thrown (NoItem2Exception) from the findItem2 method?

My first step would be to flag the Item1 from the first DB query, then after that I want to bubble up the exception by wrapping it with another exception (not important, I know how to capture exceptions from the controller)

Upvotes: 0

Views: 476

Answers (1)

Patrick Hooijer
Patrick Hooijer

Reputation: 741

Mono.onErrorResume seems to be the method you are looking for. It allows you to switch to a different Mono (in your case database.save(Item1)) if a certain exception is encountered:

public Mono<Void> doTheThing(Long someId) {
    Mono<Item1> item1 = datastore
            .findItem1(someId);

    return item1
            .flatMap(it -> datastore.findItem2(it.getItem2Id())
                    .then(it.withStatus("SUCCESS").flatMap(datastore::save))
                    .onErrorResume(NoItem2Exception.class, e -> it.withStatus("FAILURE")
                            .flatMap(datastore::save)
                            .then(Mono.error(new BusinessException(e)))));
}

Upvotes: 1

Related Questions