キューメッセージを受信し、他のいくつかのクラスを使用して何らかの作業を行うこのメインクラスがあります。これらの他のすべてのクラスは、いくつかの下位クラス自体を使用し、最終的にデータはデータベースに書き込まれるか、wcf サービスに送信されます。
下位クラスの結果に基づいて、メインクラスは、キューメッセージを削除するか、キューに再度配置するか、デッドレターキューに送信するかを決定する必要があります。
たとえば、データベースに到達できない場合は、後で再試行するためにキューメッセージをキューに入れることができます。しかし、wdcf サービスが一部のデータを受け入れないことを返した場合、メッセージをデッドレターキューに送信する必要があります。
このシナリオを実装するには、いくつかの方法があります。
- 例外をスローし、メイン クラスでのみ処理します。
- 例外をスローしますが、呼び出し元の各クラスで例外をキャッチします。そして、新しい例外を再スローします
- エラー/成功状態を示す結果オブジェクトを返します
これらは、シナリオに関する私の考えです。
最下位クラスの 1 つが例外をスローし、メインクラスがそれを処理する必要がある場合、メインクラスを最下位クラスに結合します。最下位のクラスの 1 つが例外を変更することを決定した場合、メインクラスの例外処理を変更する必要があります。
C# で呼び出されたクラスからスローされる例外を上位クラスに知らせる良い方法はありません。
これは私が好むものです。呼び出されたすべてのメソッドは、成功または失敗を示す列挙型と失敗のタイプを含む結果オブジェクトを返すことができます。
したがって、私の好みの方法はオプション 3 ですが、それがアーキテクチャ的に受け入れられるかどうかはわかりません。または何か良い方法があれば。
コード
コードは次のようになります (簡略化された形式)。
QueueHandler
private static void HandleQueueMessage(Message message)
{
var deliveryOrder = deserialize(message.body);
var deliveryOrderHandler = new DeliveryOrderHandler();
var result = deliveryOrderHandler.Execute(deliveryOrder.PubId);
switch (result)
{
case DeliveryOrderHandlerResult.DeliverySucceeded:
break;
case DeliveryOrderHandlerResult.FataleErrorInExternalSystem:
case DeliveryOrderHandlerResult.MAndatoryDocuhmentTransformationFailed:
SendDeliveryOrderToDeadletterQueue(deliveryOrder);
break;
default:
deliveryOrder.AbortCount = deliveryOrder.AbortCount + 1;
ResendDeliveryOrderToQueue(deliveryOrder);
break;
}
}
DeliveryOrderHandler
private DeliveryOrderHandlerResult Execute(long pubId)
{
DeliveryOrderHandlerResult deliveryOrderHandlerResult;
var transformationResult = GetTransformationResultaat(pubId);
if (transformationResult == TransformationResult.Success)
{
var deliveryResult = DeliverDocumentToExternalSystem(pubId);
if (deliveryResult.Status == DeliveryResult.Success)
{
SaveDeliveryResult(pubId, deliveryResult);
}
deliveryOrderHandlerResult = deliveryResult.Status;
}
else
{
switch (transformationResult)
{
case TransformationResult.NotStarted:
deliveryOrderHandlerResult = DeliveryOrderHandlerResult.TransformationNotStarted;
case TransformationResult.Busy:
deliveryOrderHandlerResult = DeliveryOrderHandlerResult.TransformationBusy;
case TransformationResult.MandatoryTransformationFailed:
deliveryOrderHandlerResult = DeliveryOrderHandlerResult.MandatoryTransformationFailed;
default:
throw new Exception(--unknown enum value --);
}
}
return deliveryOrderHandlerResult;
}
DeliverDocumentToExternalSystem
pseudo:
- Create Delivery package by reading data from database and transformed files from disk
- Send package to external system
ご覧のとおり、うまくいかないことがたくさんあります。データベース接続の失敗、wcf サービス呼び出しの失敗、ファイルが存在しないなど。
私はこれを防ぐことができると思っていました:
QueueHandler
private static void HandleQueueMessage(Message message)
{
var deliveryOrder = deserialize(message.body);
var deliveryOrderHandler = new DeliveryOrderHandler();
try
{
var result = deliveryOrderHandler.Execute(deliveryOrder.PubId);
switch(result)
{
case DeliveryOrderHandlerResult.Success:
// remove message from queue
case DeliveryOrderHandlerResult.NotStarted:
// resent message to queue
case DeliveryOrderHandlerResult.MandatoryTransformationFailed:
// send message to deadletterqueue
case ...
// handle
case ...
// handle
}
}
pseudo catches:
catch (DatabaseNotFoundexception ex)
{
// resent message to queue
}
catch (ExternalWcfServiceDownException ex)
{
// resent message to queue
}
catch (FileNotFoundException ex)
{
// send message to deadletterqueue
}
catch (...)
{
// handle
}
catch (...)
{
// handle
}
}