To help myself in reasoning, I have made a code with the following characteristics:
- When the
external
behavior receives the Change
message, it becomes internal
.
- When any behavior receives a
Crash1
message, it throws an Exception1
; when it receives a Crash2
message, it throws an Exception2
.
- Both behaviors are wrapped in a supervisor with restart strategy.
- The
external
supervisor supervises Exception1
exceptions.
- The
internal
supervisor supervises Exception2
exceptions.
- Both behaviors handle the
PreRestart
and PostStop
signals.
public class Question {
public interface Command {}
public static final class Change implements Command {}
public static final class Crash1 implements Command {}
public static final class Crash2 implements Command {}
public static final class Msg implements Command {}
public static final class Exception1 extends Exception {}
public static final class Exception2 extends Exception {}
public static Behavior<Command> external() {
return Behaviors.supervise(Behaviors.receive(Command.class)
.onMessage(Msg.class, msg -> {
System.out.println("External: received Msg, return same");
return Behaviors.same();
})
.onMessage(Crash1.class, msg -> {
System.out.println("External: received Crash1, throw Exception1");
throw new Exception1();
})
.onMessage(Crash2.class, msg -> {
System.out.println("External: received Crash2, throw Exception2");
throw new Exception2();
})
.onMessage(Change.class, msg -> {
System.out.println("External: received Change, return internal supervised behavior");
return Behaviors.supervise(internal()).onFailure(Exception2.class, SupervisorStrategy.restart());
})
.onSignal(PreRestart.class, signal -> {
System.out.println("External: PreRestart");
return Behaviors.same();
})
.onSignal(PostStop.class, signal -> {
System.out.println("External: PostStop");
return Behaviors.same();
})
.build())
onFailure(Exception1.class, SupervisorStrategy.restart());
}
public static Behavior<Command> internal() {
return Behaviors.receive(Command.class)
.onMessage(Msg.class, msg2 -> {
System.out.println("Internal: received Msg, return same");
return Behaviors.same();
})
.onMessage(Crash1.class, msg -> {
System.out.println("Internal: received Crash1, throw Exception1");
throw new Exception1();
})
.onMessage(Crash2.class, msg -> {
System.out.println("Internal: received Crash2, throw Exception2");
throw new Exception2();
})
.onSignal(PreRestart.class, signal -> {
System.out.println("Internal: PreRestart");
return Behaviors.same();
})
.onSignal(PostStop.class, signal -> {
System.out.println("Internal: PostStop");
return Behaviors.same();
})
.build();
}
}
The main looks as follows:
final ActorSystem<Command> system = ActorSystem.create(external(), "helloakka");
system.tell(new Msg()); // External: received Msg, return same
system.tell(new Crash1()); // External: received Crash1, throw Exception1
// External: PreRestart
system.tell(new Change()); // External: received Change, return internal supervised behavior
system.tell(new Msg()); // Internal: received Msg, return same
Let’s continue the main in two different ways:
V1
system.tell(new Crash1()); // Internal: received Crash1, throw Exception1
// Internal: PreRestart
system.tell(new Msg()); // External: received Msg, return same
V2
system.tell(new Crash2()); // Internal: received Crash2, throw Exception2
// Internal: PreRestart
system.tell(new Msg()); // Internal: received Msg, return same