如何处理儿童演员的回应?

时间:2014-12-30 09:56:50

标签: akka

假设我们有一个actor,它将任务划分为子任务并将它们委托给子actor。在收到所有子反应器的响应之后,这个演员做了一些自己的工作。

管理subactors响应的最佳做法是什么?

例如,将结果放入Map<ActorRef, Object>并每次检查是否收到所有回复?

2 个答案:

答案 0 :(得分:1)

您可以使用Composing Futures。与儿童Routing结合使用会更好。类似的东西:

import scala.concurrent._
import akka.pattern._
import akka.routing._
import akka.actor._
import akka.util._
import scala.concurrent.duration._


case class Req(i: Int)
case class Response(i: Int)

class Worker extends Actor { def receive = {case Req(i) => sender ! Response(i) }}
class Parent extends Actor {
     import context.dispatcher
     implicit val timeout = Timeout(10, MINUTES) //timeout for response from worker
     val router: ActorRef = 
        context.actorOf(RoundRobinPool(5).props(Props[Worker]), "router") 
     def processResults(rs: Seq[Response]) = {println(rs); rs}
     def receive = { 
         case t: List[Req] => 
             Future.sequence(t.map(router ? _).map(_.mapTo[Response])).map(processResults) 
     }  
}

结果:

scala> ActorSystem().actorOf(Props(classOf[Parent])) ! List(Req(1), Req(2), Req(3))

 List(Response(1), Response(2), Response(3))

答案 1 :(得分:0)

Helo,通常我使用List实现它,或者如果你想要Map,对象类型为Either:Left和Right(保存有关每个actor结果的信息 - 成功或失败)并在每次来自child的新消息时检查map的长度收到,收到所有消息后,发送给自己的消息WorkDone或者具有这个含义的消息。

在Net的某个地方,我看到模式创建了单独的actor,用于收集所有来自孩子的消息

superactor:

val n = 1000
val collector = system.actorOf(Props(classOf[Collector],n)
for( i<-1 to n){
    system.actorOf(Child.props()).!(DoSomeWork)(collector)
}

集电极

class Collector(expectedMsgs: Int) extends Actor {
    var results = someCollection

    def endCollecting() = {
        // You can add here some logic before returning data
        context.parent ! results.toList //or whatever you want
        context.become(afterWork)
    }

    def receive = {
        case r: DataDone =>
            results += Right(r)
            if(results.length>=expectedMsgs){
                endCollecting()
            }
        case r: DataFail =>
            results += Left(r)
            if(results.length>=expectedMsgs){
                endCollecting()
            }
    }

    def afterWork = {
        case _ =>
            // for catch some late or mutiple messages
    }

}

另外看看 http://doc.akka.io/docs/akka/snapshot/contrib/aggregator.html