儿童演员在失败时不会重新启动

时间:2017-04-06 21:23:42

标签: c# .net akka console-application akka.net

我有一个父演员:

public sealed class PersistenceSupervisor : ReceiveActor
{

    protected override void PreStart()
    {
        base.PreStart();

        Become(Active);
    }

    protected override SupervisorStrategy SupervisorStrategy()
    {
        return new OneForOneStrategy(
            10,
            TimeSpan.FromSeconds(0),
            x =>
            {
                return Directive.Restart;
            });
    }

    private void Active(object message)
    {
        IInventorPersister inventorPersistor = new InventorPersister();
        IActorRef persister = Context.ActorOf(Props.Create<Persister>(inventorPersistor), "persisterActor");
        var task = persister.Ask(message);
        task.Wait();
        Sender.Tell(task.Result);
    }
}

并且具有随机失败功能的儿童演员用于测试目的:

public sealed class Persister : ReceiveActor
{
    private readonly IInventorPersister inventorPersister;

    protected override void PreStart()
    {
        base.PreStart();

        Become(ActiveAsync);
    }

    private async void ActiveAsync(object message)
    {
        try
        {
            var savedSender = Context.Sender;
            Task persisting = Persist(message as CreatePublication);
            await persisting;
            savedSender.Tell("Success");
        }
        catch (Exception e)
        {
            throw new Exception(e.ToString());
        }
    }

    public Persister(IInventorPersister inventorPersister)        
    {
        this.inventorPersister = inventorPersister;
    }

    private async Task Persist(CreatePublication message)
    {
        RandomFailure.Fail();    
        // This function is to make an UPDATE query to db        
        await inventorPersister.Persist(message.PublicationNumber, message.Inventors);            
    }

    // Random failure for testing purpose
    private static class RandomFailure
    {
        private static readonly Random R = new Random();
        public static void Fail()
        {
            if (R.Next(0, 2) == 0)
            {
                throw new InvalidOperationException("Random failure");
            }
        }
    }
}

这个想法是重新启动子actor,直到它成功为止。但是,当故障发生时,应用程序会在那里停止并崩溃。我感谢任何帮助。非常感谢你。

1 个答案:

答案 0 :(得分:1)

一些更一般的提示:

  1. 您正在使用ReceiveActor期望在actor的构造函数中通过Receive / ReceiveAsync方法提供消息处理程序。非类型化actor使用Become(ActiveAsync)而不是ReceiveActor继承者。
  2. 你是活跃的异步方法不会返回任务只是一个空白 - 当从这种方法抛出异常时,很难预测系统的行为方式。
  3. 如果您不需要,请不要在actor的构造函数或Become方法中使用PreStart。在actor初始化期间抛出的异常将导致actor被停止(即使监督策略是重启它)。
  4. 话虽这么说,最简单的方法就是为你的演员提供ReceiveAsync处理程序。

    public sealed class Persister : ReceiveActor
    {
        private readonly IInventorPersister inventorPersister;
    
        public Persister(IInventorPersister inventorPersister)
        {
            this.inventorPersister = inventorPersister;
            ReceiveAsync<CreatePublication>(async message =>
            {
                await Persist(message);
                Context.Sender.Tell("Success");
            });
        }
        private async Task Persist(CreatePublication message) { ... }
    
        ...
    }