smeeb
smeeb

Reputation: 29577

How Akka Futures and Supervisor Strategies deal with failure

Akka Java here. I just read the Akka docs on the “ask” pattern using futures and am not understanding how several things work, with respect to scenarios when both supervisor strategies (deciders) and failure callbacks are part of the picture.

Parent asking a Child

Say I have two actors, Fizz and Buzz, where Fizz is the parent/creator of Buzz. Because Fizz is Buzz’s parent, it has a SupervisorStrategy for Buzz that handles its failures:

// Groovy pseudo-code
class Fizz extends UntypedActor {
    ActorRef buzz

    // Contstructor omitted for brevity, but Buzz is the child of
    // Fizz.

    @Override
    void onReceive(Object message) {
        if(message instanceof FizzRequest) {
            FizzRequest fReq = message as FizzRequest

            // Exceptions thrown here (inside of Buzz) will be
            // handled by Fizz’s supervisor strategy.
            Future<BuzzData> bDataFut = Patterns.ask(buzz,
                fReq.buzzRequest, 500)
            bDataFut.onComplete(new GetBuzzDataCallback())

            // etc.
        } else {
            unhandled(message)
        }
    }

    @Override
    SupervisorStrategy supervisorStrategy() {
        new FizzSupervisorStrategy()
    }
}

class Buzz extends UntypedActor {
    // …etc.
}

class FizzDecider extends Function<Throwable,Directive> {
    @Override
    Directive apply(Throwable throwable) {
        if(throwable instanceof BuzzIsAngryException) {
            return SupervisorStrategy.restart()
        }

        SupervisorStrategy.stop()
    }
}

class FizzSupervisorStrategy extends OneForOneStrategy {
    FizzSupervisorStrategy() {
        super(true, new FizzDecider())
    }
}

class GetBuzzDataCallback extends OnComplete<BuzzData> {
    @Override
    void onComplete(Throwable failure, BuzzData bData) {
        if(failure != null) {
            // If Buzz is the child of Fizz, does this code execute, or
            // just the FizzDecider above? Or both? I’m so confused!
        } else {
            // Handle success. Likely use an ‘Inbox’ to send
            // ‘bData’ back to Fizz.
        }
    }
}

Sometimes, Fizz needs to ask Buzz for some data. When this happens, there can be one of three results:

  1. Buzz returns successfully and provides the GetBuzzDataCallback with bData; or
  2. Buzz throws a BuzzIsAngryException; or
  3. Buzz throws some other kind of exception/error

I’m wondering what happens with the latter two cases:

Parent asking a non-Child

Same scenario as above, except now Fizz is not the parent/creator of Buzz. In this case, can I just assume that the GetBuzzDataCallback is sent the exception (as its Throwable failure argument)?

I guess at the root of my question(s) is this: when a supervisor strategy and a future callback are involved, who gets notified when a child exception is thrown, and in what order? As I mentioned above, to me it would be extra confusing if both receive the failure/exception because then you might have a supervisor strategy trying to restart a Buzz while the callback is trying to do something else (possibly conflicting) with the exception.

Please note: Although certainly not a requirement, I would greatly appreciate it if any code snippets provided be in Java and not Scala (Scala looks like hieroglyphics to me)!

Upvotes: 0

Views: 493

Answers (1)

johanandren
johanandren

Reputation: 11479

What ask does is basically starting a temporary actor that will be the sender of the message so that when the recipient replies it will end up in this temporary actor. The temporary actor creates a Promise and gives away the Future for it to the caller. If a reply arrives before the given timeout, the temporary actor completes the Promise with the successful result.

Supervision always happens in actors, and since ask is implemented using an actor, there isn't anything different about the interaction compared to random other actor sending it the message that could make the supervision work differently.

In your case an exception will bubble up to the parent actor, so that it can supervise the child. Then, unless you somehow send a reply message triggered by this failure, the timeout will hit and the temporary ask-actor will fail the future with an AskTimeoutException.

So, as this failure would reach the parent from two ways, it might not generally be a good idea to use the ask pattern with parent to child communication.

Upvotes: 0

Related Questions