我怎样才能安全地对 Scala Future 进行重试?

How can I safely do retries on a Scala Future?

我有一些启动 "slow" 进程的代码,我将其包装在 Future 中。如果出现问题,我想慢慢循环并在暂停后重试——无限期地。有点像这样:(我知道最终会有人介入并解决问题)

  def doSomething():Unit = {
    aFutureThing().onComplete { 
      case Success(s) => println("Success: "+s)
      case Failure(x) =>
        // Take some (hopefully) corrective action here, call for help, etc.
        Thread.sleep(1000) // pause a bit
        doSomething() // and try again...
    }
  }
  doit()

调用 onComplete 回调时,doSomething() 是否仍在堆栈中,还是因为我们在 Future 执行慢速任务 (aFutureThing) 时返回而被弹出?这种对 doSomething 的递归调用(最终)会破坏 stack/OutOfMemory 什么的吗?如果是这样......是否有更安全的方法来重试未来?

这里没有递归。 doSomething 将立即创建 Future 和 return,而 Future 被提交以在另一个线程上执行(如果它是游泳池,但不在 doSomething return 之前。

您可以通过 运行 在 repl 中看到类似的内容:

def foo(n: Int): Future[Int] = Future {
   Thread.sleep(1000)
   if(n < 10) throw new IllegalArgumentException(); else n 
} recoverWith { case e => 
   e.printStackTrace();
   println("N was " + n)
   Thread.sleep(1000)
   println("Rinse and repeat!")
   foo(n+1)
}

foo(1)

会"retry"9次才真正成功,每次都打印异常的栈,所以可以看到tracebacks是一样的,没有增长,因为没有递归。