How to distinguish actor termination reason

363 views Asked by At

I mean I did everything as described in docs:

Receive<InitTopicMessage>(m =>
{
  parserActor = getParserActor(Context, rootTopicId);
  Context.Watch(parserActor);
}

// ...

Receive<Terminated>(t =>
{
   if(t == parserActor)
   {
       // do some stuff
   }
}

The problem is that I want to do some stuff only if parser actor was terminated because of error, and not because of ActorSystem termination.

So, is there any way to distinguish the reason of the actor termination?

2

There are 2 answers

1
Elliott On BEST ANSWER

You will receive a termination message for one of two reasons:

  1. The remote actor was terminated gracefully
  2. The remote process crashed or there was a network failure.

You can distinquish between the two with Terminated.AddressTerminated

If Terminated.AddressTerminated == true then it was a crash or network failure.

If you need to to be more precise or handle certain errors then you'll want to use a supervisor strategy on the remote system (which could send the appropriate messages).

Akka is all about fault tolerance and resiliency though so you might be asking the wrong question. If the remote actor goes down, how do you make it recover without the parseActor even caring?

0
bonzaster On

There is another way to solve my problem, just in case if someone interested. I send custom message, indicating system shutdown, before terminating ActorSystem, and then actor just change its behavior to ignore Terminated message:

public class SomeActor : ReceiveActor
{
    public SomeActor()
    {
        Become(Working);
    }

    private void Working()
    {
        Receive<ApplicationStopMessage>(m =>
        {
            Become(ShuttingDown);
        });

        Receive<Terminated>(t =>
        {
            // do stuff on 
        });
    }

    private void ShuttingDown()
    {
        ReceiveAny(m =>
        {
            // ignore all messages
        });
    }
}

// somewhere in code
someActor.Tell(new ApplicationStopMessage());
actorSystem.Terminate();

now we will handle Terminated message only if it was send by failed child.

Not so obvious and clear as using Terminated.AddressTerminated, but worked for me