Posted at

[Scala Actor]Askの待ち人

More than 3 years have passed since last update.

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

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