On Fri, Mar 21, 2014 at 5:34 PM, Konrad Malawski <[email protected]> wrote:
> I assumed the commented code was in the spirit of "oh, and the commented > stuff didn't work out for me, plz help." :-) > But the quoted code should work? > > -- > Konrad Malawski > geecon.org / java.pl / krakowscala.pl / gdgkrakow.pl > > From: √iktor Ҡlang [email protected] > Reply: [email protected] [email protected] > Date: 21 March 2014 at 16:29:12 > To: Akka User List [email protected] > Cc: glidester [email protected] > > Subject: Re: [akka-user] Chaining actor ask calls > > How is that possible, that code was commented out? > > > On Fri, Mar 21, 2014 at 5:22 PM, glidester <[email protected]> wrote: > >> Yes that was it! Thank you so much Konrad. >> >> >> >> On Friday, March 21, 2014 4:14:28 PM UTC, Konrad Malawski wrote: >> >>> The reason might be that you're calling sender() inside the Future's >>> map. The sender() call is only valid *within* the actor itself, and >>> this construction (f map { sender ! ... }) might run in annother thread >>> - making the sender not what you might expect it to be - thus, the reply >>> goes to "someone" and not the intended sender (well, deadLetters probably). >>> >>> it should "work" in { >>> // given >>> val he = system.actorOf(Props(new Actor { >>> >>> import context.dispatcher >>> implicit val timeout = Timeout(2.seconds) >>> >>> def receive = { >>> case x => >>> val respondTo = sender() // "freeze" the sender value >>> >>> Future { >>> Thread.sleep(500) >>> >>> // wrong >>> // sender() ! x + "!" // the test will timeout, because reply >>> goes to deadLetters! >>> >>> // good >>> respondTo ! x + "!" // good; the right actor gets the response >>> } >>> } >>> })) >>> >>> // when >>> he ! "hi" >>> >>> // then >>> expectMsg("hi!") >>> } >>> >>> There's a nice post from Helena Edelson explaining problems explaining >>> it a bit more: http://helenaedelson.com/?p=879 and the sender()'s scala >>> docs mention this: >>> >>> * WARNING: Only valid within the Actor itself, so do not close over it >>> and >>> * publish it to other threads! >>> */ >>> final def sender(): ActorRef = context.sender() >>> >>> There is some ideas to make this error "not as easy to make", with >>> Scala's "spores", but that's not here yet… >>> >>> I hope this helps, cheers! >>> >>> -- >>> Konrad Malawski >>> geecon.org / java.pl / krakowscala.pl / gdgkrakow.pl >>> >>> From: glidester [email protected] >>> Reply: [email protected] [email protected] >>> Date: 21 March 2014 at 15:35:27 >>> To: [email protected] [email protected] >>> Cc: glidester [email protected] >>> >>> Subject: Re: [akka-user] Chaining actor ask calls >>> >>> Ok, so it seems people prefer tell to ask. The only reason I'm using >>> ask is that the example I'm working from >>> http://doc.akka.io/docs/akka/snapshot/scala/testing.html#Testing_the_Actor's_Behavior >>> uses >>> ask. >>> >>> I'm writing some unit tests to test my Actor 'a' calling Actor 'b'. My >>> Actor 'b' is outside my control (3rd party module) so I have to ask it. >>> I've modified my test code to 'tell' Actor 'a' but now I get Timeout >>> exceptions. I think it might have something to do with unit tests being >>> single threaded but I'm unsure. >>> >>> Here are the snippets of my code: >>> >>> case class ReadEntry(licKey: String) >>> >>> class LicenceBlackList extends Actor with ActorLogging with >>> DynamoModelObjects { >>> val dynamoActorRef = >>> Dynamo(DynamoConfig(System.getProperty("amazon.accessKey"), >>> System.getProperty("amazon.secret"), tablePrefix = "test_blacklist_", >>> endpointUrl = System.getProperty("dynamo.url", " >>> https://dynamodb.eu-west-1.amazonaws.com")), connectionCount = 3) >>> >>> def receive = { >>> case ReadEntry(licKey) => { log.info(s"ReadEntry $licKey") >>> val result: Option[BlacklistEntry] = Read(licKey).blockingExecute >>> sender ! result >>> >>> /*val dd: Future[Option[BlackListEntry]] = (Read(licKey) executeOn >>> dynamoActorRef) >>> >>> dd.map { >>> result => sender ! result //I get:- java.lang.AssertionError: >>> assertion failed: timeout (3 seconds) during expectMsg while waiting for >>> Some(BlacklistEntryImpl(TEST_KEY_1,1000,First Test Entry)) >>> }*/ >>> } >>> } >>> } >>> >>> class LicenceBlackListSpec(_system: ActorSystem) extends >>> TestKit(_system) with ImplicitSender with ShouldMatchers with FlatSpec with >>> BeforeAndAfterAll { >>> >>> def this() = this( ActorSystem("LicenceBlackListSpec") ) >>> >>> override def afterAll: Unit = { >>> system.shutdown() >>> system.awaitTermination(10.seconds) >>> } >>> >>> implicit val timeout = Timeout(10 seconds) >>> val blacklistRef = TestActorRef(Props[LicenceBlackList]) >>> >>> "An LicenceBlackList Actor" should "be able to retrieve a blacklisted >>> key" in { >>> val licenceKey="TEST_KEY_1" >>> >>> blacklistRef ! ReadEntry( licenceKey ) >>> val expected: BlacklistEntry = BlacklistEntryImpl(licenceKey, 1000 >>> ,"First Test Entry") >>> >>> expectMsg( Some(expected) ) >>> } >>> } >>> >>> When I run my test class I get: >>> [INFO] [03/21/2014 15:32:35.917] [pool-58-thread-2] >>> [akka://LicenceBlackListSpec/user/$$a] ReadEntry TEST_KEY_1 >>> [ERROR] [03/21/2014 15:32:45.933] [pool-58-thread-2] >>> [akka://LicenceBlackListSpec/user/$$a] Futures timed out after [10 seconds] >>> java.util.concurrent.TimeoutException: Futures timed out after [10 >>> seconds] >>> >>> What am I doing wrong in my tests? >>> >>> Thanks >>> >>> On Friday, March 21, 2014 12:08:19 PM UTC, Konrad Malawski wrote: >>>> >>>> Hello there, >>>> >>>> In general *always perfer tell (!) instead of ask (?)*, unless you >>>> have a compelling reason not to. It has less overhead, and I also find >>>> things nicer to model using plain actor tell's instead of ask's - which mix >>>> up styles a little bit (actors in general "fire and forget"). >>>> >>>> But let's also look at your example, because I think you may have mixed >>>> up what Future[_] gets completed when. The futures don't automatically >>>> get composed, but by chanining of reactions to a futures completion, actors >>>> can "cascade" completing their corresponding futures. >>>> >>>> In the bellow example we use ask twice. The a actor completes the >>>> fafuture, but only once the >>>> fb future completes successfuly. Completing an "ask created Future", >>>> happens when an actor replies to the message sent by ask - so in the end => >>>> b completes the fb future, which then triggers the map in a, which >>>> completes the fa future. >>>> >>>> import akka.pattern.ask >>>> >>>> val b = context.system.actorOf(Props(new Actor { >>>> def receive = { >>>> case s => sender() ! s // this response completes the `fb` future >>>> } >>>> })) >>>> >>>> val a = context.system.actorOf(Props(new Actor { >>>> def receive = { >>>> case s => >>>> val replyTo = sender() >>>> >>>> val fb = b ? (s + "!") >>>> fb map { bResponse => >>>> // this runs when the b actor replies - thus, completing the >>>> `fb` future >>>> replyTo ! bResponse // this completes the `fa` future >>>> } >>>> } >>>> })) >>>> >>>> val fa: Future[Any] = a ? "wat" // this future will be completed by the >>>> `a` actor replying to the "wat" message >>>> >>>> >>>> -- >>>> Konrad Malawski >>>> geecon.org / java.pl / krakowscala.pl / gdgkrakow.pl >>>> >>>> From: glidester [email protected] >>>> Reply: [email protected] [email protected] >>>> Date: 21 March 2014 at 11:49:05 >>>> To: [email protected] [email protected] >>>> Subject: [akka-user] Chaining actor ask calls >>>> >>>> Hi, >>>> >>>> I'm in the process of learning Akka and I wondered if anyone could >>>> clarify something for me. >>>> >>>> If I have 2 actors. I 'ask' Actor A which in turn 'asks' Actor B. >>>> >>>> This means I get returned a Future from ActorB wrapped in a Future from >>>> Actor A (correct?) >>>> >>>> Is this good practice? Should I be using "tell" instead to avoid the >>>> nested Futures? >>>> >>>> Any pointers gratefully received! >>>> >>>> G >>>> -- >>>> >>>>>>>>>> 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. >>>> >>>> -- >>> >>>>>>>>>> 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. >>> >>> -- >> >>>>>>>>>> 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. >> > > > > -- > Cheers, > √ > > *———————* > *Viktor Klang* > *Chief Architect - **Typesafe <http://www.typesafe.com/>* > > Twitter: @viktorklang > -- > >>>>>>>>>> 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. > > -- Cheers, √ *———————**Viktor Klang* *Chief Architect - **Typesafe <http://www.typesafe.com/>* Twitter: @viktorklang -- >>>>>>>>>> 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.
