Scala 向Akka中的父演员发送消息
标题是不言自明的,我希望能够向家长参与者发送消息(意思是我希望家长的Scala 向Akka中的父演员发送消息,scala,akka,akka-typed,Scala,Akka,Akka Typed,标题是不言自明的,我希望能够向家长参与者发送消息(意思是我希望家长的ActorRef)。在Akka Classic(非类型化)中,可以通过以下方式从孩子的ActorContext中获取家长演员的ActorRef: context.parent (例如,见) 但是,akka typed中的akka.actor.typed.scaladsl.ActorContext不会为父级公开ActorRef。在Scala中,是否有一种惯用的方法来为父角色获取一个ActorRef?如果您使用的是类型化的Akka
ActorRef
)。在Akka Classic(非类型化)中,可以通过以下方式从孩子的ActorContext
中获取家长演员的ActorRef
:
context.parent
(例如,见)
但是,akka typed中的
akka.actor.typed.scaladsl.ActorContext
不会为父级公开ActorRef
。在Scala中,是否有一种惯用的方法来为父角色获取一个ActorRef
?如果您使用的是类型化的Akka,那么可以包含所有可能的父角色的ActorRef
的唯一[Scala]类型是ActorRef[无]
,这是一个您无法向其发送消息的ActorRef
,因此,这是有限的效用
至少在经典API存在的情况下:
import akka.actor.typed.scaladsl.adapter._
type ClassicActorRef = akka.actor.ActorRef
val parentActorRef = context.toClassic.parent
这将是一个非类型化的ActorRef
,即您可以自由发送家长参与者永远不会接受的消息
如果希望对参与者的父级进行类型化引用,则在生成子参与者时需要嵌入该引用,就像希望对当前消息的发件人进行类型化引用一样,您需要在协议中嵌入replyTo
s
(context.sender
在键入的ActorContext
中不存在,原因与context.parent
不存在相同;复制经典上下文的解决方法。sender
类似:context.toClassic.senderTLDR:
在创建父参与者引用时将其注入子参与者引用
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类型的“函数”语法,但您也可以使用更“面向对象”的语法。它遵循相同的方法。这是否回答了您的问题?投票决定重新开放,因为自被投票的问题被复制以来,相关API发生了巨大的变化。Akka 2.6与之前的2.6和2.6版本有很大的不同,因此答案可能很难回答。对于OP,您是否使用类型化的actor API?值得编辑您的问题,以明确这一点(2.6中的旧答案不适用于您,但只是为了明确起见),用户的原始帖子提到“许多过时的答案”不适用。因为如果不使用类型化API,那些过时的答案是有效的。(请注意,如果按照官方Akka文档中Akka Actor的链接,您可以访问类型化API的文档,即如果Akka是新手,则类型化API是Akka Actor),我还将在目标问题中针对经典和类型化问题给出一个适合Java的答案,因为这可能会更高。