2017-04-06 1 views
0

에서 다시 시작되지 않습니다자식 배우 I는 부모 배우가 실패

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. 활성 비동기 메서드는 작업을 반환하지 않습니다. 단지 void입니다. 이러한 메서드에서 예외가 throw 될 때 시스템의 동작 방식을 예측하기는 어렵습니다.
  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

을 테스트하는 목적에 예외를 발생 싶습니다 때문에 내가 답변을하지 않습니다. 대부분의 예외에 대한 액터의 [Default strategy] (https://github.com/akkadotnet/akka.net/blob/dev/src/core/Akka/Actor/SupervisorStrategy.cs#L103)가 다시 시작됩니다. 테스트 할 수는 있지만 도메인을 테스트하지 않고 프레임 워크 자체를 테스트합니다. 첨부 한 코드는 액터를 초기화하는 방법이 내부를 분해하는 것으로 의심하기 때문에 ReceiveActor의 구성을 보여줍니다. – Horusiath

+0

예외가 발생할 경우이를 확인하고 싶습니다. 자식 액터는 데이터베이스에서 데이터를 가져올 때까지 다시 시작됩니다. 또한 예외는 생성자에서 온 것이 아니라'RandomFailure.Fail()'함수에서옵니다. 귀하의 코드를 시도했지만 작동하지 않습니다 (예외가 발생하고 응용 프로그램이 다운 됨) –