简体   繁体   English

Akka 流与 Scala 3:mapAsync 失败

[英]Akka Streams with Scala 3: mapAsync fails

I made some first experiments with Akka Streams and Scala 3. Although I know that Akka has only experimental support for Scala 3, I am a little bit surprised that the following simple program does not work: I made some first experiments with Akka Streams and Scala 3. Although I know that Akka has only experimental support for Scala 3, I am a little bit surprised that the following simple program does not work:

object HelloAkka extends App {

  implicit val actorSystem: ActorSystem = ActorSystem();
  implicit val executionContext: ExecutionContext = actorSystem.dispatcher

  val done = Source(1 to 5)
    .mapAsync(2)(n => Future {
      println(s"processing item $n in thread ${Thread.currentThread().getId}")
    })
    .runWith(Sink.ignore)

  Await.result(done, Duration.Inf)
  println("stream processing finished.")
  Await.result(actorSystem.terminate(), Duration.Inf)
  println("main thread terminated.")
}

When I build this program with Scala 3.2.0 using the following build.sbt the program hangs when mapAsync is invoked (no future is ever executed):当我使用 Scala 3.2.0 使用以下build.sbt构建这个程序时,程序在调用mapAsync时挂起(没有执行未来):

ThisBuild / version := "0.1.0-SNAPSHOT"

ThisBuild / scalaVersion := "3.2.0"  // fails
// ThisBuild / scalaVersion := "2.13.8" // works

lazy val root = (project in file("."))
  .settings(
    name := "hello-akka",
    libraryDependencies += "com.typesafe.akka" %% "akka-stream" % "2.6.20"
  )

When changing the Scala version to 2.13.8 the program behaves as expected.将 Scala 版本更改为 2.13.8 时,程序按预期运行。 Also version 2.7.0-M1 of the Akka Streams library shows the same behavior. Akka Streams 库的 2.7.0-M1 版本也显示了相同的行为。

Since mapAsync is elementary to Akka Streams programming, I suspect that I miss an obvious error.由于mapAsync是 Akka Streams 编程的基础,我怀疑我错过了一个明显的错误。

Full running example: https://scastie.scala-lang.org/jheinzel/PHzMfGNDSmaSbssTX5YhWw .完整运行示例: https://scastie.scala-lang.org/jheinzel/PHzMfGNDSmaSbssTX5YhWw

I suspect that you're encountering weirdness with extends App which relies on DelayedInit being treated specially by the compiler.我怀疑您在使用extends App时遇到了奇怪的问题,它依赖于编译器对DelayedInit进行特殊处理。 Scala 3 no longer gives DelayedInit special treatment, instead the code in the body of HelloAkka becomes part of the static initializer of the object, which means it executes before the HelloAkka object is considered to be a real object by the JVM. Scala 3 no longer gives DelayedInit special treatment, instead the code in the body of HelloAkka becomes part of the static initializer of the object, which means it executes before the HelloAkka object is considered to be a real object by the JVM. This means that any thread outside the thread initializing HelloAkka (ie the equivalent of the "main thread") will block until such time as the initializing thread completes, which in this case entails a deadlock thanks to the Await s in the body of HelloAkka .这意味着初始化HelloAkka的线程之外的任何线程(即“主线程”的等价物)都将阻塞,直到初始化线程完成为止,在这种情况下,由于Await主体中的HelloAkka ,这会导致死锁。

Moving your code into a main method (which is not typically necessary with Scastie) causes your program to run as expected .将您的代码移动到main方法中(这对于 Scastie 通常不是必需的)会导致您的程序按预期运行

Removing the Await s to allow the static initializer to return causes the program to run as expected删除Await以允许 static 初始化程序返回导致程序按预期运行

Await ing in an App which is intended to be compiled for Scala 3 will deadlock if some asynchronous task (in this case the Akka Stream's mapAsync stage) reads a val / var from the App .如果某些异步任务(在本例中为Await Stream 的mapAsync阶段)从App读取val / var ,则在旨在为 Scala 3 编译的App中的 Await 将死锁。

The Scala 3 docs recommend either @main annotations or an explicit def main . Scala 3 文档推荐@main注释或显式def main

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM