Using that `id` is *safe*. Let me maybe explain by example why closing over sender is not safe when it seems as if it’s the same thing “from the outside"…
So `sender()` is not a value, it’s a `def` which has an underlying `var`. That var is changed each time a message arrives to the Actor, to point to the sender of that message. This leads to the problem why closing over sender is not safe. Two hints here: 1) you can write `sender()` instead of `sender` to remind yourself about “oh man, but this is a method, not a value!” 2) we want to remove sender all together from akka 3 - but that’s waaay ahead of us, but we know we’ll want to remove it as it’s unsafe. So, back to the example: I get a message “a", sender is A, I start my future to process “a", I get another message “b”, sender is set to B, future triggers and accesses sender(), sender returns B. So that’s the problem scenario. Whereas closing over any `val` is completely safe, because noone will swap things in it (id is a val in your case - as I assume CalculateFor is a case class). Hope this explains things in more depth! Happy hakking! — konrad On 21 November 2014 at 00:55:12, David ([email protected]) wrote: Thanks very much for your reply, Konrad. Could you tell me if the state of "id" is preserved when the future returns? I would assume "No", since I don't see how I'm "freezing" the state of "id" when the future returns. class ConfirmationCalc( dbClient:ActorRef ) extends Actor{ def receive:Receive = { case CalculateFor( id ) => val orig_sender = sender val f = ( dbClient ? ReadCommand( id ) )mapTo[Option[String]] f.onComplete{ case Success( result ) => result match { case Some( click ) => println( "Success: calculate using {}", click ) //orig_sender ! calculate( click ) orig_sender ! calculate( click, id ) // <--- I am now using a previously received "id" case None => println( "Got Empty" ) case Failure( e ) => e.printStackTrace() } case _ => } def calculate( click:String, id:String ):BigDecimal = {...} } On Wednesday, November 19, 2014 12:13:06 PM UTC-5, David wrote: Hi, I am coming from Java and am new to Scala and Akka and asynchronous programming in general. I have a threadsafe, async db client like this: class Client{ ... def get(key: K): Future[Option[V]] = ... } I would like embed this functionality in an Actor. My initial thoughts are something like this: class MyDBClient extends Actor{ val client = Client( "102.98.2.1:3000" ) def receive = { case ReadCommand( id ) => val orig_sender = sender val f:Future[Option[String]] = client.get( id ) f pipeTo orig_sender case _ => } } And I would have a pool of these actors like this: class DBManager extends Actor{ var router = { val routees = Vector.fill(5) { val r = context.actorOf( Props[MyDBClient] ) context watch r ActorRefRoutee(r) } Router( RoundRobinRoutingLogic(), routees ) } def receive = { case DoSomething( id ) => { router.route( ReadCommand( id ), sender() ) } case _ => } I have an actor which requires the database parameter to calculate a click value: class ConfirmationCalc( dbClient:ActorRef ) extends Actor{ def receive:Receive = { case CalculateFor( id ) => val orig_sender = sender val f = ( dbClient ? ReadCommand( id ) )mapTo[Option[String]] f.onComplete{ case Success( result ) => result match { case Some( click ) => println( "Success: calculate using {}", click ) orig_sender ! calculate( click ) case None => println( "Got Empty" ) case Failure( e ) => e.printStackTrace() } case _ => } def calculate( click:String ):BigDecimal = {...} } My questions are: 1. Is this the "correct" pooling architecture - that is, having a central router that delegates to a number of dbactors which have a "connection" to the database? Are there other architectures given that each DB Client class controls its own connections? 2. ConfirmationCalc actor will be furiously processing "CalculateFor" messages. I understand that the future will eventually complete with either Success or Failure or timeout. My newbie question is after I process my first message in ConfirmationCalc and send the async request to the dbclient, ConfirmationCalc may be processing its second message when the future completes. In my newbie opinion, this code would have concurrency issues since I would be getting the first message's db results when processing the second message and send back the first results to the sender who is expecting the second results. I have read about "Cameo" patterns that encapsulate state within actors but "ask" does not allow me to send the cameo in the ask. What code would address this issue ( if it is one at all ?) 3. This is related to my previous question. In asynchronous systems, we might have ActorA asking ActorB asking ActorC asking ActorD. I find it a bit mind bending how each actor in the chain is going to maintain state of futures. Future A may have onCompletions triggered thousands of times while it is processing a message. Is there example code somewhere that addresses this? Thanks David -- >>>>>>>>>> Read the docs: http://akka.io/docs/ >>>>>>>>>> Check the FAQ: >>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html >>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user --- You received this message because you are subscribed to the Google Groups "Akka User List" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/akka-user. For more options, visit https://groups.google.com/d/optout. -- Konrad 'ktoso' Malawski hAkker @ typesafe http://akka.io -- >>>>>>>>>> Read the docs: http://akka.io/docs/ >>>>>>>>>> Check the FAQ: >>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html >>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user --- You received this message because you are subscribed to the Google Groups "Akka User List" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/akka-user. For more options, visit https://groups.google.com/d/optout.
