5
votes

I'm looking over the Akka Java documentation on untyped actors (http://doc.akka.io/docs/akka/2.3.2/java/untyped-actors.html)

I effectively want to accomplish something such as:

Set a timeout for any particular message I expect to receive in my onReceive() method. For instance:

 public void onReceive(Object message) throws Exception {

     if (message.equals("start")) {
        child.tell("fetch something for me!", getSelf());
     }

     if (message.equals("child's response")) {
        // handle a response from a child here,
        // but timeout within some timeframe if I don't get a 
        // response quick enough.
       // use this here? getContext().setReceiveTimeout(Duration.create("1 second"));
     }
 }

I understand you can use Patterns.ask( actor , message , timeout ), which returns a future. If the response isn't sent back within the specified timeout argument, fail.

I don't want to use futures here. I don't understand the usage of the setReceiveTimeout method. How do I accomplish this by purely using actor.tell ?

1

1 Answers

8
votes

You should set the receive timeout immediately after performing your tell to the other actor. Once you do that, a clock basically starts ticking. If this actor does not receive any message to its mailbox within that timeframe, then a ReceiveTimeout message will be put into the mailbox indicating that you did not get a response in time. An updated version of your code to account for this would look something like:

public void onReceive(Object message) throws Exception {

    if (message.equals("start")) {
        child.tell("fetch something for me!", getSelf());
        getContext().setReceiveTimeout(Duration.create("1 second"));
    }

    else if (message.equals("child's response")) {
        getContext().setReceiveTimeout(Duration.Undefined()); //turn off receive timeout
        // handle a response from a child here
    }

    else if (message instanceof ReceiveTimeout) {
        getContext().setReceiveTimeout(Duration.Undefined()); //turn off receive timeout
        // handle situation where I did not get a response in time
    }
 }

You'll notice that whether I get an actual response or I get a receive timeout, I'm always turning off the receive timeout I set after the tell. The receive timeout is repeating; if I don't explicitly turn it off it will continue to send me ReceiveTimeout messages every interval (based on what I set the interval to when I set the receive timeout).

Be sure to keep in mind that the receive timeout functionality is message inspecific. That is it is skipped for an interval provided I receive any message to my mailbox; not just the one I want. So if some other actor sent me another completely different message, it will skip the receive timeout for that interval. If this is not going to be an issue, then no need to worry about it. But if it is possible that other messages besides the response might be arriving, you will need to handle that accordingly, resetting the original receive timeout based on how much time has elapsed since originally setting it (probably via a Deadline instance.