2017-04-06 13 views
0

に再起動されません。私は、親の俳優があります子役は失敗

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"); 
      } 
     } 
    } 
} 

アイデアを成功するまで子アクタを再起動することです。しかし、障害が発生すると、アプリケーションはすぐそこで停止し、クラッシュします。私はどんな助けにも感謝します。どうもありがとうございました。

答えて

1

いくつかのより一般的なヒント:あなたが俳優のコンストラクタ内部Receive/ReceiveAsync方法を介して供給されたメッセージハンドラを持っていることを期待ReceiveActorを使用している

  1. Become(ActiveAsync)は、ReceiveActorの継承者ではなく、型なしのアクターによって使用されます。
  2. あなたはアクティブな非同期メソッドはタスクを返さないだけです。このメソッドから例外がスローされると、システムの動作を予測することは難しいです。
  3. 俳優のコンストラクタ内でBecomeを使用しないでください。そうでない場合は、PreStartメソッドを使用しないでください。アクターの初期化中にスローされた例外は、常にアクターが停止することになります(監督戦略でもアクターを再始動することさえあります)。

言われている最も簡単な方法はあなたの俳優に提供することです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) { ... } 

    ... 
} 
+0

ご協力いただきありがとうございますが、私は、私はあなたがそれをテストしたいか、なぜわからないんだけど、スーパーバイザー戦略 –

+0

をテストするために意図的に例外をスローしたいと思いますので、私はあなたの答えを得ることはありません。ほとんどの例外に対してアクターの[デフォルト戦略](https://github.com/akkadotnet/akka.net/blob/dev/src/core/Akka/Actor/SupervisorStrategy.cs#L103)が再起動されます。あなたはそれをテストするかもしれませんが、この方法でドメインをテストするのではなく、フレームワーク自体をテストします。私が添付したコードは、あなたのアクターを初期化する方法が内部を壊していると思われるので、ReceiveActorの設定を示しています。 – Horusiath

+0

例外が発生した場合は、そのことを確認したいと思います。データベースからデータを取得するまで子アクターが再起動されます。また例外はコンストラクタから来るのではなく、 'RandomFailure.Fail()'関数から来ます。私はあなたのコードを試してみましたが、それは動作しません(例外を投げてアプリケーションをクラッシュさせます)。 –

関連する問題