У меня есть два актера (родитель и ребенок), и я использую SupervisorStrategy.StoppingStrategy
и Watch
для обработки ошибок. Но проблема в том, что родитель не получает Terminated
-сообщение, когда ребенок умирает.
Ниже приведен простой тест для проверки моей проблемы.
[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();
});
}
}
Я хочу, чтобы родитель, который наблюдает за ребенком, получал Terminated
всякий раз, когда у ребенка есть ошибка, которую он не обрабатывает. Как я могу это сделать?
Он отлично работает, когда я отправляю PoisonPill
вместо того, чтобы бросать Exception
.
Актеры в тестах, по-видимому, созданы со стратегией наблюдения за перезапуском и, таким образом, не убивают актера при возникновении исключения. Я не могу найти способ изменить стратегию супервайзера тестов. Итак, я написал это для создания акторов в тестах со стратегией остановки супервизора без необходимости писать «настоящий» актор-оболочку.
[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();
}
}
Следующая строка, которую вы написали, даст дочернему ребенку стратегию остановки надзирателя, что означает, что дети ребенка будут остановлены, когда что-то произойдет.
var child = Sys.ActorOf(Props.Create(() => new FooActor(), SupervisorStrategy.StoppingStrategy), "Name");