[Scala Actor]Askの待ち人

ちょっとハマったのでメモ…

akka.pattern.ask で待ってくれるActorは別人であった…

#askのお試し

例えで、一定時間ごとに挨拶してくれるActorを作ってみた。

```scala:TestActors.scala
import akka.actor.{ ActorRef, ActorLogging, Actor}
import akka.util.Timeout
import scala.concurrent.Await
import scala.concurrent.duration._
import akka.pattern.ask
import scala.collection.mutable.ListBuffer

class HelloActor extends Actor with ActorLogging{
  val connectionList = ListBuffer[ActorRef]()
  val system = context.system
  implicit val executionContext = system.dispatcher

  system.scheduler.schedule(1 seconds, 2 seconds, self, Update )
  override def receive = {
    case Connect =>{
      connectionList += sender
      sender ! OK
    }
    case Update => {
      connectionList.foreach( _ ! Hello )
    }
  }
}

class ConnectActor extends Actor with ActorLogging{
  val duration = 5 second
  var server :ActorRef = _
  implicit val timeout = Timeout(3 seconds)

  override def receive = {
    case SetRef(server) => {
      this.server = server
      Await.result(server ? Connect , duration) match { // ask here!
        case OK => log.info("init OK!")
      }
    }
    case Hello =>{
      log.info("Hello")
    }
  }
}

case object Connect
case object Hello
case object OK
case object Update
case class SetRef(ref:ActorRef)
```

```scala:Main.scala
object Main {
  def main(args: Array[String]): Unit = {
    val system = ActorSystem.create("test-system")

    val server = system.actorOf(Props[HelloActor])
    val actor1 = system.actorOf(Props[ConnectActor],name = "actor1")
    actor1 ! SetRef(server)
    val actor2 = system.actorOf(Props[ConnectActor],name = "actor2")
    actor2 ! SetRef(server)
  }
}
```

実行結果はこちら↓
>[INFO] [10/08/2015 16:24:27.805] [test-system-akka.actor.default-dispatcher-2] [akka://test-system/user/actor2] init OK!
>[INFO] [10/08/2015 16:24:27.805] [test-system-akka.actor.default-dispatcher-4] [akka://test-system/user/actor1] init OK!
>[INFO] [10/08/2015 16:24:28.814] [test-system-akka.actor.default-dispatcher-4] [akka://test-system/deadLetters] Message [chat2.Hello$] from Actor[akka://test-system/user/$a#1304157529] to Actor[akka://test-system/deadLetters] 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] [10/08/2015 16:24:28.814] [test-system-akka.actor.default-dispatcher-4] [akka://test-system/deadLetters] Message [chat2.Hello$] from Actor[akka://test-system/user/$a#1304157529] to Actor[akka://test-system/deadLetters] 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'.


**違うActor**に送っているみたいだ…なぜ?

実は`server ? Connect`で待ってるActorは違う人だったのだ…


#tellのお試し

試しに**!(tell)**に変えてみた

```scala:TestActors.scala
import akka.actor.{ ActorRef, ActorLogging, Actor}
import akka.util.Timeout
import scala.concurrent.duration._
import scala.collection.mutable.ListBuffer


class HelloActor extends Actor with ActorLogging{
  val connectionList = ListBuffer[ActorRef]()
  val system = context.system
  implicit val executionContext = system.dispatcher

  system.scheduler.schedule(1 seconds, 2 seconds, self, Update )
  override def receive = {
    case Connect =>{
      connectionList += sender
      sender ! OK
    }
    case Update => {
      connectionList.foreach( _ ! Hello )
    }
  }
}

class ConnectActor extends Actor with ActorLogging{
  val duration = 5 second
  var server :ActorRef = _
  implicit val timeout = Timeout(3 seconds)

  override def receive = {
    case SetRef(server) => {
      this.server = server
      server ! Connect   // tell here!
    }
    case Hello =>{
      log.info("Hello")
    }
    case OK =>{
      log.info("init OK!")
    }
  }
}

case object Connect
case object Hello
case object OK
case object Update
case class SetRef(ref:ActorRef)
```

実行結果はこちら↓
>[INFO] [10/08/2015 23:25:37.830] [test-system-akka.actor.default-dispatcher-3] [akka://test-system/user/actor2] init OK!
>[INFO] [10/08/2015 23:25:37.830] [test-system-akka.actor.default-dispatcher-5] [akka://test-system/user/actor1] init OK!
>[INFO] [10/08/2015 23:25:38.847] [test-system-akka.actor.default-dispatcher-5] [akka://test-system/user/actor1] Hello
>[INFO] [10/08/2015 23:25:38.847] [test-system-akka.actor.default-dispatcher-6] [akka://test-system/user/actor2] Hello
>[INFO] [10/08/2015 23:25:40.834] [test-system-akka.actor.default-dispatcher-3] [akka://test-system/user/actor1] Hello
>[INFO] [10/08/2015 23:25:40.834] [test-system-akka.actor.default-dispatcher-5] [akka://test-system/user/actor2] Hello

どうやら挨拶されているようだ。

#まとめ
- Askを使うとsenderが**akka://test-system/user/$a#1304157529**に変わっていた（見た感じ適当な変数）…
- Tellではsenderは正しかった
- Askで送信元伝えたい時どうしたらいいんやろ？

以上、いつも引っかかるのでメモりました。
間違いあればご指摘お願いしますm(_ _)m