As I understand it, an actor can be sent a message "fire and forget" style with the ! operator, or "Send-And-Receive-Future" style with the ? operator. An actor that is passed a message via ? must call a self.reply or the sender will receive a timeout exception. On the other hand, an actor that is passed a message via ! cannot have self.reply if the message is not being passed from another actor.
My question is, is the Actor supposed to know at compile time whether it will be invoked with ! or ? ??? Or if the necessity of self.reply can be determined at runtime, how can this be determined? Perhaps self.tryReply is involved, but the akka documentation seems to imply that a failed attempt to reply is an error case, whereas if the sender is not an actor, it is not really an error to fail to reply if the message is passed with !
Edit:
Here's some code:
package akTest
import akka.actor.Actor
object Main1 {
val worker = Actor.actorOf[ak].start()
def main(args: Array[String]) {
val resp = worker ? "Hi"
resp.get
println(resp)
}
}
class ak extends Actor {
def receive = {
case msg:String => {
val response = "Received: " + msg
println(response)
response
}
}
}
This gets
Exception in thread "main" akka.dispatch.FutureTimeoutException: Futures timed out after [4995] milliseconds
So I add a self.reply to the actor:
class ak extends Actor {
def receive = {
case msg:String => {
val response = "Received: " + msg
println(response)
self.reply(response)
response
}
}
}
This change fixes the timeout error. But now if I have a Main2 which sends a fire and forget message:
object Main2 {
val worker = Actor.actorOf[ak].start()
def main(args: Array[String]) {
val resp = worker ! "Hi"
println(resp)
}
}
, a new error is produced: [ERROR] [2/1/12 2:04 PM] [akka:event-driven:dispatcher:global-1] [LocalActorRef]
No sender in scope, can't reply.
How can I write my actor to eliminate the coupling between its manner of response and the sender's method of invoking? I don't want to have 1 version of the actor for ! and a second version of the actor for ?