scalaakkascala-catsretry-logic

Scala - Retry on a for comp of futures (SoftwareMill Retry)


I have some code that attempts to execute a series of futures within a for comp and returns the value of the completion of the comp. I want to implement a retry function on the entirety of the for comp, rather than implementing an individual retry on each of the nested futures. I'm trying to use SoftwareMill's Retry

Example code:

  implicit val successDeterminer: Success[Either[Error, Option[FinalResponse]]] =
    Success[Either[Error, Option[FinalResponse]]](
      test => test.isRight
    )

    def processExample(var1: Variable1, var2: Variable2): Future[Either[Error, SuccessfulResponse]] = {
    val result = for {
      resp1 <- function1(var1) //returns EitherT[Future, Error, Response1]
      resp2 <- function2(var2) // returns EitherT[Future, Error, Response2]
      doesSomething = function3(resp2) // returns boolean
      finalResult <- function4(doesSomething) // returns EitherT[Future, Error, Option[FinalResponse]
    } yield finalResult

    val retryResult = policy.apply(() => result.value)(
      success = successDeterminer,
      executor = executionContext
    )
    handleRetriedResult(retryResult) // returns Future[Either[Error, Option[SuccessfulResponse]]
  }

So this runs, but I have a unit test that forces function2 to return a Left response. Therefore, I expect this retry to execute 3 times based on my policy. However, it only executes the call to function2 once.

Is it not possible to put the retry on the entire for comp and have it retry the entire flow of operations? Do I need to put it on each individual future that I have if I want them all to retry?


Solution

  • This always happens. As soon as I post a question it ends up clicking. So the problem is that the for comp is being defined as a variable inside the function call. So when the retry happens, its retrying that variable which already executed the for comp and therefore has a value. It doesn't need to recall the futures inside.

    By moving my for comp code into its own function, and then having the retry call that function instead, when it retries it is creating a brand new call of my for comp future and therefore executing the number of times I want.