我怎样才能从接待员那里得到 ActorRef 以便我的演员可以向那个演员发送消息
How can I get the ActorRef from the Receptionist so my actor can send messages to that actor
所以我有 2 个演员,ClientIn
和 Maker
。
我需要在 ClientIn 中引用 Maker,这样我就可以将 ClientIn
收到的一些消息转发给 Maker
。
我将 Maker
添加到 receptionist
,但由于 clientIn
是第一个创建的,而 maker
第二个我不确定如何查询以获取 actorRef .
实际上我只是很困惑我现在如何查询接待员以便 clientIn 将获得对 Maker actor 的引用。
这是我的:
// 守护actor构造函数:
Behaviors.setup[Any] { context =>
implicit val ec: ExecutionContext = context.executionContext
val system = context.system
val clientIn = context.spawn(ClientIn(), "ClientIn")
val maker = context.spawn(Maker(clientOut), "mmaker")
....
}
ClientIn.scala:
object ClientIn {
sealed trait ClientInCommand
case class Watch(symbol: String) extends ClientInCommand
case class Command(value: String) extends ClientInCommand
private case class ListingResponse(listing: Receptionist.Listing)
extends ClientInCommand
def apply(): Behavior[ClientInCommand] = {
Behaviors.setup { context =>
context.log.info(s"ClientIn starting...${context.self}")
val listingResponseAdapter =
context.messageAdapter[Receptionist.Listing](ListingResponse.apply)
var maker: Option[ActorRef[Maker.MMCommand]] = None
Behaviors.receiveMessage[ClientInCommand] {
case Watch(symbol) =>
context.log.info(s"ClientIn watch message received..$symbol")
Behaviors.same
case Command(value) =>
context.log.info(s"ClientInCommand.Command with value:$value")
// TODO: Maker ! RecieveCommand(value)
Behaviors.same
case ListingResponse(Maker.makerKey.Listing(listings)) =>
maker = Some(listings.head)
Behaviors.same
}
}
}
}
Maker.scala:
object Maker {
val makerKey = ServiceKey[MMCommand]("makerKey")
sealed trait MMCommand
case object Startup extends MMCommand
case object Shutdown extends MMCommand
def apply(): Behavior[MMCommand] = {
Behaviors.setup { context =>
context.system.receptionist ! Receptionist.Register(
makerKey,
context.self
)
Behaviors.receiveMessage[MMCommand] {
case Startup =>
context.log.info("Maker startup message received..")
Behaviors.same
case Shutdown =>
context.log.info("Maker shutdown message received..")
Behaviors.same
}
}
}
}
您可以向接待员发送 Receptionist.Subscribe(Maker.makerKey)
消息,如 Actor discovery 上的 Akka 文档所述:
context.system.receptionist ! Receptionist.Subscribe(Maker.makerKey, listingResponseAdapter)
引用文档:
It will send Listing messages to the subscriber, first with the set of entries upon subscription, then whenever the entries for a key are changed.
这允许它接收制造商 ActorRef
,即使它在生成 ClientIn
演员后向接待员注册也是如此。但是,原则上 ClientIn
可能会在此之前收到其他消息,例如 Command
。它将需要处理这些情况,可能通过 stashing 或删除命令直到 Maker
被注册。
在这个具体的例子中,通过先生成 Maker
并将它的 ActorRef
传递给 ClientIn.apply
来避免这个要求会更简单:
val maker = context.spawn(Maker(), "mmaker")
val clientIn = context.spawn(ClientIn(maker), "ClientIn")
然后,在ClientIn
:
def apply(maker: ActorRef[Maker.MMCommand]): Behavior[ClientInCommand] = {
Behaviors.setup { context =>
context.log.info(s"ClientIn starting...${context.self}")
Behaviors.receiveMessage[ClientInCommand] {
case Watch(symbol) =>
context.log.info(s"ClientIn watch message received..$symbol")
Behaviors.same
case Command(value) =>
context.log.info(s"ClientInCommand.Command with value:$value")
maker ! Maker.ReceiveCommand(value)
Behaviors.same
}
}
}
请注意,从 spawn
返回的 ActorRef
能够立即接收消息,即使 actor 尚未完全初始化。
所以我有 2 个演员,ClientIn
和 Maker
。
我需要在 ClientIn 中引用 Maker,这样我就可以将 ClientIn
收到的一些消息转发给 Maker
。
我将 Maker
添加到 receptionist
,但由于 clientIn
是第一个创建的,而 maker
第二个我不确定如何查询以获取 actorRef .
实际上我只是很困惑我现在如何查询接待员以便 clientIn 将获得对 Maker actor 的引用。
这是我的:
// 守护actor构造函数:
Behaviors.setup[Any] { context =>
implicit val ec: ExecutionContext = context.executionContext
val system = context.system
val clientIn = context.spawn(ClientIn(), "ClientIn")
val maker = context.spawn(Maker(clientOut), "mmaker")
....
}
ClientIn.scala:
object ClientIn {
sealed trait ClientInCommand
case class Watch(symbol: String) extends ClientInCommand
case class Command(value: String) extends ClientInCommand
private case class ListingResponse(listing: Receptionist.Listing)
extends ClientInCommand
def apply(): Behavior[ClientInCommand] = {
Behaviors.setup { context =>
context.log.info(s"ClientIn starting...${context.self}")
val listingResponseAdapter =
context.messageAdapter[Receptionist.Listing](ListingResponse.apply)
var maker: Option[ActorRef[Maker.MMCommand]] = None
Behaviors.receiveMessage[ClientInCommand] {
case Watch(symbol) =>
context.log.info(s"ClientIn watch message received..$symbol")
Behaviors.same
case Command(value) =>
context.log.info(s"ClientInCommand.Command with value:$value")
// TODO: Maker ! RecieveCommand(value)
Behaviors.same
case ListingResponse(Maker.makerKey.Listing(listings)) =>
maker = Some(listings.head)
Behaviors.same
}
}
}
}
Maker.scala:
object Maker {
val makerKey = ServiceKey[MMCommand]("makerKey")
sealed trait MMCommand
case object Startup extends MMCommand
case object Shutdown extends MMCommand
def apply(): Behavior[MMCommand] = {
Behaviors.setup { context =>
context.system.receptionist ! Receptionist.Register(
makerKey,
context.self
)
Behaviors.receiveMessage[MMCommand] {
case Startup =>
context.log.info("Maker startup message received..")
Behaviors.same
case Shutdown =>
context.log.info("Maker shutdown message received..")
Behaviors.same
}
}
}
}
您可以向接待员发送 Receptionist.Subscribe(Maker.makerKey)
消息,如 Actor discovery 上的 Akka 文档所述:
context.system.receptionist ! Receptionist.Subscribe(Maker.makerKey, listingResponseAdapter)
引用文档:
It will send Listing messages to the subscriber, first with the set of entries upon subscription, then whenever the entries for a key are changed.
这允许它接收制造商 ActorRef
,即使它在生成 ClientIn
演员后向接待员注册也是如此。但是,原则上 ClientIn
可能会在此之前收到其他消息,例如 Command
。它将需要处理这些情况,可能通过 stashing 或删除命令直到 Maker
被注册。
在这个具体的例子中,通过先生成 Maker
并将它的 ActorRef
传递给 ClientIn.apply
来避免这个要求会更简单:
val maker = context.spawn(Maker(), "mmaker")
val clientIn = context.spawn(ClientIn(maker), "ClientIn")
然后,在ClientIn
:
def apply(maker: ActorRef[Maker.MMCommand]): Behavior[ClientInCommand] = {
Behaviors.setup { context =>
context.log.info(s"ClientIn starting...${context.self}")
Behaviors.receiveMessage[ClientInCommand] {
case Watch(symbol) =>
context.log.info(s"ClientIn watch message received..$symbol")
Behaviors.same
case Command(value) =>
context.log.info(s"ClientInCommand.Command with value:$value")
maker ! Maker.ReceiveCommand(value)
Behaviors.same
}
}
}
请注意,从 spawn
返回的 ActorRef
能够立即接收消息,即使 actor 尚未完全初始化。