当前位置: 首页 > 知识库问答 >
问题:

键入Akka向父执行元发送消息

奚卓
2023-03-14

标题是不言自明的,我希望能够向父执行元发送消息(意味着我希望父执行元的actorref)。在Akka Classic(非类型化)中,父执行元的ActorRef可以通过以下方式从子执行元的ActorContext获得:

context.parent

(例如,参见这个问题(在Java))。

但是,Akka Typed中的Akka.actor.Typed.Scaladsl.ActorContext不公开父级的ActorRef。Scala中是否有惯用的方法为父执行元获取actorref

共有2个答案

水恩
2023-03-14

tldr:在创建父执行元引用时将其注入子执行元引用。

键入的Akka强制执行严格的协议,因此您需要绝对清楚地表明“这个演员与另一个演员对话”。公认的答案是一种变通方法(转换为classic并使用父级),但也有它的缺点:现在您不再强制执行类型了。

下面是一些可以让您开始的代码。查看如何强制执行所有类型。你可以用不同的方式来模拟这些特征,但是你应该得到一些改变:

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类型的“函数”语法,但您也可以使用更“面向对象”的语法。它遵循同样的方法。

益光亮
2023-03-14

如果您使用的是类型化的Akka,那么可以包含所有可能的父执行元的actorref的唯一[Scala]类型是actorref[Nothing],这是一个您不能向其发送消息的actorref,因此它的效用有限。

至少在经典API存在的时间内:

import akka.actor.typed.scaladsl.adapter._

type ClassicActorRef = akka.actor.ActorRef

val parentActorRef = context.toClassic.parent

这将是一个非类型化的actorref,即您可以自由地发送父执行元永远不会接受的消息。

如果您想要对执行元的父级的类型化引用,则需要在生成子执行元时嵌入该引用,就像如果您想要对当前消息的发件人的类型化引用,则需要在协议中嵌入replytos一样。

(Context.Sender在键入的ActorContext中不存在,原因与Context.Parent不存在相同;复制经典Context.Sender的解决办法类似:Context.ToClassic.Sender)

 类似资料:
  • 我遇到了在多个请求下扩展应用程序的问题。 每个请求都向一个参与者发送一个ask,然后生成其他参与者。这是很好的,但是,在负载下(一次5个以上的询问),会花费大量的时间将消息传递给目标执行元。最初的设计是均匀地隔离请求,但这造成了一个瓶颈。示例: 在此图片中,是在查询计划解析程序之后发送的。但是,当执行元接收到此消息时有一个多秒的间隔。这只在负载(5+请求/秒)下才会出现。我最初以为这是一个饥饿的问

  • 问题内容: 我可以发送消息给父进程吗? 主 子进程 问题答案: 简而言之: 较长的例子,我前段时间写过:

  • 在官方的akka 2.0.4文档中,它说: actor重新启动只替换实际的actor对象;邮箱的内容不受重新启动的影响,因此在postRestart钩子返回后,将继续处理邮件。不会再收到触发异常的消息。在重新启动时发送给参与者的任何消息都将像往常一样排队到其邮箱。 我唯一能想到的是,如果消息由于某种原因出现畸形,它将永远不会离开系统,并导致演员定期重新启动...

  • 我有一个actor,它持有一个。您可以使用以下对象从所述商店进行读写: 存储以及其值响应。 为了方便找到这家店,我有另一个演员(一个客串),我在飞行中创造: 这使我能够将所述参与者的“定位”(即通过其路径)保持在一个位置,避免在移动时进行过多的返工。此有一个可选的目标参与者,一旦执行查找,将将结果发送到该参与者。在我做一些工作之前,我在另一个参与者中使用所有这些来获取配置值: 但当我这么做时,我得

  • 我正在尝试刮这个url https://www.veikkaus.fi/fi/tulokset#!/tarkennettu-haku 刮伤主要有三个部分: null 我刚刚意识到,当选中时,输入字段从#date-range#from-date变为#date-range#from-date#focus-visible

  • 我试图点击支付信息的输入字段,然后提交这些输入字段的关键字。我发现它们在iframes,但我没有运气切换到不同的帧。我附上了html的图片以及页面的样子。任何帮助都将不胜感激!下面是我的代码: 输入字段/字段的html和屏幕的图像