首页 > 解决方案 > 在 Akka Typed 中向父actor发送消息

问题描述

标题是不言自明的,我希望能够向父演员发送消息(意思是我想要父母的ActorRef)。在 Akka Classic(无类型)中,ActorRef可以从孩子的ActorContext通过以下方式获得父演员的 :

context.parent

(例如,参见this question (in Java))。

然而,akka.actor.typed.scaladsl.ActorContext在 Akka Typed 中并没有ActorRef为父级公开一个。在 Scala 中是否有一种惯用的方法来ActorRef为父演员获取一个?

标签: scalaakkaakka-typed

解决方案


TLDR:在创建子角色时将父角色引用注入到子角色中。

Akka Typed 强制执行严格的协议,因此您需要明确表示“这个演员与另一个演员交谈”。接受的答案是一种解决方法(转换为经典并使用父级),但有其缺点:现在您不再强制执行类型。

这是一些可以帮助您入门的代码。看看所有类型是如何被强制执行的。您可以对特征进行不同的建模,但您应该有所了解:

object ParentActor {
  sealed trait Command 
  
  case class DoSomething() extends Command
  
  // you do not have to do this, but creating another trait
  // allows you to narrow the amount of messages the parent can receive from the child
  sealed trait ChildNotification extends Command
  case class MessageFromChild() extends ChildNotification

  
  def apply(): Behavior[Command] = {
    Behaviors.receive( (context, message) => 
      message match {
        case DoSomething() =>
          // create a child that knows about its parent
          context.spawn(ChildActor(context.self), "child")
          Behaviors.same

        case MessageFromChild() =>
          context.log.info("I received a message from my child")
          Behaviors.same
      })
  }
}

object ChildActor {
  sealed trait Command
  case class Work() extends Command
  
  // inject the parent here (or any other actor that matches the signature)
  def apply(parent: ActorRef[ParentActor.ChildNotification]): Behavior[Command] = {
     Behaviors.receive( (context, message) => 
       message match {
         case Work() =>
           // send message to parent actor (or any other actor with that type)
           parent ! ParentActor.MessageFromChild()
           Behaviors.same

     })
  }
}

顺便说一句,我使用的是 akka typed 的“函数式”语法,但您也可以使用更“面向对象”的语法。它遵循相同的方法。


推荐阅读