EasyNetQ - 如何在 EasyNetQ_Default_Error_Queue 消息中包含原始队列名称?

标签 easynetq

当使用发布者/订阅者模式并且在订阅者处理期间引发异常时,EasyNetQ 默认情况下会将消息放入 EasyNetQ_Default_Error_Queue 中。

问题是错误消息中只有原始交换名称。我真正需要的是原始队列名称,这样我就可以将消息重新发布到队列,而不是交换器。

如何在错误消息中包含队列名称?

EasyNetQ_Default_Error_Queue 中的示例错误消息:

{
   "RoutingKey": "",
   "Exchange": "EiHD.Application.Restaurant.Events.RestaurantDeliveryMailChanged:EiHD",
   "Exception": "System.AggregateException: Um ou mais erros. ---> System.NullReferenceException: Referência de objeto não definida para uma instância de um objeto.\r\n   em EiHD.Infrastructure.Mailing.EmailSender.OnEvent(RestaurantDeliveryMailChanged evt) na d:\\Projetos\\EatInHouseDelivery\\sln\\Infrastructure\\Mailing\\EmailSender.cs:linha 136\r\n   em EiHD.Infrastructure.EventDispatching.EasyNeqQEventDispatcher.<>c__DisplayClass5`1.<RegisterListener>b__4(T evt) na d:\\Projetos\\EatInHouseDelivery\\sln\\Infrastructure\\EventDispatching\\EasyNeqQEventDispatcher.cs:linha 68\r\n   em EasyNetQ.RabbitBus.<>c__DisplayClass6`1.<Subscribe>b__5(T msg)\r\n   --- Fim do rastreamento de pilha de exceções internas ---\r\n---> (Exceção Interna N° 0) System.NullReferenceException: Referência de objeto não definida para uma instância de um objeto.\r\n   em EiHD.Infrastructure.Mailing.EmailSender.OnEvent(RestaurantDeliveryMailChanged evt) na d:\\Projetos\\EatInHouseDelivery\\sln\\Infrastructure\\Mailing\\EmailSender.cs:linha 136\r\n   em EiHD.Infrastructure.EventDispatching.EasyNeqQEventDispatcher.<>c__DisplayClass5`1.<RegisterListener>b__4(T evt) na d:\\Projetos\\EatInHouseDelivery\\sln\\Infrastructure\\EventDispatching\\EasyNeqQEventDispatcher.cs:linha 68\r\n   em EasyNetQ.RabbitBus.<>c__DisplayClass6`1.<Subscribe>b__5(T msg)<---\r\n",
   "Message": "{\"FromEmail\":\"<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c2b1adafa7a7afa3abae82a5afa3abaeeca1adaf" rel="noreferrer noopener nofollow">[email protected]</a>\",\"ToEmail\":\"<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f1909f9e85999483949c90989db1969c90989ddf929e9c" rel="noreferrer noopener nofollow">[email protected]</a>\",\"RestaurantName\":\"SomeRestaurant\"}",
   "DateTime": "2015-10-25T19:20:17.2317949Z",
   "BasicProperties": {
      "ContentType": null,
      "ContentEncoding": null,
      "Headers": {},
      "DeliveryMode": 2,
      "Priority": 0,
      "CorrelationId": "f212f734-6cd7-41fe-ac71-09335f44bb2c",
      "ReplyTo": null,
      "Expiration": null,
      "MessageId": null,
      "Timestamp": 0,
      "Type": "EiHD.Application.Restaurant.Events.RestaurantDeliveryMailChanged:EiHD",
      "UserId": null,
      "AppId": null,
      "ClusterId": null,
      "ContentTypePresent": false,
      "ContentEncodingPresent": false,
      "HeadersPresent": true,
      "DeliveryModePresent": true,
      "PriorityPresent": false,
      "CorrelationIdPresent": true,
      "ReplyToPresent": false,
      "ExpirationPresent": false,
      "MessageIdPresent": false,
      "TimestampPresent": false,
      "TypePresent": true,
      "UserIdPresent": false,
      "AppIdPresent": false,
      "ClusterIdPresent": false
   }
}

最佳答案

我想出了一个解决方案。

我必须将 DefaultConsumerErrorStrategy 类的扩展版本注册到总线的 IConsumerErrorStrategy:

this.bus = RabbitHutch.CreateBus(this.connectionString, (serviceRegister) => {
    serviceRegister.Register<IConsumerErrorStrategy>((sp) => new ExtendedConsumerErrorStrategy(sp.Resolve<IConnectionFactory>(), sp.Resolve<ISerializer>(), sp.Resolve<IEasyNetQLogger>(), sp.Resolve<IConventions>(), sp.Resolve<ITypeNameSerializer>()));
});

public class ExtendedConsumerErrorStrategy : DefaultConsumerErrorStrategy
{
    public ExtendedConsumerErrorStrategy(IConnectionFactory connectionFactory, ISerializer serializer, IEasyNetQLogger logger, IConventions conventions, ITypeNameSerializer typeNameSerializer)
        : base(connectionFactory, serializer, logger, conventions, typeNameSerializer)
    {   
    }

    public override AckStrategy HandleConsumerError(ConsumerExecutionContext context, Exception exception)
    {
        context.Properties.Headers.Add("OriginalQueue", context.Info.Queue);
        return base.HandleConsumerError(context, exception);
    }
}

现在,我的消息 header 属性中有原始队列名称。对我有用。

关于EasyNetQ - 如何在 EasyNetQ_Default_Error_Queue 消息中包含原始队列名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33334261/

相关文章:

rabbitmq - 是否有一种简单的方法可以订阅 EasyNetQ 中的默认错误队列?

当机器非常活跃时,RabbitMQ/EasyNetQ 会断开连接吗?

c# - 如何在 EasyNetQ 中为每个消费者声明自定义错误交换?

c# - MVC - WCF - RabbitMQ - 通过消息队列到消费者的域事件加速或替代方案?

c# - 来自工厂方法的 Autofac 单例

c# - 在 ASP.NET Core 2.x 中实现 EasyNetQ 发布/订阅模式的正确方法是什么?

rabbitmq - 如何处理 RabbitMq 发布失败的情况?

asp.net-web-api - RabbitMQ 与 Web API + SignalR

c# - 无法通过 EasyNetQ 连接 RabbitMQ,拒绝用户 guest 访问