如何使用 Behavior.receiveMessage 处理生命周期信号

How to handle lifecycle signal with Behavior.receiveMessage

我有一个演员,创建如下:

    Behaviors.setup { context =>
          val greeter = context.spawn(HelloWorld.greeter, "greeter")

          Behaviors.receiveMessage { message =>
            val replyTo = context.spawn(HelloWorldBot.bot(greetingCounter = 0, max = 3), message.name)
            greeter ! HelloWorld.Greet(message.name, replyTo)
            Behaviors.same
          }
        }

我想在 Behaviors.receiveMessage 和文档中处理 Signals 消息(例如 PostStop):

Simplified version of Receive with only a single argument - the message to be handled. Useful for when the context is already accessible by other means, like being wrapped in an setup or similar. Construct an actor behavior that can react to both incoming messages and lifecycle signals. After spawning this actor from another actor (or as the guardian of an akka.actor.typed.ActorSystem) it will be executed within an ActorContext that allows access to the system, spawning and watching other actors, etc. Compared to using AbstractBehavior this factory is a more functional style of defining the Behavior. Processing the next message results in a new behavior that can potentially be different from this one. State is maintained by returning a new behavior that holds the new immutable state.

但是如何在Behaviors.receiveMessage中实现生命周期信号呢?

这是文档 https://doc.akka.io/api/akka/current/akka/actor/typed/scaladsl/Behaviors$.html#receiveMessageT:akka.actor.typed.scaladsl.Behaviors.Receive[T]

的 link

因为 receiveMessage[A] 只能匹配符合类型 A 的消息,您无法声明包含 [=14] 系统消息的类型 A =], 等等。相反 Akka-Typed 有一个专用的 receiveSignal.

鉴于您的示例,您已经通过 Behavior.setup 捕获共享上下文,您可以将 receiveSignal 链接到消息行为上以成为同一行为的一部分:

Behaviors.setup { context =>
      val greeter = context.spawn(HelloWorld.greeter, "greeter")

      Behaviors.receiveMessage { message =>
        val replyTo = context.spawn(HelloWorldBot.bot(greetingCounter = 0, max = 3), message.name)
        greeter ! HelloWorld.Greet(message.name, replyTo)
        Behaviors.same
      }.receiveSignal {
         case (context, PostStop) =>
           context.log.info("behavior stopped")
           Behaviors.same
    }