smoksnes
smoksnes

Reputation: 10851

Not receiving Terminated after Exception in Akka.net

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

Answers (1)

Lejdholt
Lejdholt

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

Related Questions