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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With