LoginSignup
3
1

More than 5 years have passed since last update.

akkaの子actorが死んだ時に親actorも巻き込まれて死ぬか

Posted at

TL;DR

akkaにErlangのLinkのような機構が無いか探している。
akkaの子actorが死んだ時に親actorも巻き込まれて死ぬか確認した。

テストケース

  • 子actorへのwatch無し
    • poison
    • stop
    • exception
  • 子actorへのwattch有り
    • poison
    • stop
    • exception

code

package.scala
package net.wrap_trap.akka_samples.monitor

import akka.actor._

object Monitor {
  def main(args: Array[String]): Unit = {
    val superVisor = ActorSystem("test").actorOf(Props[Supervisor])
    superVisor ! args
  }
}
Supervisor.scala
package net.wrap_trap.akka_samples.monitor

import akka.actor.{ActorRef, Actor, Terminated, Props}

class Supervisor extends Actor {

  var parent: Option[ActorRef] = None

  override def preStart(): Unit = {
    parent = Option(context.actorOf(Props[Parent]))
  }

  def receive = {
    case Terminated(p) => {
      println("terminated: " + p)
    }
    case args: Array[String] => {
      val p = parent.get
      context.watch(p)
      p ! args
    }
  }
}
Parent.scala
package net.wrap_trap.akka_samples.monitor

import akka.actor.{ActorRef, Actor, Terminated, Props}

class Parent extends Actor {

  var child: Option[ActorRef] = None

  override def preStart(): Unit = {
    child = Option(context.actorOf(Props[Child]))
  }

  def receive = {
    case Terminated(c) => {
      println("terminated: " + c)
    }
    case args: Array[String] => {
      val c = child.get 
      if(args.length > 1 && args(1) == "1") {
        context.watch(c)
        println("start to watch: " + child)
      }
      c ! args(0)
    }
  }
}
Child.scala
package net.wrap_trap.akka_samples.monitor

import akka.actor.{ActorRef, Actor, PoisonPill}

class Child extends Actor {
  def receive = {
    case "poison"  => {
      println("message received: poison")
      self ! PoisonPill
    }
    case "stop" => {
      println("message received: stop")
      context.stop(self)
    }
    case "exception" => throw new RuntimeException("error")
  }
}

実行

子actorへのwatch無し

  • poison
masayuki@masayuki-ubuntu:~/git/akka-samples$ sbt "run-main net.wrap_trap.akka_samples.monitor.Monitor poison 0"
[info] Loading global plugins from /home/masayuki/.sbt/0.13/plugins
[info] Loading project definition from /home/masayuki/git/akka-samples/project
[info] Set current project to akka-samples (in build file:/home/masayuki/git/akka-samples/)
[info] Running net.wrap_trap.akka_samples.monitor.Monitor poison 0
message received: poison
  • stop
^Cmasayuki@masayuki-ubuntu:~/git/akka-samples$ sbt "run-main net.wrap_trap.akka_samples.monitor.Monitor stop 0"
[info] Loading global plugins from /home/masayuki/.sbt/0.13/plugins
[info] Loading project definition from /home/masayuki/git/akka-samples/project
[info] Set current project to akka-samples (in build file:/home/masayuki/git/akka-samples/)
[info] Running net.wrap_trap.akka_samples.monitor.Monitor stop 0
message received: stop
  • exception
^Cmasayuki@masayuki-ubuntu:~/git/akka-samples$ sbt "run-main net.wrap_trap.akka_samples.monitor.Monitor exception 0"
[info] Loading global plugins from /home/masayuki/.sbt/0.13/plugins
[info] Loading project definition from /home/masayuki/git/akka-samples/project
[info] Set current project to akka-samples (in build file:/home/masayuki/git/akka-samples/)
[info] Running net.wrap_trap.akka_samples.monitor.Monitor exception 0
[ERROR] [02/06/2017 02:55:37.660] [test-akka.actor.default-dispatcher-5] [akka://test/user/$a/$a/$a] error
java.lang.RuntimeException: error
    at net.wrap_trap.akka_samples.monitor.Child$$anonfun$receive$1.applyOrElse(Child.scala:15)
    at akka.actor.Actor$class.aroundReceive(Actor.scala:480)
    at net.wrap_trap.akka_samples.monitor.Child.aroundReceive(Child.scala:5)
    at akka.actor.ActorCell.receiveMessage(ActorCell.scala:526)
    at akka.actor.ActorCell.invoke(ActorCell.scala:495)
    at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:257)
    at akka.dispatch.Mailbox.run(Mailbox.scala:224)
    at akka.dispatch.Mailbox.exec(Mailbox.scala:234)
    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)

子actorへのwatch有り

  • poison
^Cmasayuki@masayuki-ubuntu:~/git/akka-samples$ sbt "run-main net.wrap_trap.akka_samples.monitor.Monitor poison 1"
[info] Loading global plugins from /home/masayuki/.sbt/0.13/plugins
[info] Loading project definition from /home/masayuki/git/akka-samples/project
[info] Set current project to akka-samples (in build file:/home/masayuki/git/akka-samples/)
[info] Running net.wrap_trap.akka_samples.monitor.Monitor poison 1
start to watch: Some(Actor[akka://test/user/$a/$a/$a#1037068608])
message received: poison
terminated: Actor[akka://test/user/$a/$a/$a#1037068608]
  • stop
^Cmasayuki@masayuki-ubuntu:~/git/akka-samples$ sbt "run-main net.wrap_trap.akka_samples.monitor.Monitor stop 1"
[info] Loading global plugins from /home/masayuki/.sbt/0.13/plugins
[info] Loading project definition from /home/masayuki/git/akka-samples/project
[info] Set current project to akka-samples (in build file:/home/masayuki/git/akka-samples/)
[info] Running net.wrap_trap.akka_samples.monitor.Monitor stop 1
start to watch: Some(Actor[akka://test/user/$a/$a/$a#1039911163])
message received: stop
terminated: Actor[akka://test/user/$a/$a/$a#1039911163]
  • exception
^Cmasayuki@masayuki-ubuntu:~/git/akka-samples$ sbt "run-main net.wrap_trap.akka_samples.monitor.Monitor exception 1"
[info] Loading global plugins from /home/masayuki/.sbt/0.13/plugins
[info] Loading project definition from /home/masayuki/git/akka-samples/project
[info] Set current project to akka-samples (in build file:/home/masayuki/git/akka-samples/)
[info] Running net.wrap_trap.akka_samples.monitor.Monitor exception 1
start to watch: Some(Actor[akka://test/user/$a/$a/$a#-1810233518])
[ERROR] [02/06/2017 02:56:10.867] [test-akka.actor.default-dispatcher-7] [akka://test/user/$a/$a/$a] error
java.lang.RuntimeException: error
    at net.wrap_trap.akka_samples.monitor.Child$$anonfun$receive$1.applyOrElse(Child.scala:15)
    at akka.actor.Actor$class.aroundReceive(Actor.scala:480)
    at net.wrap_trap.akka_samples.monitor.Child.aroundReceive(Child.scala:5)
    at akka.actor.ActorCell.receiveMessage(ActorCell.scala:526)
    at akka.actor.ActorCell.invoke(ActorCell.scala:495)
    at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:257)
    at akka.dispatch.Mailbox.run(Mailbox.scala:224)
    at akka.dispatch.Mailbox.exec(Mailbox.scala:234)
    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)

まとめ

子actorを作っただけでは、子actorは死んでも親actorは死なない。
ErlangのLinkのように片側が死んだらLink先も死ぬ、という機構はakkaには無いのかな。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1