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) Akka Actor tell() Method It works on "fire-forget" approach. You can also use ! (bang) exclamation mark to send message. This is the preferred way of sending messages.
java.io.Serializable. An ActorRef is the identity or address of an Actor instance. It is valid only during the Actor’s lifetime and allows messages to be sent to that Actor instance.
Actors are objects (class instances in Java sense) that may have mutable state and normally follow the standard rules: Everything is an actor. Actors communicate with each other exclusively by sending asynchronous messages. There is no shared state, public static variables, etc.
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.
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