【问题标题】:How to know which Future fail when doing Future.sequence?执行 Future.sequence 时如何知道哪个 Future 失败?
【发布时间】:2015-06-18 20:38:44
【问题描述】:

这是一个接收我正在制作的演员的一部分的示例:

def receive = {
        case "begin" =>
            val listOfFutures: IndexedSeq[Future[Any]] = workers.map(worker => worker ? Work("test"))
            val future: Future[IndexedSeq[Any]] = Future.sequence(listOfFutures)

            future onComplete {
                case Success(result) => println("Eventual result: "+result)
                case Failure(ex) =>  println("Failure: "+ex.getMessage)
            }
        case msg => println("A message received: "+msg)
    }

当其中一名工作人员的询问失败时(在超时的情况下),序列未来以失败告终。但是我想知道哪些工人失败了。有没有比不使用 Future.sequence 简单地一一映射 listOfFutures 更优雅的方法?

【问题讨论】:

  • 除了使用 Futures 之外,您还可以考虑只接收个人回复并处理它们。这个 Actor 也可能非常适合 FSM 特质。
  • 还有来自this answer的“Future of Trys”方法。

标签: scala akka


【解决方案1】:

您可以使用future的recover方法来映射或包装底层异常:

import scala.concurrent.{Future, ExecutionContext}

case class WorkerFailed(name: String, cause: Throwable) 
  extends Exception(s"$name - ${cause.getMessage}", cause)

def mark[A](name: String, f: Future[A]): Future[A] = f.recover {
  case ex => throw WorkerFailed(name, ex)
}

import ExecutionContext.Implicits.global

val f = (0 to 10).map(i => mark(s"i = $i", Future { i / i }))
val g = Future.sequence(f)

g.value  // WorkerFailed: i = 0 - / by zero

【讨论】:

    【解决方案2】:

    感谢@O__,我提供了另一种可能更适合某些情况的解决方案。

    case class WorkerDone(name: String)
    case class WorkerFailed(name: String)
    
    import ExecutionContext.Implicits.global
    
    val f = (0 to 10).map {
        i => Future {i/i; WorkerDone(s"worker$i")}.recover{
            case ex => WorkerFailed(s"worker$i")
        }
    }
    val futureSeq = Future.sequence(f)
    
    futureSeq onComplete {
            case Success(list) => list.collect {case result:WorkerFailed => result}.foreach {failed => println("Failed: "+failed.name)}
            case Failure(ex) => println("Exception: "+ex.getMessage)
        }
    
    // just to make sure program doesn't end before onComplete is called.
    Thread.sleep(2000L)
    

    我不确定我的示例是否是一个好的做法,但我的目标是知道哪些工人确实失败了,无论他们是如何失败的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-10
      • 1970-01-01
      • 2020-12-09
      • 2013-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多