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

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には無いのかな。