0
votes

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 ?

1

1 Answers

2
votes

if senderFuture.isDefined then you have a future to reply to