【发布时间】:2012-12-20 07:32:48
【问题描述】:
我有这个接收队列消息的主类,然后使用其他一些类来做一些工作。所有这些其他类本身都使用一些较低的类,最终将数据写入数据库或发送到 wcf 服务。
根据低级类的结果,主类必须决定是删除队列消息,还是将其重新放入队列,或者将其发送到死信队列。
例如,如果数据库无法访问,则可以将 queuemessage 放入队列中稍后再试。但是如果 wdcf 服务返回它不接受某些数据,则必须将消息发送到死信队列。
我有几种方法来实现这个场景:
- 抛出异常并仅在主类中处理它们。
- 抛出异常,但在每个调用类中捕获它们。并重新抛出一个新异常
- 返回指示错误/成功状态的结果对象
这些是我对场景的想法:
如果最低类之一抛出异常,并且主类必须处理它,它会将主类一直耦合到最低类。如果最低类之一决定更改异常,我必须更改主类异常处理。
没有好办法让上层类知道C#中被调用的类会抛出哪些异常。
这是我更喜欢的。每个被调用的方法都可以返回一个结果对象,带有一个指示成功或失败的枚举,以及失败的类型。
所以,我的首选方式是选项 3,但我不知道这在架构上是否可以接受。或者是否有更好的方法。
代码
这就是代码(简化形式)的样子:
队列处理程序
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 服务调用失败、文件不存在等。
我希望我能阻止这种情况:
队列处理程序
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
}
}
【问题讨论】:
-
到目前为止你有什么关于你可以展示的代码以便有人可以提供更好的方法..如果你发布这种性质的代码..它可能最好在 codereview 中提供关于stackoverflow的部分。