Akka / Scala:onSuccess多个要求不同的演员

时间:2014-05-30 03:46:35

标签: scala akka

我试图对不同的子角色进行异步调用,例如:

A ---> B ---> C
        \---> D

Actor A向Actor B发送请求消息,B向C和D发送两条任务消息,当C和D发回结果时,B合并结果并将其发送回A。

我试图使用ask模式和onSuccess来解决这个问题:

class B(fakeInterface: String, subInterface: Array[ActorRef]) extends Actor {

val subCount = subInterface.length
var finishCount = 0

def receive = {
  case reqMsg(msg) =>

    if (subInterface.length == 0){
      sender ! DoneMessage(msg)
    } else {
      implicit val timeout = Timeout(5 minutes)
      val composedFutures = subInterface map { x =>
        (x ? DoItMessage(msg)).mapTo[DoneMessage]
      }

      val allResult = Future.sequence(composedFutures)
      allResult.onSuccess {
        case _ => sender ! DoneMessage(msg)
      }
    }
  }
}

但是上面的代码根本没有编译,我有三个错误:

[error] inferred type arguments [dummy.DoneMessage,Array] do not conform to method sequence's type parameter bounds [A,M[_] <: TraversableOnce[_]]
[error]         val allResult = Future.sequence(composedFutures)
[error]                                ^
[error]  type mismatch;
[error]  found   : Array[scala.concurrent.Future[dummy.DoneMessage]]
[error]  required: M[scala.concurrent.Future[A]]
[error]         val allResult = Future.sequence(composedFutures)
[error]                                         ^
[error]  Cannot construct a collection of type M[A] with elements of type A based on a collection of type M[scala.concurrent.Future[A]].
[error]         val allResult = Future.sequence(composedFutures)
[error]                                        ^
[error] three errors found

我该如何解决这个问题?或者有更合适的方法来解决这种情况吗?

2 个答案:

答案 0 :(得分:2)

Array不是TraversableOnce。存在从ArrayWrappedArray的隐式转换,它是TraversableOnce,但是当类型参数被推断为Array时,隐式转换为时已晚。如果将Array替换为集合库中的一个类,例如List您可以通过这些编译器错误。

ask模式效率低下,因为它必须为每个请求创建一个假的actor,这会产生相当大的开销。允许非演员代码与演员进行通信非常有用,但演员本身应该直接互相发送消息。演员B必须是有状态的,因此它可以跟踪来自C和D的消息,但它会带来更好的解决方案。

答案 1 :(得分:1)

scala.Array不会从scala.collection.TraversableOnce继承,因此无法与Future.sequence一起使用。请尝试使用ListSeq

http://www.scala-lang.org/api/current/index.html#scala.Array