Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
super.preRestartの位置でライフサイクルの呼ばれる順番が変わる
import akka.actor.SupervisorStrategy.{Resume, Restart, Stop}
import akka.actor._
object PreRestart extends App {
val system = ActorSystem()
try {
val actor = system.actorOf(Props[SupervisorExceptionActor2])
actor ! 1
actor ! 2
actor ! 3
Thread.sleep(5000)
} finally {
system.shutdown()
}
}
class SupervisorExceptionActor2 extends Actor {
val actor = context.actorOf(Props[KilledActor2])
override def supervisorStrategy = OneForOneStrategy() {
case _: ActorInitializationException Stop
case _: ActorKilledException Stop
case _: DeathPactException Stop
case _: Exception Restart
}
def receive = {
case Terminated(ref: ActorRef) => println(ref)
case x => actor forward x
}
}
class KilledActor2 extends Actor {
println("primary constructor")
override def preStart(): Unit = {
super.preStart()
println("preStart")
}
override def postStop(): Unit = {
super.postStop()
println("postStop")
}
override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
/*
* super.preRestart内でpostStopを呼ぶため、super.preRestartをoverrideの先頭で呼ぶか、最後で呼ぶかによって処理順が関わる(中間に書いてpostStop前後の処理を書くことも可能)
* primary constructor -> preStart -> before preRestart -> postStop -> after preRestart -> primary constructor -> preStart -> postRestart
*
*
* これ以外にもsuper.postRestartでpreStartを呼ぶなどしているためオーバーライド時に呼び忘れると復帰のときだけ呼ばれない現象がおこるため注意(これを利用して、本当に最初の一回だけ初期化するような処理を書くこともできる)
* 同様にsuper.preRestartでpostStopが呼ばれているため呼び忘れるとrestart時にpostStopが呼ばれなくなる。(これを利用して本当に最後だけ終了処理を行いたいという処理を書くこともできる)
*/
println("before preRestart")
super.preRestart(reason, message)
println("after preRestart")
}
override def postRestart(reason: Throwable): Unit = {
super.postRestart(reason)
println("postRestart")
}
def receive: Receive = {
case 2 => throw new RuntimeException("")
case x => println(x)
}
}
import akka.actor.SupervisorStrategy.{Restart, Resume, Stop}
import akka.actor._
object PreRestart extends App {
val system = ActorSystem()
try {
val actor = system.actorOf(Props[ExceptionSupervisor])
actor ! 1
actor ! 2
actor ! 3
Thread.sleep(5000)
} finally {
system.shutdown()
}
}
class ExceptionSupervisor extends Actor {
val actor = context.actorOf(Props[RestartingActor])
override def supervisorStrategy = OneForOneStrategy() {
case _: ActorInitializationException Stop
case _: ActorKilledException Stop
case _: DeathPactException Stop
case _: Exception Restart
}
def receive = {
case Terminated(ref: ActorRef) => println(ref)
case x => actor forward x
}
}
/**
* 各ライフサイクルの最初でsuperを呼ぶことを強制する版
* [old instance] 例外発生 -> postStop -> preRestart ->
* [new instance] primary constructor -> preStart -> postRestart
*
* 完全版:
* [old instance] 例外発生 -> before preRestart -> before postStop -> after postStop -> after preRestart ->
* [new instance] primary constructor -> before postRestart -> before preStart -> after preStart -> after postRestart
*
* @see [[http://doc.akka.io/docs/akka/current/general/supervision.html#What_Restarting_Means]]
*/
class RestartingActor extends Actor {
println(s"primary constructor")
override def preStart(): Unit = {
println(s"before preStart")
super.preStart()
println(s"after preStart")
}
override def postStop(): Unit = {
println(s"before postStop")
super.postStop()
println(s"after postStop")
}
override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
println(s"before preRestart")
super.preRestart(reason, message)
println(s"after preRestart")
}
override def postRestart(reason: Throwable): Unit = {
println(s"before postRestart")
super.postRestart(reason)
println(s"after postRestart")
}
def receive: Receive = {
case 2 => throw new RuntimeException("")
case x => println(x)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment