使用 ActorSelection 识别 Actor
Identifying an Actor using an ActorSelection
我正在写一个 Actor
应该看另一个 Actor
;我们将后者称为 target。一旦目标停止,我的 Actor
就会自行停止。对于这个目标,我只有一个 ActorSelection
。要观看它,我显然需要一个 ActorRef
,所以我想我应该向 ActorSelection
发送一个 Identify
消息;当它回复 ActorIdentity
时,我会得到它的 ActorRef
。到目前为止一切顺利,但我无法让它工作。
规格如下:
// Arrange
val probe = TestProbe()
val target = TestProbe().ref
val sut = system.actorOf(MyActor.props(system.actorSelection(target.path)), "watch-target")
probe watch sut
// Act
target ! PoisonPill
// Assert
probe.expectTerminated(sut)
和实现(FSM
,细节略过):
log.debug("Asking target selection {} to identify itself; messageId={}", selection.toString(), messageId)
selection ! Identify(messageId)
when(Waiting) {
case Event(ActorIdentity(`messageId`, Some(ref)), Queue(q)) =>
log.info("Received identity for remote target: {}", ref)
context.watch(ref)
goto(NextState) using TargetFound(ref)
case Event(ActorIdentity(`messageId`, None), Queue(q)) =>
log.error("Could not find requested target {}", selection.toString())
stop()
}
initialize()
现在,当我运行 我的测试时,它是绿色的,因为被测系统确实停止了。但问题是它会自行停止,因为它无法使用上述步骤找到目标。日志文件显示:
Asking target selection ActorSelection[Anchor(akka://default/), Path(/system/testProbe-3)] to identify itself; messageId=871823258
Could not find requested target ActorSelection[Anchor(akka://default/), Path(/system/testProbe-3)]
我是不是遗漏了什么明显的东西?也许 TestProbe
不应该暴露它的真实身份?我什至尝试将虚拟 Actor
实例化为 target 但结果是一样的。有什么线索吗?
原来答案其实很简单:测试运行得如此之快,以至于在MyActor
将Identify
消息发送给selection
之前,Actor
在selection
后面选择已经收到它的 PoisonPill
,因此被杀死。
在发送 PoisonPill
之前添加一点 Thread.sleep()
解决了这个问题。
目标参与者在发出识别请求之前被终止。这是因为 Akka only guarantees order when sending messages between a given pair of actors.
如果您在以下行上方添加 thread.sleep
,识别请求应该会成功。
Thread.sleep(100)
// Act
target ! PoisonPill
请注意,可能有更好的方法来编写测试代码 - 休眠线程并不理想。
您的观看演员还应处理目标演员的 Terminated
消息,如 here 所述。
我正在写一个 Actor
应该看另一个 Actor
;我们将后者称为 target。一旦目标停止,我的 Actor
就会自行停止。对于这个目标,我只有一个 ActorSelection
。要观看它,我显然需要一个 ActorRef
,所以我想我应该向 ActorSelection
发送一个 Identify
消息;当它回复 ActorIdentity
时,我会得到它的 ActorRef
。到目前为止一切顺利,但我无法让它工作。
规格如下:
// Arrange
val probe = TestProbe()
val target = TestProbe().ref
val sut = system.actorOf(MyActor.props(system.actorSelection(target.path)), "watch-target")
probe watch sut
// Act
target ! PoisonPill
// Assert
probe.expectTerminated(sut)
和实现(FSM
,细节略过):
log.debug("Asking target selection {} to identify itself; messageId={}", selection.toString(), messageId)
selection ! Identify(messageId)
when(Waiting) {
case Event(ActorIdentity(`messageId`, Some(ref)), Queue(q)) =>
log.info("Received identity for remote target: {}", ref)
context.watch(ref)
goto(NextState) using TargetFound(ref)
case Event(ActorIdentity(`messageId`, None), Queue(q)) =>
log.error("Could not find requested target {}", selection.toString())
stop()
}
initialize()
现在,当我运行 我的测试时,它是绿色的,因为被测系统确实停止了。但问题是它会自行停止,因为它无法使用上述步骤找到目标。日志文件显示:
Asking target selection ActorSelection[Anchor(akka://default/), Path(/system/testProbe-3)] to identify itself; messageId=871823258
Could not find requested target ActorSelection[Anchor(akka://default/), Path(/system/testProbe-3)]
我是不是遗漏了什么明显的东西?也许 TestProbe
不应该暴露它的真实身份?我什至尝试将虚拟 Actor
实例化为 target 但结果是一样的。有什么线索吗?
原来答案其实很简单:测试运行得如此之快,以至于在MyActor
将Identify
消息发送给selection
之前,Actor
在selection
后面选择已经收到它的 PoisonPill
,因此被杀死。
在发送 PoisonPill
之前添加一点 Thread.sleep()
解决了这个问题。
目标参与者在发出识别请求之前被终止。这是因为 Akka only guarantees order when sending messages between a given pair of actors.
如果您在以下行上方添加 thread.sleep
,识别请求应该会成功。
Thread.sleep(100)
// Act
target ! PoisonPill
请注意,可能有更好的方法来编写测试代码 - 休眠线程并不理想。
您的观看演员还应处理目标演员的 Terminated
消息,如 here 所述。