Как отследить исключения и результаты вложенных фьючерсов в scala - PullRequest
1 голос
/ 28 апреля 2020

У меня есть сценарий, в котором я хочу вычислить вложенные фьючерсы. Ниже приведен сценарий:

def firstFuture(factor: Int): Future[Int] = Future {
    println("Running future 1")
    Thread.sleep(3000)
    5 * factor
  }

  def secondFuture(factor: Int) = Future {
    println("Running future 2")
    throw new Exception("fjdfj")
    Thread.sleep(4000); 3 * factor
  }

  def thirdFuture = Future {
    println("Running future 3")
    Thread.sleep(5000)
    throw new Exception("mai fat raha hu")
  }

  def method = {
    (Future(5).map { factor =>
      firstFuture(factor).recover { case ex: Exception => throw new Exception("First future failed") }
      secondFuture(factor).recover { case ex: Exception => throw new Exception("Second future failed") }
      thirdFuture.recover { case ex: Exception => throw new Exception("Third future failed") }
    }).flatMap(identity).recover { case ex: Exception =>
      println("Inside recover")
      println(ex.getMessage)
    }
  }
  Await.result(method, 20 seconds)

Я хочу обработать исключения из всего вложенного будущего, где завершается основное будущее. Предположим, что если SecondFuture потерпит неудачу, то результатом будет SecondFuture. Но я только отражаю это для Третьего будущего. Как я могу этого достичь. Какой должна быть реализация.

Примечание. Предполагается, что вложенные три фьючерса будут работать параллельно.

1 Ответ

3 голосов
/ 28 апреля 2020

Причина, по которой вы получаете только ошибку третьего будущего, состоит в том, что значение целого блока является последним выражением блока, поэтому

Future(5).map { factor =>
  firstFuture(factor)   // this executes but the result is discarded
  secondFuture(factor)  // this executes but the result is discarded
  thirdFuture           // the last expression becomes the value of the whole block
}

Также рассмотрите, что происходит, когда у нас есть вложенные фьючерсы и мы бросаем во внутреннее будущее

Future(41).map { v =>
  Future(throw new RuntimeException("boom"))  // the exception is simply swallowed
  v + 1                                      
}

Результат - Future(42), несмотря на исключение, выброшенное во внутреннее Future. Это важно понимать, так как в противном случае мы можем ввести тихие сбои в системе.

Для достижения вашего требования попробуйте комбинацию для понимания и Future.sequence

for {
  factor <- Future(5)
  results <- Future.sequence(List(firstFuture(factor), secondFuture(factor), thirdFuture))
} yield results

Три фьючерса, переданные в sequence, будут выполняться одновременно, а sequence вернет неудачное будущее, если произойдет сбой любого из них.

...