假设我们有一个actor,它将任务划分为子任务并将它们委托给子actor。在收到所有子反应器的响应之后,这个演员做了一些自己的工作。
管理subactors响应的最佳做法是什么?
例如,将结果放入Map<ActorRef, Object>
并每次检查是否收到所有回复?
答案 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