Migrating systems which use multiple nested reacts to effect initialization

44 views
Skip to first unread message

oxbow_lakes

unread,
May 25, 2012, 12:34:35 PM5/25/12
to akka...@googlegroups.com
More from me I'm afraid :-(

Another common pattern for me in scala's actors is to do this. The situation is that my actor has three dependencies from which it requires data from in order to go into the main process loop; it makes requests of all 3 and then uses nested reacts to ensure it can only hit the main loop when everything has arrived:

class MyActor(dep1: D1, dep2: D2, dep3: D3) {
  def act() {
     dep1 ! Request1
     dep2 ! Request2
     dep3 ! Request3
     react {
       case Reply1(r1) =>
         react {
           case Reply2(r2) =>
             react {
               case Reply3(r3) =>
                 //main loop here

Now, I cannot do this in Akka and neither can I use "become", because I don't know which one of the replies will get sent first (and I don't want to wait for the first reply to send the second request). Using Akka, I can think of doing the following:

class MyActor(dep1: ActorRef, dep2:  ActorRef , dep3: ActorRef) {
  override def preStart() {
    (dep1 ? Request1) zip (dep2 ? Request2) zip (dep3 ? Request3) pipeTo self
  }
  def receive = { case ((Reply1(r1), Reply2(r2)), Reply3(r3)) => become(looping(r1, r2, r3)) }
  def looping(r1: R1, r2: R2, r3: R3): Receive =  { //main loop }
}

Is this a valid mechanism for replacing the behaviour? Is there a better one? (Note - I am doing migrations, so want to avoid as much as possible major application re-writing. I'm trying to determine some mechanical rules for replacing a scala system with an Akka one)

Chris



√iktor Ҡlang

unread,
May 25, 2012, 12:44:40 PM5/25/12
to akka...@googlegroups.com

Was answered this week on the ML, see archives.
Thx.
V

--
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To view this discussion on the web visit https://groups.google.com/d/msg/akka-user/-/d_VotR8vLhkJ.
To post to this group, send email to akka...@googlegroups.com.
To unsubscribe from this group, send email to akka-user+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/akka-user?hl=en.

Samuel Tardieu

unread,
May 25, 2012, 12:45:59 PM5/25/12
to akka...@googlegroups.com
You need to break the sequencing: you do not need to receive Reply1
before Reply2 and before Reply3.

Let's rephrase what you want: you want to have received all three
results before doing anything (your main loop). If you had used Future
instances to hold the replies, then you want in fact to do something
when all of them are fullfilled.

Let's assume you work with Future1, Future2 and Future3 (instead of
waiting for Reply1..3), then you can do something like:

for (r1 <- Future1; r2 <- Future2; r3 <- Future3) {
… // main loop here
}

If your action *must* be performed by your actor, instead of the
composition context used by the futures, then you can do something like:

val r13 = for (r1 <- Future1; r2 <- Future2; r3 <- Future3) yield (r1, r2, r3)
r13 pipeTo self

using the "pipeTo" pattern.

Now, to get futures instead of Reply(…), you may want to look at the
"ask" pattern which gives you a future resolving to the reply you want.

Sam

oxbow_lakes

unread,
May 25, 2012, 12:48:23 PM5/25/12
to akka...@googlegroups.com
Isn't flatMap on Akka's futures non-concurrent? That is; the second request is actually waiting for the first to complete in this example

Other than that, isn't this precisely what I just laid out?

Chris

oxbow_lakes

unread,
May 25, 2012, 12:52:24 PM5/25/12
to akka...@googlegroups.com
I asked earlier in the week about piping the results of a future to an actor; is that what you mean? (Was not the same question). I can't find anything else on rested reacts

C
To unsubscribe from this group, send email to akka-user+unsubscribe@googlegroups.com.

Samuel Tardieu

unread,
May 25, 2012, 12:52:27 PM5/25/12
to akka...@googlegroups.com
On 25/05, oxbow_lakes wrote:

| Isn't flatMap on Akka's futures non-concurrent? That is; the second request
| is actually waiting for the first to complete in this example

Yes, when I started this answer, I was planning on directing you to
sequence and missed your use of zip, I read it too fast :)

Jonas Boner

unread,
May 25, 2012, 1:36:35 PM5/25/12
to akka...@googlegroups.com

Does this help?
http://doc.akka.io/api/akka/2.0/akka/actor/Stash.html

On May 25, 2012 6:34 PM, "oxbow_lakes" <oxbow...@gmail.com> wrote:
--
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To view this discussion on the web visit https://groups.google.com/d/msg/akka-user/-/d_VotR8vLhkJ.
To post to this group, send email to akka...@googlegroups.com.
To unsubscribe from this group, send email to akka-user+...@googlegroups.com.

oxbow_lakes

unread,
May 26, 2012, 5:56:53 AM5/26/12
to akka...@googlegroups.com
It may do; I can't see exactly how I'd use it though. In my case, there's no "done" message; there is simply the fact that all 3 initialization replies are received. I'm afraid the usage example in the documentation doesn't really explain what it going on

Chris
To unsubscribe from this group, send email to akka-user+unsubscribe@googlegroups.com.

oxbow_lakes

unread,
May 29, 2012, 10:34:32 AM5/29/12
to akka...@googlegroups.com
The answer is, "yes" - to some extent; I could do this (using scalaz), or something like it

object state {
  var maybeR1 = none[R1]
  var maybeR2 = none[R2] 
  var maybeR3 = none[R3] 
  def invokeIfReady(fn: (R1, R2, R3) => Unit) = (maybeR1 <***> (maybeR2, maybeR3) foreach fn
}
def tryLoop() {
  val transition = (r1: R1, r2: R2, r3: R3) => { unstashAll(); context become looping(r1, r2, r3) }
  state invokeIfReady transition 
}
def receive {
  case Reply(r1) => state.maybeR1 = some(r1); tryLoop()
  case Reply(r2) => state.maybeR2 = some(r2); tryLoop()
  case Reply(r3) => state.maybeR3 = some(r3); tryLoop()
  case other => stash()
}
def looping(r1: R1, r2: R2, r3: R3) : Receive = { /* main loop here */ }
Reply all
Reply to author
Forward
0 new messages