Akkatype with classic actors giving me an error: Unsupported access to ActorContext from outside of Actor

Akkatype with classic actors giving me an error: Unsupported access to ActorContext from outside of Actor

我的 akka 应用程序(同时使用 akka typed 和 classic)出现以下运行时错误

java.lang.UnsupportedOperationException: Unsupported access to ActorContext from the outside of Actor[akka://my-classic-actor-system/user/ChatServer#1583147696]. No message is currently processed by the actor, but ActorContext was called from Thread[my-classic-actor-system-akka.actor.default-dispatcher-5,5,run-main-group-0].

def main(args: Array[String]): Unit = {
    val logger = LoggerFactory.getLogger(getClass)
    logger.debug("Server starting yo...")

    implicit val system = akka.actor.ActorSystem("my-classic-actor-system")

    implicit val typedGuardian: ActorRef[Any] =
      system.spawn(HttpWebsocketServer(), "ChatServer")



     val client = system.actorOf(Client.props(remote), "clientActor")
    
    //..
}

错误的来源是在 HttpWebsocketServer 内部,它取自 ( https://github.com/johanandren/chat-with-akka-http-websockets/blob/akka-2.6/src/main/scala/chat/Server.scala#L101):

object HttpWebsocketServer {
    def apply(): Behavior[Any] = {
        Behaviors.setup[Any] { context =>
            implicit val ec: ExecutionContext = context.executionContext

            val system = context.system
            val chatRoom = context.spawn(ChatRoom(), "chat")
            val userParent = context.spawn(SpawnProtocol(), "users")

            val maker =
            context.spawn(websock.Maker(), "mmaker")

             val route =
                path("chat") {
                    get {
                        handleWebSocketMessages(
                        newUserFlow(system, chatRoom, userParent)
                        )
                    }
                }

            // needed until Akka HTTP has a 2.6 only release
            implicit val materializer: Materializer =
                SystemMaterializer(context.system).materializer

            implicit val classicSystem: akka.actor.ActorSystem =
                context.system.toClassic

            Http()
                .bindAndHandle(route, "0.0.0.0", 9000)
                // future callback, be careful not to touch actor state from in here
                .onComplete {
                case Success(binding) =>
                    context.log.debug(
                    s"Started server at ${binding.localAddress.getHostString}:${binding.localAddress.getPort}"
                    )
                case Failure(ex) =>
                    ex.printStackTrace()
                    context.log.error("Server failed to start, terminating")
                    context.system.terminate()
                }

            Behaviors.empty

        }
    
    }
}         

build.sbt

val AkkaVersion = "2.6.18"
val AkkaHttpVersion = "10.2.7"      
libraryDependencies ++= Seq(
    "io.netty" % "netty-all" % "4.1.68.Final",
    "com.typesafe.akka" %% "akka-actor" % AkkaVersion,
    "com.typesafe.akka" %% "akka-actor-typed" % AkkaVersion,
    "com.typesafe.akka" %% "akka-stream" % AkkaVersion,
    "com.typesafe.akka" %% "akka-stream-typed" % AkkaVersion,
    "com.typesafe.akka" %% "akka-http" % AkkaHttpVersion,
    "com.typesafe.akka" %% "akka-http-spray-json" % AkkaHttpVersion,
    "ch.qos.logback" % "logback-classic" % "1.2.10",
    scalaTest % Test
) 

如果我在我的代码中注释掉下面的内容,我不会收到运行时错误,所以看起来这就是问题的根源:

 implicit val materializer: Materializer =
                SystemMaterializer(context.system).materializer

            implicit val classicSystem: akka.actor.ActorSystem =
                context.system.toClassic

            Http()
                .bindAndHandle(route, "0.0.0.0", 9000)
                // future callback, be careful not to touch actor state from in here
                .onComplete {
                case Success(binding) =>
                    context.log.debug(
                    s"Started server at ${binding.localAddress.getHostString}:${binding.localAddress.getPort}"
                    )
                case Failure(ex) =>
                    ex.printStackTrace()
                    context.log.error("Server failed to start, terminating")
                    context.system.terminate()
                }
 

我不确定我能做些什么来解决这个问题,我正在从系统或子演员中创建演员。

您不能在 actor 之外使用 context。你这样做是为了回想你的未来。

case Success(binding) =>
   context.log.debug(
  s"Started server at ${binding.localAddress.getHostString}:${binding.localAddress.getPort}"
   )
case Failure(ex) =>
   ex.printStackTrace()
   context.log.error("Server failed to start, terminating")
   context.system.terminate()

问题是 actor 上下文被视为 actor 的内部状态,不能在范围之外访问。连你的评论都这么说

// future callback, be careful not to touch actor state from in here

解决方案是在回调之外的 val 中预先引用您的 logsystem(您已经有了)。回调看起来像

case Success(binding) =>
   log.debug(
  s"Started server at ${binding.localAddress.getHostString}:${binding.localAddress.getPort}"
   )
case Failure(ex) =>
   ex.printStackTrace()
   log.error("Server failed to start, terminating")
   system.terminate()