询问模式在使用Akka流时不起作用

时间:2018-11-05 19:08:17

标签: scala akka akka-stream

我尝试实现与tutorial稍有不同的示例:

object Test extends App {
      class A extends Actor {
        override def receive: Receive = {
          case 10 => context.system.terminate()
          case x =>
            println(s"Received: $x")
            sender() ! x
        }
      }

      implicit val system = ActorSystem()
      implicit val materializer = ActorMaterializer()
      implicit val dispatcher = system.dispatcher
      implicit val askTimeout = Timeout(1, TimeUnit.SECONDS)

      val a = system.actorOf(Props[A])

      val graph = RunnableGraph.fromGraph(GraphDSL.create() {
        {
          implicit builder: GraphDSL.Builder[NotUsed] => {
            import GraphDSL.Implicits._

            val source: Source[Int, NotUsed] = Source(1 to 10)
            source ~> Flow[Int].ask(2)(a) ~> Sink.foreach[String](println)
            ClosedShape
          }
        }
      })

      val x = graph.run()
}

结果我得到了:

  

已收到:1

     

已收到:2

但是我希望这样:

  

已收到:1

     

1

     

已收到:2

     

2

     

...

     

已收到:9

     

9

如果我通过Source.actorRef向演员发送消息,则一切正常,演员接收到所有消息。似乎物化演员正在等待引用演员的响应。 如何解决?

1 个答案:

答案 0 :(得分:2)

如果您将Sink.foreach[String](println)替换为Sink.onComplete(println) 您会看到流终止并显示错误:

Received: 1
Received: 2
Failure(java.lang.ClassCastException: Cannot cast java.lang.Integer to scala.runtime.Nothing$)

问题在于Source.ask需要知道将演员的回复映射到see API docs的类。否则,它将尝试将回复投射为Nothing并在内部引发异常。

要修复您的原始代码,请用Ask [Int]替换ask:

  val graph = RunnableGraph.fromGraph(GraphDSL.create() {
    {
      implicit builder: GraphDSL.Builder[NotUsed] => {
        import GraphDSL.Implicits._

        val source: Source[Int, NotUsed] = Source(1 to 10)
        source ~> Flow[Int].ask[Int](2)(a) ~> Sink.foreach(println)
        ClosedShape
      }
    }
  })