我怎样才能安全地对 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是一样的,没有增长,因为没有递归。
我有一些启动 "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是一样的,没有增长,因为没有递归。