Chaining actors together

325 views
Skip to first unread message

Tomáš Heřman

unread,
Dec 2, 2011, 7:01:09 PM12/2/11
to akka...@googlegroups.com
Hello friends,
This may be a stupid question, but how does one chain actors together without too much blocking? Consider the following code scenario:

Lets have actor 'Last' that returns some value. Lets have actor 'Proxy' that sends message to Last, gets result from it, does something with it and sends it to actor 'First'. Actor first just initiates the whole process, by sending message to Proxy. How would one go about doing that? I tried following:

class Last extends Actor { def receive = {case _ => "win"} }

class Proxy extends Actor { 
  val last = Actor.actorOf[Last].start()
  def receive = { case x => (last ? x).onComplete { x => self.reply(x.get.asInstanceOf[String].toUpperCase) } }
}

class First extends Actor { 
  val proxy = Actor.actorOf[Proxy].start()
  def receive = { case x => println((proxy ? x).get) }
}

val f = Actor.actorOf[First].start()
f ! "hola"

But this doesn't seem to work. There is a timeout error. Is there a better solution? Thanks for any help!

Peter Vlugter

unread,
Dec 2, 2011, 10:29:18 PM12/2/11
to akka...@googlegroups.com
Hi Tomáš,

On 3/12/2011, at 11:01 AM, Tomáš Heřman wrote:

> Hello friends,
> This may be a stupid question, but how does one chain actors together without too much blocking? Consider the following code scenario:
>
> Lets have actor 'Last' that returns some value. Lets have actor 'Proxy' that sends message to Last, gets result from it, does something with it and sends it to actor 'First'. Actor first just initiates the whole process, by sending message to Proxy. How would one go about doing that? I tried following:
>
> class Last extends Actor { def receive = {case _ => "win"} }

The Last actor is not replying, so the query in the Proxy actor will always time out.

> class Proxy extends Actor {
> val last = Actor.actorOf[Last].start()
> def receive = { case x => (last ? x).onComplete { x => self.reply(x.get.asInstanceOf[String].toUpperCase) } }
> }

In this part, using self.reply won't work as the onComplete callback is not run in the same sender scope as the original message. The callback is scheduled elsewhere. You can capture the reply channel, so doing something like this in Proxy should work as expected:

def receive = {
case x =>

val replyTo = self.channel
(last ? x) onResult { case s: String => replyTo ! s.toUpperCase }
}

In terms of avoiding blocking, the blocking occurs when future.get is called. So you could put your final println in a callback as well to make things async.

Alternatively, you can write the same example using only tell/! to send messages. There's more than one way to do this. One way would be to encode the request-reply chain in the messages. Another would be to create one-off actors to handle the return path.

Peter

Tomáš Heřman

unread,
Dec 3, 2011, 3:49:21 AM12/3/11
to akka...@googlegroups.com
Hi Peter, thanks a lot! 
This does exactly what i wanted to do! So silly of me to forget the replay! :( Also i was trying to capture self.sender in the Proxy actor but that didn't work, the way you did it works fine. It's good to know that you can just bang message to an channel and it does the same thing as self.reply!
Thanks a lot again, i wasted like 3 hours on this yesterday :)
Tomas

Peter Vlugter

unread,
Dec 3, 2011, 6:27:58 AM12/3/11
to akka...@googlegroups.com

On 3/12/2011, at 7:49 PM, Tomáš Heřman wrote:

> Hi Peter, thanks a lot!
> This does exactly what i wanted to do!

Awesome, good to hear!

> So silly of me to forget the replay! :( Also i was trying to capture self.sender in the Proxy actor but that didn't work, the way you did it works fine. It's good to know that you can just bang message to an channel and it does the same thing as self.reply!

Yes, channel is the one to use as it abstracts over both actor senders and futures. Futures are used with ask. This has been reworked for 2.0 so that there is only a sender actor ref to reply to (or capture) for both tell and ask.

Reply all
Reply to author
Forward
0 new messages