Question
I seem to be observing a scenario in which the messages stashed for a typed supervised actor are lost during a restart, using the Akka backoff supervision strategy.
Is this expected behavior? If not, how can I implement ensure these stashed messages are retained?
The Setup
I create a typed supervised actor with a stash
BackoffSupervisorStrategy backoff = SupervisorStrategy
.restartWithBackoff(Duration.ofMillis(10), Duration.ofMillis(10000), 0)
.withStashCapacity(2000);
return Behaviors.supervise(Behaviors.setup(MyActor::new)).onFailure(Throwable.class, backoff);
It handles a command ForceFail
which results in a RuntimeException
so that we can let the Akka supervisor do its thing.
private Behavior<Command> forceFail(ForceFail command) {
getContext().getLog().info("Got fail command: {}", command.name);
throw new RuntimeException(command.name);
}
After spawning the actor, I send a series of tells
testSystem.tell(new ForceFail("first fail"));
testSystem.tell(new ForceFail("second fail"));
testSystem.tell(new ForceFail("third fail"));
Each tell
results in an exception in the actor, triggering a restart by the supervisor.
I check the size of the StashBuffer
right before the supervisor unstashes the messages during a restart.
What I see is that during the first restart, the StashBuffer
shows a size of 2, as expected. However, during the second restart for the second message, the size is 0, where I would expect it to be 1.
I do not see the last message get sent to the dead letter actor. It seems to be lost, with no logging describing what happens to it.
Notes
I see in the Akka internal code, the StashBuffer unstashAll()
method is called. As written in the javadocs:
If an exception is thrown by processing a message a proceeding messages and the message causing the exception have been removed from the StashBuffer, but unprocessed messages remain.
The wording seems a bit funny, but what it's saying is that it will sequentially process the messages in the stash until it processes all of them or we hit an exception. Unhandled messages remain in the stash. This does not seem to be what I'm observing though.
I'm using Akka 2.7.0.