scala - Akka ask returns nothing when tell is used in future -
the following code uses 2 asks , seems supposed print "this should printed in actor1 of time wont because of race condition receive method finishing". there seems race condition between 'receive' method finishing , future finishing , nothing printed. intended behavior akka? bug? trying avoid using 'ask' as possible , using 'tell' instead, it's must.
import akka.actor._ import akka.routing.smallestmailboxpool import akka.util.timeout import akka.pattern.ask import scala.concurrent.duration._ import scala.concurrent.executioncontext.implicits.global import scala.util.{failure, success} object actorsaskingstuff extends app { val system = actorsystem("abc-system") val actor1 = system.actorof(props[actor1].withrouter(smallestmailboxpool(1)), "actor1") actor1 ! 5 } class actor1 extends actor { implicit val timeout = timeout(60 seconds) val actor2: actorref = context.actorof(props[actor2].withrouter(smallestmailboxpool(1)), "actor2") override def receive: receive = { case _ => println("actor1 called") actor2 ? "hello" oncomplete { case success(a) => println(a) case failure(b) => println("failure") } } } class actor2 extends actor { implicit val timeout = timeout(6 seconds) val actor3: actorref = context.actorof(props[actor3].withrouter(smallestmailboxpool(1)), "actor3") override def receive: actor.receive = { case _ => println("actor2 called") actor3 ? "hello" map { _ => println("actor2 completed future") sender ! "this should printed in actor1 of time wont because of race condition receive method finishing" } // uncomment make work //thread.sleep(100) } } class actor3 extends actor { override def receive: actor.receive = { case _ => println("actor3 called") sender ! "i'm actor3" } }
you closing on sender when this:
actor3 ? "hello" map { _ => println("actor2 completed future") sender ! "this should printed in actor1 of time wont because of race condition receive method finishing" } at point sender have changed. in order avoid closing on sender can rewrite this:
val originator = sender() actor3 ? "hello" map { _ => println("actor2 completed future") originator ! "this should printed in actor1 of time wont because of race condition receive method finishing" } once go future based callback (like oncomplete or map example) @ point, actor thinks it's done precessing current message , moves onto next message in mailbox (if there one). when happens, sender() def returns value of var subject change return either new actorref (more messages) or nothing (deadletter) if no messages.
you can checkout post more info: sender inside future
Comments
Post a Comment