akka 在context.actorSelection中找到“未找到参与者”,actorFor在其中工作

tquggr8v  于 2022-11-05  发布在  其他
关注(0)|答案(1)|浏览(149)

代码为:

//      pilot = Await.result(context.actorSelection(s"../$pilotName").resolveOne, 5.seconds)
         pilot = context.actorFor("../" + pilotName)

actorFor在实际应用和测试中效果良好。
这真的很奇怪,注解的代码在应用程序中工作,但在运行测试时失败与akka.actor.ActorNotFound(它寻找的演员存在,我认为超时是足够的)。
试验是:

class PilotsSpec extends TestKit(ActorSystem("PilotsSpec",
  ConfigFactory.parseString(PilotsSpec.configStr)))
  with ImplicitSender with WordSpecLike with MustMatchers {
  import PilotsSpec._
  import plane.Plane._

  def nilActor: ActorRef = TestProbe().ref

  val pilotPath = s"/user/TestPilots/$pilotName"
  val copilotPath = s"/user/TestPilots/$copilotName"

  def pilotsReadyToGo(): ActorRef = {
    implicit val timeout = Timeout(5.seconds)

    val a = system.actorOf(Props(
      new IsolatedStopSupervisor with OneForOneStrategyFactory {
        def childrenStart() = {
          context.actorOf(Props[FakePilot], pilotName)
          context.actorOf(Props(new CoPilot(testActor, nilActor, nilActor)), copilotName)
        }
      }), "TestPilots")
    Await.result(a ? IsolatedLifeCycleSupervisor.WaitForStart, 5.seconds)
    system.actorFor(copilotPath) ! Pilots.ReadyToGo
    a
  }

  "CoPilot" should {
    "takecontrol when the Pilotdies" in {
      pilotsReadyToGo()
      // Kill the Pilot
      system.actorFor(pilotPath) ! PoisonPill
      // Sincethe test classis the "Plane" we can
      // expect to see this request
      expectMsg(GiveMeControl)
      // The girl who sent it had better be Mary
      lastSender must be (system.actorFor(copilotPath))
    }
  }

}

我不知道我是否做错了演员选择。
我尝试使用onComplete,但它仍然不起作用,并在测试中抛出ActorNotFound异常。

val f = context.actorSelection("../" + pilotName).resolveOne
  f onComplete {
    case Success(v) => { pilot = v; context.watch(pilot); println("pilot get") }
    case Failure(e) => throw e
  }

有没有人知道为什么actorFor可以工作,但actorSelection失败(在测试中完全失败)?
然后我将下面的代码添加到测试代码中:

system.actorSelection(pilotPath).resolveOne map {v => println("------pilot:"+v)}
system.actorSelection(copilotPath).resolveOne map {v => println("------copilot:"+v)}
Thread.sleep(1000)

然后我尝试用常量字符串pilotPath替换../+pilotName,但再次失败(无论是context.actorSelection还是context.system.actorSelection
下面是例外(一个片段):
航空电子设备飞行员规范
[详细信息]正在将1个Scala源代码编译为G:\scala_workspace\akka_test_u7\target\scala-2.10\测试类...
[warn]有2个不推荐使用警告;有关详细信息,请使用-deprecation重新运行
[警告]找到一个警告
------副驾驶:演员[akka://驾驶员规格/用户/测试驾驶员/玛丽#962346268]
------飞行员:参与者[akka://飞行员规范/用户/测试飞行员/Mark#-320295209]
参与者选择[锚(akka://试点规范/用户/测试试点/Mary#962346268),路径(/../Mark)]
[错误] [04/29/2014 15:13:16.080] [PilotsSpec-akka.actor.default-dispatcher-4] [akka. dispatcher.Dispatcher]未找到以下项的执行元:演员选择[Ancho r(akka://试点规范/用户/测试试点/玛丽#962346268),路径(/../Mark)]
akka.actor.ActorNotFound:找不到以下项目的执行元:参与者选择[锚(akka://试点规范/用户/测试试点/Mary#962346268),路径(/../Mark)]
在akka. actor. actorselection中,选择一个角色,然后应用这个角色。
请输入您的姓名和密码,然后输入您的密码。
在scala.concurrent.impl.CallbackRunnable.run(承诺。等级:32)
在akka.dispatch.batchingExecutor$Batch$$anonfun$run$1.processBatch$1(批处理执行程序.比例:67)
在akka.dispatch.batchingExecutor$Batch$$anonfun$run$1.apply$mcV$sp(批处理执行程序.比例:82)上执行批处理。
(批处理执行程序.规模:59)
(批处理执行程序.规模:59)
在scala中创建一个新的块上下文。
(Batch.run批量执行程序,规模:58)
(未来的脚本:74)
在这个例子中,您可以使用一个脚本来执行批处理操作。
只有actorFor在测试中工作,其他使用actorSelection注解的代码在应用程序中工作,但在测试中失败(太奇怪了):

class CoPilot(plane: ActorRef,
  var controls: ActorRef,
  altimeter: ActorRef) extends Actor {
  implicit val timeout = Timeout(1.second)
  implicit val ct = context.dispatcher
  var pilot: ActorRef = context.system.deadLetters
  val pilotName: String = context.system.settings.config.getString("cc.akka.avionics.flightcrew.pilotName")
  val pilotId : Int = 200

  def receive = {
    case ReadyToGo =>
//      fails in test
//      pilot = Await.result(context.actorSelection(s"../$pilotName").resolveOne, 3.seconds)
//      println("get pilot:" + pilot.path + " dead:" + pilot.isTerminated)

//      actorFor works
//      pilot = context.actorFor("../" + pilotName) 
//      context.watch(pilot)
//      autopilot = Await.result(context.actorSelection("../AutoPilot").resolveOne, 100.millis)

//      fails in test
//      val f = context.actorSelection("../" + pilotName).resolveOne  
//      f onComplete {
//        case Success(v) => { pilot = v; context.watch(pilot); println("pilot get") }
//        case Failure(e) => throw e
//      }
        println("-----------"+pilotName)

        // fails in test
        context.actorSelection("../" + pilotName) ! Identify(pilotId) 

    case Terminated(_) =>
      plane ! GiveMeControl
    case Controls(controlSurfaces) =>
      controls = controlSurfaces

    case ActorIdentity(pilotId, Some(ref)) =>
      pilot = ref
      context.watch(pilot)
      println("find copilot:"+pilot)
    case ActorIdentity(pilotId, None) => 
      println("failed to find pilot")
  }
}
q3aa0525

q3aa05251#

actorFor会建立新的执行元,而actorSelection则会寻找已经存在的执行元。
我怀疑您的actorSelection不起作用而您的actorFor起作用的原因是因为该actor当前不存在。

相关问题