Since drexin answered the part about handling and recovering exceptions, let me try to answer the question about the recursive function related to futures. I believe that using Promise will help you achieve your goal. The modified code will look like this:
def win(prefix: String): String = { val prom = Promise[String]() def doWin(p:String) { val futureGameLog = aPlayThatMayFail futureGameLog.onComplete(t => t match { case Success(diceRoll) => prom.success("%s, and finally, I won! I rolled %d !!!".format(prefix, diceRoll)) case Failure(e) => e match { case ex: LoserException => doWin("%s, and then i got %d".format(prefix, ex.diceRoll)) case other => prom.failure(new Exception("%s, and then somebody cheated!!!".format(prefix))) } }) } doWin(prefix) Await.result(prom.future, someTimeout) }
Now this will not be true recursion in the sense that it will grow one long stack due to the fact that futures are asynchronous, but this is similar to recursion in spirit. Using a promise gives you something to block while recursion does this, blocking the caller from what happens behind the scenes.
Now, if I were to do this, I would suggest overriding things like this:
def win(prefix: String): Future[String] = { val prom = Promise[String]() def doWin(p:String) { val futureGameLog = aPlayThatMayFail futureGameLog.onComplete(t => t match { case Success(diceRoll) => prom.success("%s, and finally, I won! I rolled %d !!!".format(prefix, diceRoll)) case Failure(e) => e match { case ex: LoserException => doWin("%s, and then i got %d".format(prefix, ex.diceRoll)) case other => prom.failure(new Exception("%s, and then somebody cheated!!!".format(prefix))) } }) } doWin(prefix) prom.future }
So you can defer the decision about whether to block or use asynchronous callbacks to the caller of this function. This is more flexible, but also provides the caller with the fact that you are performing async calculations, and I'm not sure if this will be acceptable for your scenario. I will leave this decision to you.
source share