what does replyTo refer to here? - akka-actor

I am reading this Akka document, https://doc.akka.io/docs/akka/current/typed/actor-lifecycle.html#spawning-children, and this code snippet,
CompletionStage<ActorRef<HelloWorld.Greet>> greeter =
AskPattern.ask(
system,
replyTo ->
new SpawnProtocol.Spawn<>(HelloWorld.create(), "greeter", Props.empty(), replyTo),
timeout,
system.scheduler());
This is to use the Ask pattern to create a child actor. My question is about this piece,
replyTo ->
new SpawnProtocol.Spawn<>(HelloWorld.create(), "greeter", Props.empty(), replyTo),
It is a lamda representing a factory function, which takes a replyTo parameter, and returns an actor. But what is replyTo here? where does it come from and what does it refer to? Having a hard time to have a very clear picture about it.
Thanks for any help!

Finally figure this out, so let me answer my own question.
Basically, the Ask pattern produces a future that represents the reply from the actor that is being asked. In other words, we ask, and we get a future back that represents a placeholder, which will be fulfilled by the real response when it is ready.
So how does Akka know how to fulfill this future? That is where the replyTo parameter fits in. Akka actually creates a temporary actor in the actor system, the replyTo parameter is used to represent this temporary actor. When the actor being asked replies to the message it receives from an Ask, this temporary actor starts to run and it completes the future with the response replied from the actor that is being asked.
Hope this makes sense, and hope this helps someone else who has the same question. Akka is great, but I really hope they have a better documentation so we don't have to search so hard.

Related

Akka Classic Ask pattern. How does it match asks with responses?

I'm a newbie with Akka Actors, and I am learning about the Ask pattern. I am looking at the following example from alvin alexander:
class TestActor extends Actor {
def receive = {
case AskNameMessage => // respond to the "ask" request
sender ! "Fred"
case _ => println("that was unexpected")
}
}
...
val myActor = system.actorOf(Props[TestActor], name = "myActor")
// (1) this is one way to "ask" another actor
implicit val timeout = Timeout(5 seconds)
val future = myActor ? AskNameMessage
val result = Await.result(future, timeout.duration).asInstanceOf[String]
println(result)
(Yes, I know that Await.result isn't generally the best practice, but this is just a simple example.)
So from what I can tell, the only thing you need to do to implement the "askee" actor to service an Ask operation is to send a message back to the "asker" via the Tell operator, and that will be turned into a future on the "asker" side as a response to the Ask. Seems simple enough.
My question is this:
When the response comes back, how does Akka know that this particular message is the response to a certain Ask message?
In the example above, the "Fred" message doesn't contain any specific routing information that specifies that it's the response to a particular Ask operation. Does it just assume that the next message that the asker receives from that askee is the answer to the Ask? If that's the case, then what if one actor sends multiple Ask operations to the same askee? Wouldn't the responses likely get jumbled, causing random responses to be mapped to the wrong Asks?
Or, what if the asker is also receiving other types of messages from the same askee actor that are unrelated to these Ask messages? Couldn't the Asks receive response messages of the wrong type?
Just to be clear, I'm asking about Akka Classic, not Typed.
For every Ask message sent to an actor, akka creates a proxy ActorRef whose sole responsibility is to process one single message. This temp "actor" is initialized with a promise, which it needs to complete on message processing.
The source code of it is found here
but the main details are
private[akka] final class PromiseActorRef private (
val provider: ActorRefProvider,
val result: Promise[Any],
....
val alreadyCompleted = !result.tryComplete(promiseResult)
Now, it should be clear that Ask pattern is backed by independent unique actor asker for every message sent to the receiver askee.
The askee does know actor reference of the sender, or asker, of every message received via method context.sender(). Thus, it just needs to use this ActorRef to send a response back to the asker.
Finally, this all avoids any race conditions given that an actor only processes a message at a time. Thus it excludes any possibility of retrieving a "wrong" asker via method context.sender().

Akka Actors: ask pattern vs Promise

Lately I've found myself wrapping actors in classes so that I get back a little of the typesafety I lose when dealing with ActorRefs.
The problem is, at the end, that not only I need to send a specific message, I also need to cast the response to the expected result.
So I thought that I could send messages to actors that contain Promise so that they could report the result eventually.
Is that a bad idea? It looks pretty neat to me... Is typesafe and works just as good. Why hasn't anyone come with the idea? Is there anything wrong with it that I haven't noticed?
ask pattern based solution
case class GetUser(id:Long)
(actorRef ! GetUser(1l)).mapTo[User]
class UserRepoActor extends Actor{
def receive={
case GetUser(id)=>
sender() ! getUser(id)
}
...
}
Promise based solution
case class GetUser(id: Long, resp: Promise[User])
val req = GetUser(1l,Promise())
actorRef ! req
req.resp.future // No casting!!
class UserRepoActor extends Actor{
def receive={
case GetUser(id,resp)=>
response.success(getUser(id))
}
...
}
There is nothing wrong. Very close approach is used in akka typed with the only difference: a single-use ActorRef[T] is being sent instead of Promise[T]
Promises won't work in distributed actor system.
At least, without additional efforts for that.
Ask pattern is definitely better.
1) Actors are supposed to share no state and interact with the outer world via messages. Fulfilling the promise is actually a mutating shared variable
2) Passing the stateful objects into actor's creator (e.g. promise) breaks actor's lifecycle in case of restarts
So promise-based approach works in simple cases. But if you use it just like that probably you don't need such complicated stuff like akka at all?

Is passing around ActorRef to other Actors good or bad ?

I'm trying to figure out if my usage of passing Akka ActorRef around to other actors is not an anti-pattern.
I've a few actors in my system. Some are long lived (restClientRouter,publisher) and some die after that they have done the work (geoActor). The short-lived actors need to send messages to the long-lived actors and therefore need their ActorRefs.
//router for a bunch of other actors
val restClientRouter = createRouter(context.system)
//publishers messages to an output message queue
val publisher: ActorRef = context.actorOf(Props(new PublisherActor(host, channel)), name = "pub-actor")
//this actor send a message to the restClientRouter and then sends the response
//to the publisher
val geoActor = context.actorOf(Props(new GeoInferenceActor(restClientRouter, publisher)), name = "geo-inference-actor")
As you can see I'm passing the ActorRefs (restClientRouter and publisher) to the constructor of GeoInferenceActor. Is this okay or not? Is there a better way of doing this ?
There are a couple of good ways to "introduce" actor refs to actor instances that need them.
1) Create the actor with the refs it needs as constructor args (which is what you are doing)
2) Pass in the needed refs with a message after the instance is created
Your solution is perfectly acceptable, and even suggested by Roland Kuhn, the Tech Lead for Akka, in this post:
Akka actor lookup or dependency injection
It is perfectly valid, as stated in the Akka API documentation:
ActorRefs can be freely shared among actors by message passing.
In your case, you are passing them to the constructors, which is absolutely fine and the way it is supposed to be.

Akka: What happens when you tell an ActorRef and it expects you to ask?

I have the following:
val future = myActor ? Message
And in my actor my receive message has something like this:
sender ! Response
If I do the following and ignore the response, is there any negative impact?
myActor ! Message
Maybe I'm just missing where it says this in the documentation. Is it like a method that returns a value and the caller doesn't assign the return value to anything? If I make that call from another actor is there going to be some weird threading issue or memory leaks that result from it? My unit tests don't seem to be affected but it's kind of a contrived. I'm hoping I'm just over-thinking the problem and maybe I can't find the answer because it's a stupid question that no one in their right mind asks.
With ask pattern Response is received by temporary light-weight actor (PromiseActorRef).
In case of myActor ! Message there should be implicit ActorRef in scope. Response will be sent to this implicit ActorRef. This message will not be garbage-collected until you explicitly read it.
If there is no implicit ActorRef in scope Actor.noSender is used and Response will be forwarded to system's deadLetters.
If you make that call from another actor this Response will be delivered to message box of this another actor.

actor:possible to send and receive nested in a receive

When process a message, is it possible to send out an message to another actor and wait for that actor to reply, and consume the replied message and then continue, like the following, is it doable?
val lineMap=HashMap[String,Int]()
receive {
case bigTaskMap=>
for (line <-readSomeFile){
if(lineMap.get(line)==None){
anotherActor!line // that actor will reply a hashmap which contain the key for line
receive {
case x:HashMap => lineMap=x
}
}
lineMap.get(line) // use that value to do further work
}
}
This answer is for Akka (old Scala actors are deprecated in Scala 2.10).
Yes. You can use ask to get a future (rather than creating a fully-fledged actor yourself) and then call onComplete on the Future returned to set an action which will be executed when the Future's value (or an error) becomes available. Don't worry about how quickly the Future might yield a value - it doesn't matter, because the onComplete action will be executed even if the Future is already available when onComplete is called!
However, be very careful: you should not directly access any of the state (i.e. the variables) in the containing actor in your action(s), because the onComplete action(s) will not run in the same execution context as the actor (i.e. they could be running at the same time as the original actor is processing a message). Instead, send further messages back to the original actor, or forward them on.
In fact, in some cases you may find the simplest thing to do is simply to send a message, and let the original actor handle the reply. become and unbecome may help here. However, again, be careful if using become, that in the actor's new behaviour, it doesn't drop "ordinary" messages that should be handled in the ordinary way.