Akka Java here. I have two actors, Parent
and Child
, where the former is the parent of the latter. If Child
throws a specific exception (say, an UnrulyTeenagerExcepton
), then the behavior I am looking for is as follows:
Parent
saves a reference to the message that was being processed by Child
when the exception was thrown; thenChild
is restarted, and the persisted message is “played back” to the Child
; butChild
throws the UnrulyTeenagerException
three times, then we SupervisorStrategy.escalate()
My best attempt thus far:
// Groovy pseudo-code
class ChildFailureDecider extends Function<Throwable,Directive> {
int maxRetries = 3
int numRetries = 0
@Override
Directive apply(Throwable childFailure) {
if(childFailure instanceof UnrulyTeenagerException) {
numRetries++
if(numRetries <= maxRetries) {
// TODO: #1 How to persist the message that caused the ‘childFailure’?
return SupervisorStrategy.restart()
// TODO: #2 How to ‘play back’ the persisted message to Child?
}
}
SupervisorStrategy.escalate()
}
}
But as you can see, I’m struggling with message persistence and play back. Any ideas? Java code samples greatly appreciated, Akka is tough enough without also having to learn Scala hieroglyphics!
Akka persistence is about recording events (not the same thing as messages) in a persistent way (e.g. to disk, or to a database) in a persistent way so that if your whole application terminates (such as a JVM crash or hardware failure), it is possible to rebuild the state of that actor on restart. In your case, you want to remember the message sent to a single actor and resend it when that actor is restarted due to a failure, so I don't think you need the persistence API in this case.
When an actor throws an exception, that exception is presented to the supervisor but the message that caused it is not. I don't think there is a built in way for this to be achieved. The supervisor can manage the rule of only restarting 3 times, by setting the supervision strategy with appropriate parameters: http://doc.akka.io/japi/akka/2.4-M3/akka/actor/OneForOneStrategy.html#OneForOneStrategy-int-scala.concurrent.duration.Duration-akka.japi.Function-
The replaying of messages needs to be handled by the sender. You can implement at least once semantics by having the receiver send an acknowledgement to the sender when the message has been handled, and have the sender retry periodically if the acknowledgement is not received. See this question for more info: Akka Message Delivery Guarantees
Sorry for the lack of code but I use the Scala API rather than Java.