akka.net
akka.net copied to clipboard
Need to document `ActorInitializationException` and how it occurs in actor lifecycle
Well I learned something new today
Throwing an exception in an actor's PreStart
block will not allow the actor to be restarted: https://replit.com/@Aaronontheweb/ActorsPreStart#main.cs
I'm trying to imagine if that's by design or not (it might be since the child actor can't really complete its startup sequence if it fails there.)
Either way, that means this bug is more severe than I thought. We'll get this patched right away.
Originally posted by @Aaronontheweb in https://github.com/akkadotnet/akka.net/issues/5962#issuecomment-1138580434
One implication of this is that the actor's PostStop
method is also never called, which causes functions that depend on PostStop
for cleanup such as IWithTimers
to never run correctly.
I think that's because any exception in an actor's PreStart
will throw ActorInitializationException
, to which the default Supervisor Strategy will react by stopping (not restarting) the actor.
If you use a supervisor with a custom-defined Supervisor Strategy that restarts on every exception, then it'll work:
public class MySupervisorActor : UntypedActor
{
private IActorRef actor;
protected override SupervisorStrategy SupervisorStrategy() =>
new OneForOneStrategy(Decider.From(_ => Directive.Restart));
protected override void PreStart()
{
base.PreStart();
actor = Context.ActorOf(Props.Create<MyActor>(), "myactor");
}
protected override void OnReceive(object message) => actor.Forward(message);
}
public class MyActor : UntypedActor
{
public bool _failedOnce;
protected override void PreStart()
{
if (_failedOnce)
return;
_failedOnce = true;
throw new ApplicationException("crashing!");
}
protected override void OnReceive(object message) => Context.Sender.Tell(message);
}
In that case this is working as intended, but we should probably expand on this inside the documentation: https://getakka.net/articles/actors/fault-tolerance.html