Scala EitherT Future Exception handling

70 Views Asked by At

In the below method, only the exception coming from burnService.execute is getting caught in the catch. Any exception coming from earnService.execute is not getting caught. If I move the earnService,execute to top of the for comprehension, the error from earnService is caught but not from burnService.

private def processSearchItems(
      processedValuesCtx: OffersProcessedValuesCtx
  ): Future[Either[APIError, Seq[OfferV3Response]]] = {
    implicit val baseInfo: BaseInfo = BaseInfo.apply(this)

    val searchResults = processedValuesCtx.req.requestWrapperInternal.offers.searchResults
    // Process the search results
    val result        = searchResults.map { searchResult =>
      try {
        val searchItem                = enrichSearchItemWithPricingTokenData(searchResult)
        val searchItemProcessedValues = buildProcessedValues(searchItem, processedValuesCtx)

        (for {

          burnResponse                    <- EitherT(
                                               burnService.execute(
                                                 processedValuesCtx,
                                                 searchItemProcessedValues
                                               )
                                             )
          enrichedProcessedValuesAfterBurn =
            updateItemProcessedValuesAfterBurn(processedValuesCtx, burnResponse, searchItemProcessedValues)
          earnResponse                    <- EitherT(
                                               earnService.execute(
                                                 processedValuesCtx,
                                                 enrichedProcessedValuesAfterBurn
                                               )
                                             )

          splitTenders                    <- EitherT(
                                               splitTenderResponseTransformer
                                                 .buildSplitTenderResponse(
                                                   burnResponse,
                                                   earnResponse,
                                                   processedValuesCtx,
                                                   searchItemProcessedValues
                                                 )
                                             )
        } yield {
          val finalTenders = splitTenderResponseTransformer
            .removeChargeSplitsTooCloseApart(splitTenders, processedValuesCtx)
            .sortBy(_.burn.map(_.points))

          OfferV3Response(
            offerIdentifier = searchResult.identifier,
            priceInfo = PriceInfoV3ResponseWrapper(splitTenders = finalTenders),
            priceUsedToCalculate = getPriceUsedToCalculate(processedValuesCtx)
          )
        }).value

      } catch {
        case ex: Exception =>
          // log and build empty response
          logger.logError(
            rc.toBaseLog(
              s"Exception occurred!! while calculating offer :: ${ex.getMessage}",
              Some(ex)
            )
          )
               Future.successful(Right(resp))
      }
    }
    EitherUtils.sequenceOfFutureEither(result)
  }

Tried few things seems like none of the approaches worked

1

There are 1 best solutions below

0
Gaël J On

That's the expected behaviour: eitherT1.flatMap(eitherT2) will not "accumulate" errors, if the 1st fails you'll only get the 1st error.

It's the same as you'd get with a regular Future or Either.

If you want to accumulate errors, with Cats you can look at Validated.