Search code examples
easynetq

EasyNetQ - how can I include the original queue name in the EasyNetQ_Default_Error_Queue message?


When using the Publisher/Subscriber pattern and an exception is throwed during a subscriber handling, EasyNetQ, by default, put a message in the EasyNetQ_Default_Error_Queue.

The problem is I only have the original exchange name in the error message. What I really need is the original queue name, so I can republish the message to the queue, not to the exchange.

How can I include the queue name in the error message?

Sample error message in the 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\":\"[email protected]\",\"ToEmail\":\"[email protected]\",\"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
   }
}

Solution

  • I figured out a solution.

    I had to register an extended version of the DefaultConsumerErrorStrategy class to IConsumerErrorStrategy of my bus:

    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);
        }
    }
    

    Now I have the original queue name in my message Headers property. Works for me.