LoginSignup
5
4

More than 5 years have passed since last update.

[Scala Actor]Askの待ち人

Posted at

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

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

askのお試し

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

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)
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)に変えてみた

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

5
4
2

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
5
4