重试返回Future的函数 [英] Retry a function that returns a Future
问题描述
假设我有一个函数 foo
,该函数执行异步计算并返回 Future
:
Suppose I've got a function foo
that performs asynchronous computation and returns a Future
:
def foo(x: Int)(implicit ec: ExecutionContext): Future[Int] = ???
现在我想重试此计算 n
次直到计算成功。
Now I'd like to retry this computation n
times until the computation succeeds.
def retryFoo(x: Int, n: Int)(implicit ec: ExecutionContext): Future[Int] = ???
我还要返回重试时抛出的所有 all 异常。因此,我定义了新的异常类 ExceptionsList
并要求 retryFoo
返回 ExceptionsList
当所有重试均失败时。
I would like also to return all exceptions thrown while retrying. So, I define new exception class ExceptionsList
and require retryFoo
to return ExceptionsList
when all retries fail.
case class ExceptionsList(es: List[Exception]) extends Exception { ... }
您如何编写 retryFoo
重试 foo
并返回 Future
或 foo
结果或 ExceptionsList
?
How would you write retryFoo
to retry foo
and return a Future
with either the foo
result or ExceptionsList
?
推荐答案
我可能会做这样的事情:
I'd probably do something like this:
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))
}
expr
是按名称调用的,因为它本身可能引发异常,而不是返回失败的Future。我将累积的例外记录在列表中,但我想那是一种味道。
expr
is call-by-name since it itself could throw an exception rather than returning a failed Future. I keep the accumulated exceptions in a list, but I guess that's a taste-thing.
这篇关于重试返回Future的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!