重试返回Future的函数

Mic*_*ael 2 scala future exception

假设我有一个foo执行异步计算并返回的函数Future

def foo(x: Int)(implicit ec: ExecutionContext): Future[Int] = ???
Run Code Online (Sandbox Code Playgroud)

现在,我想重试此计算n时间,直到计算成功。

def retryFoo(x: Int, n: Int)(implicit ec: ExecutionContext): Future[Int] = ???
Run Code Online (Sandbox Code Playgroud)

我也想返回重试时抛出的所有异常。因此,我定义了新的异常类,ExceptionsList并要求在所有重试均失败时retryFoo返回ExceptionsList

case class ExceptionsList(es: List[Exception]) extends Exception { ... }  
Run Code Online (Sandbox Code Playgroud)

你会怎么写retryFoo重试foo,并返回一个Future与无论是foo结果还是ExceptionsList

Vik*_*ang 5

我可能会做这样的事情:

final case class ExceptionsList(es: List[Throwable]) extends Throwable
def retry[T](n: Int, expr: => Future[T], exs: List[Throwable] = Nil)(implicit ec: ExecutionContext): Future[T] =
  Future.unit.flatMap(_ => expr).recoverWith {
    case e if n > 0 => retry(n - 1, expr, e :: exs)
    case e => Future.failed(new ExceptionsList(e :: exs))
  }
Run Code Online (Sandbox Code Playgroud)

expr之所以称为“按名称”,是因为它本身可能引发异常,而不是返回失败的Future。我将累积的异常保留在列表中,但是我想那是一种味道。