Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between Actorref.tell and inbox.send in Akka

Tags:

scala

akka

So i have started learning Akka and trying out the examples in typesafe. So the Hello Akka app has the following code :

    import akka.actor.{ ActorRef, ActorSystem, Props, Actor, Inbox }
import scala.concurrent.duration._

case object Greet
case class WhoToGreet(who: String)
case class Greeting(message: String)

class Greeter extends Actor {
  var greeting = ""

  def receive = {
    case WhoToGreet(who) => greeting = s"hello, $who"
    case Greet           => sender ! Greeting(greeting) // Send the current greeting back to the sender
  }
}

object HelloAkkaScala extends App {

  // Create the 'helloakka' actor system
  val system = ActorSystem("helloakka")

  // Create the 'greeter' actor
  val greeter = system.actorOf(Props[Greeter], "greeter")

  // Create an "actor-in-a-box"
  val inbox = Inbox.create(system)

  // Tell the 'greeter' to change its 'greeting' message
  greeter.tell(WhoToGreet("akka"), ActorRef.noSender)

  // Ask the 'greeter for the latest 'greeting'
  // Reply should go to the "actor-in-a-box"
  inbox.send(greeter, Greet)

  // Wait 5 seconds for the reply with the 'greeting' message
  val Greeting(message1) = inbox.receive(5.seconds)
  println(s"Greeting: $message1")

  // Change the greeting and ask for it again
  greeter.tell(WhoToGreet("typesafe"), ActorRef.noSender)
  inbox.send(greeter, Greet)
  val Greeting(message2) = inbox.receive(5.seconds)
  println(s"Greeting: $message2")

  val greetPrinter = system.actorOf(Props[GreetPrinter])
  // after zero seconds, send a Greet message every second to the greeter with a sender of the greetPrinter
  system.scheduler.schedule(0.seconds, 1.second, greeter, Greet)(system.dispatcher, greetPrinter)

}

// prints a greeting
class GreetPrinter extends Actor {
  def receive = {
    case Greeting(message) => println(message)
  }
}

Now i am stuck in understanding what is the difference between ,

greeter.tell(WhoToGreet("akka"), ActorRef.noSender)

and

inbox.send(greeter, Greet)

From my understanding the actor starts its own thread at the end of the

val inbox = Inbox.create(system)

Can someone please explain what exactly does the Actorref.tell do and then what is exactly achieved by the Inbox.send line.

like image 246
Som Bhattacharyya Avatar asked Dec 09 '14 14:12

Som Bhattacharyya


People also ask

What is ActorRef in Akka?

ActorRefFactory, an interface which is implemented by ActorSystem and akka. actor. ActorContext. This means actors can be created top-level in the ActorSystem or as children of an existing actor, but only from within that actor. ActorRefs can be freely shared among actors by message passing.

What is mailbox in Akka?

Mailboxes are part of core Akka, which means that they are part of the akka-actor dependency. This page describes how to use mailboxes with akka-actor-typed , which has dependency: sbt. val AkkaVersion = "2.6. 19" libraryDependencies += "com.

What is Akka protocol?

Interacting with an Actor in Akka is done through an ActorRef[T] where T is the type of messages the actor accepts, also known as the “protocol”. This ensures that only the right kind of messages can be sent to an actor and also that no one else but the Actor itself can access the Actor instance internals.


1 Answers

The purpose of tell, also represented as ! is to send a message to an actor. As actors communicate via message passing, tell is the mechanism used to support that message passing. It is asynchronous to the caller, so that once the caller calls tell, they are decoupled from the receiving and processing of that message by the target actor instance. In this particular example, the code is using tell to cause the greeter actor to update its internal state. As this interaction does not result in a response of any kind (the receiving actor is not sending a message back to the sender in response to this request), tell alone is sufficient here.

For getting a greeting response from the greeter, the interaction is slightly different. In this interaction, the sender is expecting a response message. This type of request/response interaction can be handed via ask (i.e. ?) in which the caller gets a Future back that will be completed when the receiver replies but ask was not used here. In this example, the coder got the request/response semantic by using an Inbox instead which can behave as an actor and it eliminates the need for futures. The inbox must look like an ActorRef to the receiver allowing it to route a response back to it with the following line:

sender ! Greeting(greeting)

The sender() method returns the ActorRef of whoever sent in the message being currently processed. The Inbox must be able to represent itself as an ActorRef for this to work. But as I said earlier, you also could have used ask here to get the request/response interaction working. I think it's just a matter of choice. The bottom line is that tell is used for the fire and forget interaction model and the inbox (or another actor or ask) can be used when a request/response semantic is needed.

like image 68
cmbaxter Avatar answered Sep 28 '22 09:09

cmbaxter