2016-07-05 2 views
2

NServiceBus 사용하기 4.3 특정 조건이 발생하면 오류 대기열로 메시지를 보내려고합니다.처음으로 오류 대기열로 메시지 보내기

시나리오는 메시지를 받았을 때이 메시지가 데이터베이스에있는 하나 이상의 항목을 나타내는 것인지 확인합니다. 참조가 여러 개인 경우 AmbiguousItemException을 던져 잡습니다. 나에게 정확한 정보를 제공 할 책임이있는 사람에게 이메일을 보내야합니다. 이 모든 것을 알아 냈지만이 메시지를 다시 시도하기를 원하지 않습니다. 대신 오류 대기열로 이동시켜야하므로 필요한 정보를 얻으면 nullable 속성을 추가하고 메시지를 처리 ​​대기열에 다시 넣을 수 있습니다. _bus.ForwardCurrentMessageTo("error"), _bus.Send("error", message), _bus.SendLocal(message)을 사용해 보았습니다. 마지막 하나는 기본적으로 메시지를 무한 루프에 넣습니다. 코드는 이런 종류입니다. 당신이 장기 실행 비즈니스 프로세스를 가지고있는 것처럼

public class MoveToErrorQueue 
{ 
    private readonly IBus _bus; 

    public MoveToErrorQueue(IBus bus) 
    { 
     _bus = bus; 
    } 

    public virtual void Send(ResubmitMessage message) 
    { 
     message.Foo= -1; 
     _bus.Send("error", message); 
    } 
} 

당신이 그것을 묘사하는 것에서 그

 try 
     { 
      //removed for brevity 
     } 
     catch (AmbiguousItemException ex) 
     { 
      Log.Error(ex); 
      sendNotificationCommand.FailureMessage = ex.Message; 
      _moveToErrorQueue.Send(commandMesage); 
     } 
     SendNotification(sendScanningNotificationCommand); 

답변

6

를 호출하는 코드는 소리가 난다. 이 사람은 using a Saga의 후보입니다. Sagas는 핸들러처럼 들어오는 메시지를 처리하지만 Saga에서는 상태를 추적 할 수도 있습니다. 따라서 메시지를 오류 대기열로 보내지 말고 (실제로는 좋은 생각이 아닙니다) 대신 Saga에 부울 또는 열거 형과 같은 플래그를 설정하여 메시지가 " 데이터베이스에있는 하나 이상의 항목을 참조하십시오 "라고 말합니다.

깃발을 설정하면 업데이트 정보를 얻기 위해 이메일을 고객에게 보내야한다는 것을 알리는 메시지를 내보낼 수 있습니다 (이것은 아마도 자동화 될 수 있습니다).

필요한 정보를 받으면 필요한 조치를 취한 다음 해당 프로세스를 계속 진행하고 완료로 표시하고 종료하는 메시지를 사가에 보낼 수 있습니다.

You can learn more about Sagas here

+0

이렇게하면 효과가 있었지만 팀과 이야기 한 후 알림 명령을 대기열에 넣지 않고 메시지 오류를 해결하고 오류 대기열로 이동하기로 결정했습니다. –

+1

알림 명령은 Saga로 바로 돌아올 수 있으며 자체적으로 처리 할 수 ​​있습니다. 그것은 단지 제안이었습니다. 당신은 쉽게 테이블에 레코드를 넣거나 자신에게 이메일을 보낼 수 있습니다. 에러 큐를 어지럽히는 것은 권장되지 않습니다. 그것을 위해 설계된 것이 아닙니다. 나는 그것을 추천하지 않을 것이다. –

+2

참고로, @ColinPear는 오류 대기열이 비즈니스 유효성 검사 오류를 포착해서는 안된다는 의미입니다. –

1

본질적으로 오류 큐에 특정 예외를 보내기 위해 "아니오 재시도"숫자를 은퇴의 API에 연결하고 돌아

http://docs.particular.net/nservicebus/errors/automatic-retries#second-level-retries-custom-retry-policy-exception-based-policy

var retriesSettings = busConfiguration.SecondLevelRetries(); 
retriesSettings.CustomRetryPolicy(MyCustomRetryPolicy); 

정책

가능하다
TimeSpan MyCustomRetryPolicy(TransportMessage transportMessage) 
{ 
    if (transportMessage.ExceptionType() == typeof(MyBusinessException).FullName) 
    { 
     // Do not retry for MyBusinessException 
     return TimeSpan.MinValue; 
    } 

    if (transportMessage.NumberOfRetries() >= 3) 
    { 
     return TimeSpan.MinValue; 
    } 

    return TimeSpan.FromSeconds(5); 
} 

a 헤더 도우미

static class ErrorsHeadersHelper 
{ 
    internal static int NumberOfRetries(this TransportMessage transportMessage) 
    { 
     string value; 
     if (transportMessage.Headers.TryGetValue(Headers.Retries, out value)) 
     { 
      return int.Parse(value); 
     } 
     return 0; 
    } 

    internal static string ExceptionType(this TransportMessage transportMessage) 
    { 
     return transportMessage.Headers["NServiceBus.ExceptionInfo.ExceptionType"]; 
    } 
} 
+0

이 작업은 효과가 있지만 어쩌면 FLR이 SLR에 넘겨지기 전에 구성된 횟수만큼 실행됩니다.FLR이하는 동안 당신이 파이프 라인에 연결할 수 있는지 모르겠습니다. 내가 이해하는 한, 당신은 FLR이 시도를 다 써 버릴 때까지 헤더를 추가하지 않습니다. –

+0

@JustinSelf가 맞습니다. 예외 유형에 따라 FLR을 제어해야한다는 요구 사항이 있습니까? 만약 그렇다면 그것을 조사하고 가능한 경우 샘플을 추가 할 수 있습니다. – Simon

관련 문제