bie*_*000 3 c# masstransit microservices
我想知道应该如何以正确的方式处理域异常?
我的所有消费者代码是否都应该包装到 try、catch 块中,或者我应该抛出一个异常,该异常将由适当的FaultConsumer 处理?
考虑这两个示例:
示例 1 - 整个操作被包装到 try...catch 块中。
public async Task Consume(ConsumeContext<CreateOrder> context)
{
try
{
//Consumer that creates order
var order = new Order();
var product = store.GetProduct(command.ProductId); // check if requested product exists
if (product is null)
{
throw new DomainException(OperationCodes.ProductNotExist);
}
order.AddProduct(product);
store.SaveOrder(order);
context.Publish<OrderCreated>(new OrderCreated
{
OrderId = order.Id;
});
}
catch (Exception exception)
{
if (exception is DomainException domainException)
{
context.Publish<CreateOrderRejected>(new CreateOrderRejected
{
ErrorCode = domainException.Code;
});
}
}
}
Run Code Online (Sandbox Code Playgroud)
示例 2 - MassTransit 通过将消息推送到 CreateOrder_error 队列来处理 DomainException。另一个服务订阅该事件,并在该事件发布到该特定队列上后对其进行处理;
public async Task Consume(ConsumeContext<CreateOrder> context)
{
//Consumer that creates order
var order = new Order();
var product = store.GetProduct(command.ProductId); // check if requested product exists
if (product is null)
{
throw new DomainException(OperationCodes.ProductNotExist);
}
order.AddProduct(product);
store.SaveOrder(order);
context.Publish<OrderCreated>(new OrderCreated
{
OrderId = order.Id;
});
}
Run Code Online (Sandbox Code Playgroud)
哪种方法应该更好?
我知道我可以使用请求/响应并立即获取有关错误的信息,但就我而言,它必须通过消息代理完成。
在您的第一个示例中,您通过生成未知产品订单被拒绝的事件来处理域条件(在您的示例中,目录中不存在产品)。这是完全有道理的。
现在,如果用于检查产品的数据库查询无法连接到数据库,这是一种临时情况,可能会自行解决,因此使用重试或计划重新交付是有意义的 - 在完全放弃之前重试。这些是您想要抛出的异常。
但是您想要捕获并通过发布事件来处理的业务异常。
public async Task Consume (ConsumeContext<CreateOrder> context) {
try {
var order = new Order ();
var product = store.GetProduct (command.ProductId); // check if requested product exists
if (product is null) {
throw new DomainException (OperationCodes.ProductNotExist);
}
order.AddProduct (product);
store.SaveOrder (order);
context.Publish<OrderCreated> (new OrderCreated {
OrderId = order.Id;
});
} catch (DomainException exception) {
await context.Publish<CreateOrderRejected> (new CreateOrderRejected {
ErrorCode = domainException.Code;
});
}
}
Run Code Online (Sandbox Code Playgroud)