在Akka中回复多个答案

时间:2018-07-03 14:44:58

标签: scala akka

我与一位演员进行了交流

[rabbitmq_management].

只要我从val future = ask(foo, Bar())(1 seconds).mapTo[Row] val result = Await.result(future, 1 seconds) 发回一个Row,就可以正常工作。我将如何回答多个foo

Row

随后是sender() ! Row() sender() ! Row() 吗?

3 个答案:

答案 0 :(得分:1)

就像其他人在评论中提到的那样,仅当您将所有行作为一条消息发送时,询问模式才有效。使用akka-stream是为此构建处理器的绝佳解决方案:

val barActor = system.actorOf(Props(new BarActor()))

def runQuery(): Future[Seq[Row]] = {
  // complete when EndOfQuery message is received 
  val runnableGraph = Source.actorRef[DataProtocol](Int.MaxValue, OverflowStrategy.fail)
    .takeWhile(elem => {
      elem match {
        case _:Row => true
        case _ | EndOfQuery => false
      }
    })
    .toMat(Sink.seq[DataProtocol])(Keep.both)

  // keep both the ActorRef and the Future[DataProtocol]
  val (actor, future) = runnableGraph.run()

  // issue query to actor
  barActor ! Query(actor)

  // only Row messages were emitted:
  future.map(_.asInstanceOf[Seq[Row]])
}

val data = Await.result(runQuery(), Duration.Inf)

如您在问题中提到的,您将需要停止消息。

答案 1 :(得分:0)

您只能用一个对象进行响应。响应列表呢?

class Foo extends Actor {
  def receive = {
    case Bar(): sender() ! List.of(Row(), Row())
  }
}

val future = ask(foo, Bar())(1 seconds).mapTo[List[Row]]
val result = Await.result(future, 1 seconds)

val row0 = result(0);
val row1 = result(1);

答案 2 :(得分:0)

在没有更多背景信息的情况下,我不确定100%地希望完成什么。我怀疑@lasekio的answer可能正是您想要的。

但是,如果您正在寻找异步流解决方案,那就是说,如果您要在行进入时对其进行处理,而不是等到行全部可用之后(也许是因为行数超出了内存的容纳能力-数百万/ billions),那么,那么,您应该使用Akka Streams。但是由于您似乎反对这种说法,因此有一种选择是纯Akka + Futures:

演员将返回该行,以及下一行的未来。由于您需要一种表示没有更多行的方法,因此在示例中将结果包装在Option中,其中Some包含Row和下一个{{ 1}},而Row表示没有更多行。您也可以创建单独的类型,或使用None,只是可以清楚地表明没有其他数据的内容。在演员方面,您可以这样做:

null

在消费者方面:

case _: Bar =>
  if (/*... there are more rows...*/) sender() ! Some((Row(), (context.self ? Bar()))
  else sender() ! None