Effect of returning a supervised receive behavior from within a supervised receive behavior

51 Views Asked by At

I'd like to cross-post a question that I originally posted on Akka's user forum.

In Akka typed: What is the motivation for allowing a supervised receive behavior to return a new, supervised receive behavior?

Suppose we have a Receive behavior R1 decorated by a supervisor S1. As part of message processing, R1 returns a new Receive behavior R2, itself decorated by a supervisor S2.

Akka allows for this. Why? I couldn't find a similar example on the Internet. It is unusual: typically, a supervisor decorates a behavior once. Therefore, I am trying to come up with some motivating examples, and I am looking for validation.

Scenario 1:

  • R1 can throw Exception1 (and Exception1 only) as part of message processing. S1 decorates R1 handling Exception1.
  • R1 returns R2. Suppose that R2 can throw Exception2 as part of message processing logic. S1 is still there, but it only handles Exception1, not Exception2. Therefore, we must decorate R2 with S2 handling Exception2.

Does this make sense? If yes, why not make S1 handle both Exception1 and Exception2 directly, by nesting calls to onFailure?

Scenario 2:

  • R1 can throw both Exception1 and Exception2 as part of message processing. S1 handles both failures, by nesting calls to onFailure, with restart strategy.
  • R1 returns R2. Suppose we want to override S1's supervision strategy for Exception2: resume instead of restart. To do so, we decorate R2 with S2 handling Exception2 with resume strategy.

As discussed in Akka's user forum post, supervisors are evaluated in order inner to outer. Therefore, S2's supervision strategy for Exception2 will override S1's.

Questions

Am I on the right track? Do such scenarios ever arise in real life?

1

There are 1 best solutions below

0
Roland Kuhn On

This part of the Akka Typed design is the one that I was least sure about, there were several iterations going back and forth regarding how to do this.

The final result from my point of view was that a Behaviour should not include supervision, since the parent actor has the duty of deciding which failures to handle and which to escalate (into stopping the child actor, possibly inducing the parent to fail).

This distinction isn’t nicely representable in the Java/Scala type systems — if a Behaviour can be optionally supervised, then anyone can do that. The only recurse would have been to demand a SupervisedBehaviour for spawn(), enforcing that exactly one supervision scheme is added to the raw Behaviour. This didn’t feel right, either, since it curbs the freedom of choice of code modularity.


In short, while your scenario 1 sounds plausible, it isn’t really perfectly supported since shedding S2 later requires quite a bit of ugly boilerplate code.