Reputation: 10851
I have two actors (a parent and a child) and I use SupervisorStrategy.StoppingStrategy
and Watch
to handle errors. But the problem is that the parent is not receiving a Terminated
-message when the child dies.
Below is a simple test to verify my problem.
[Fact]
public void ExceptionTest()
{
var child = Sys.ActorOf(Props.Create(() => new FooActor(), SupervisorStrategy.StoppingStrategy), "Name");
Watch(child);
child.Tell("Some message");
ExpectMsg<Terminated>(); // This will not occur.
}
public class FooActor : ReceiveActor
{
public FooActor()
{
ReceiveAny((e) =>
{
// Crashes on every message.
throw new Exception();
});
}
}
What I want is that the parent which is watching the child should get a Terminated
whenever the child has an error which it doesn't handle. How can I accomplish it?
It works fine when I send a PoisonPill
instead of throwing an Exception
.
Upvotes: 0
Views: 306
Reputation: 542
Actors in tests seems to be created with restart supervising strategy and thus will not kill the actor when the exception happens. I can't find a way to change the supervisor strategy of tests. So I wrote this to create actors in tests with stopping supervisor strategy with out having to write a "real" wrapper actor.
[Fact]
public async Task ExceptionTest()
{
var actor = await CreateActorWithStoppingStrategy(Props.Create(() => new AsGoodAsDead()));
Watch(actor);
actor.Tell("Death");
ExpectTerminated(actor);
}
private async Task<IActorRef> CreateActorWithStoppingStrategy(Props props)
{
IActorRef child = null;
Action<IActorDsl> actor = d =>
{
d.Strategy = SupervisorStrategy.StoppingStrategy;
d.OnPreStart = context => child = context.ActorOf(props);
d.ReceiveAny((o, context) => context.Sender.Tell("ready"));
};
var parent = Sys.ActorOf(Props.Create(() => new Act(actor)));
await parent.Ask("ready?");
return child;
}
public class AsGoodAsDead : UntypedActor
{
protected override void OnReceive(object message)
{
throw new Exception();
}
}
The following line you wrote will give the child the stopping supervisor strategy, meaning the child's children will be stopped when something happens.
var child = Sys.ActorOf(Props.Create(() => new FooActor(), SupervisorStrategy.StoppingStrategy), "Name");
Upvotes: 2