我有这个主类接收队列消息,然后使用其他一些类来做一些工作。所有这些其他类本身都使用一些较低的类,最终将数据写入数据库或发送到wcf服务。
根据较低类的结果,主类必须决定删除队列消息,或者将其再次放入队列,或将其发送到死信号。
例如,如果数据库无法访问,则可以将队列消息放入队列中以便稍后再次尝试。但是如果wdcf服务返回它不接受某些数据,则必须将消息发送到deadletterqueue。
我有几种方法可以实现这种情况:
这些是关于场景的想法:
如果其中一个最低类抛出一个异常,并且main-class必须处理它,它会将main-class一直耦合到最低类。如果其中一个最低类决定更改异常,我必须更改主类异常处理。
没有好办法让上层人员知道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
}
}