読者です 読者をやめる 読者になる 読者になる

ActorInitializationExceptionではpostStopは呼ばれない(?) - akka

akka 2.3.13です。

preStartの中で例外が出た時にpostStopが呼ばれないような挙動があり、微妙に問題になったので本当に呼ばれてないのかどうか調べてみました。

import akka.actor._
 
object Main extends App {
  val system = ActorSystem()
  try {
    val actor = system.actorOf(Props[SupervisorExceptionActor])
    Thread.sleep(3000)
 
    (1 to 5).foreach{ actor ! _}
  } finally {
    system.shutdown()
  }
}
 
class SupervisorExceptionActor extends Actor {
  val actor = context.actorOf(Props[ExceptionActor])
 
  override def preStart() = {
    super.preStart()
    println(s"preStart() in ${getClass()}")
  }
 
  override def postStop() = {
    super.postStop()
    println(s"postStop() in ${getClass()}")
  }
 
  override val supervisorStrategy = OneForOneStrategy(){ case _ => SupervisorStrategy.Stop }
 
  def receive = {
    case x:Terminated => println(s"Terminated ${x}")
    case x => actor ! x
  }
}
 
class ExceptionActor extends Actor {
  override def preStart() = {
    println(s"preStart() in ${getClass()}")
//    throw new RuntimeException("preStartで死亡")
  }
  override def postStop() = println(s"postStop() in ${getClass()}")
 
  def receive = {
    case x: Int if x == 3 => throw new RuntimeException("Receiveで死亡")
    case x: Int => println(x + " : " + this)
  }
}

preStartの例外をコメントアウトしてreceiveで例外を発生させたときのログ(ExceptionActorのpostStopが呼ばれる)

> run
[info] Running Main
preStart() in class SupervisorExceptionActor
preStart() in class ExceptionActor
1 : ExceptionActor@4f340570
2 : ExceptionActor@4f340570
[ERROR] [02/01/2016 16:12:23.580] [default-akka.actor.default-dispatcher-2] [akka://default/user/$a/$a] Receiveで死亡
java.lang.RuntimeException: Receiveで死亡
    at ExceptionActor$$anonfun$receive$2.applyOrElse(Main.scala:44)
    at akka.actor.Actor$class.aroundReceive(Actor.scala:467)
    at ExceptionActor.aroundReceive(Main.scala:36)
    at akka.actor.ActorCell.receiveMessage(ActorCell.scala:516)
    at akka.actor.ActorCell.invoke(ActorCell.scala:487)
    at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:238)
    at akka.dispatch.Mailbox.run(Mailbox.scala:220)
    at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:397)
    at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
    at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
    at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
    at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
 
postStop() in class ExceptionActor
[INFO] [02/01/2016 16:12:23.584] [default-akka.actor.default-dispatcher-3] [akka://default/user/$a/$a] Message [java.lang.Integer] from Actor[akka://default/user/$a#1727329357] to Actor[akka://default/user/$a/$a#-526916506] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
[INFO] [02/01/2016 16:12:23.584] [default-akka.actor.default-dispatcher-3] [akka://default/user/$a/$a] Message [java.lang.Integer] from Actor[akka://default/user/$a#1727329357] to Actor[akka://default/user/$a/$a#-526916506] was not delivered. [2] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
postStop() in class SupervisorExceptionActor
[success] Total time: 3 s, completed 2016/02/01 16:12:23

preStartで例外を発生させたときのログ(ExceptionActorのpostStopが呼ばれない)

> run
[info] Running Main
preStart() in class ExceptionActor
preStart() in class SupervisorExceptionActor
[ERROR] [02/01/2016 16:11:52.124] [default-akka.actor.default-dispatcher-4] [akka://default/user/$a/$a] preStartで死亡
akka.actor.ActorInitializationException: exception during creation
    at akka.actor.ActorInitializationException$.apply(Actor.scala:166)
    at akka.actor.ActorCell.create(ActorCell.scala:596)
    at akka.actor.ActorCell.invokeAll$1(ActorCell.scala:456)
    at akka.actor.ActorCell.systemInvoke(ActorCell.scala:478)
    at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:263)
    at akka.dispatch.Mailbox.run(Mailbox.scala:219)
    at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:397)
    at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
    at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
    at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
    at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
Caused by: java.lang.RuntimeException: preStartで死亡
    at ExceptionActor.preStart(Main.scala:39)
    at ExceptionActor.preStart(Main.scala:36)
    at akka.actor.Actor$class.aroundPreStart(Actor.scala:472)
    at ExceptionActor.aroundPreStart(Main.scala:36)
    at akka.actor.ActorCell.create(ActorCell.scala:580)
    ... 9 more
 
[INFO] [02/01/2016 16:11:55.125] [default-akka.actor.default-dispatcher-2] [akka://default/user/$a/$a] Message [java.lang.Integer] from Actor[akka://default/user/$a#-1647396111] to Actor[akka://default/user/$a/$a#-198589273] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
[INFO] [02/01/2016 16:11:55.125] [default-akka.actor.default-dispatcher-2] [akka://default/user/$a/$a] Message [java.lang.Integer] from Actor[akka://default/user/$a#-1647396111] to Actor[akka://default/user/$a/$a#-198589273] was not delivered. [2] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
[INFO] [02/01/2016 16:11:55.125] [default-akka.actor.default-dispatcher-2] [akka://default/user/$a/$a] Message [java.lang.Integer] from Actor[akka://default/user/$a#-1647396111] to Actor[akka://default/user/$a/$a#-198589273] was not delivered. [3] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
postStop() in class SupervisorExceptionActor
[INFO] [02/01/2016 16:11:55.126] [default-akka.actor.default-dispatcher-2] [akka://default/user/$a/$a] Message [java.lang.Integer] from Actor[akka://default/user/$a#-1647396111] to Actor[akka://default/user/$a/$a#-198589273] was not delivered. [4] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
[INFO] [02/01/2016 16:11:55.126] [default-akka.actor.default-dispatcher-2] [akka://default/user/$a/$a] Message [java.lang.Integer] from Actor[akka://default/user/$a#-1647396111] to Actor[akka://default/user/$a/$a#-198589273] was not delivered. [5] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.

まあpreStartでエラーでるとActorとしてstartしてなさそうなので気持ちは分かる気がします(;´Д`) 何か呼ばせる方法はあるのかもしれませんが、少なくともこのコードでは呼ばれないというようです。 akka難しい・・・