Masstransit: IConsumer<Fault<T>> can not handle exceptions

Created on 15 Mar 2016  路  4Comments  路  Source: MassTransit/MassTransit

Hi,
I have a question when using the interface IConsumer<Fault<T>> to handle the exception messages. Below is my code snippet:

public class UpdateInventoryConsumer : IConsumer<UpdateInventory>
    {
        public async Task Consume(ConsumeContext<UpdateInventory> context)
        {
            if (Math.Abs(context.Message.Qty) > 100)
                throw new Exception("The limit Qty is great than abs(100)");

            await Console.Out.WriteLineAsync($"Updating Inventory-> Qty:{context.Message.Qty} to {context.Message.Location}-{context.Message.ProductId} When {context.Message.Timestamp}");
        }
    }
public class UpdateInventoryFaultConsumer : IConsumer<Fault<UpdateInventoryConsumer>>
    {
        private readonly ILog _log = Logger.Get<UpdateInventoryFaultConsumer>();
        public async Task Consume(ConsumeContext<Fault<UpdateInventoryConsumer>> context)
        {
            var originalMessage = context.Message.Message;
            var exceptions = context.Message.Exceptions;

            Array.ForEach(exceptions, ex => _log.Info($"received exception:{ex.Message}"));

            await Console.Out.WriteLineAsync($"discarding message:{JsonConvert.SerializeObject(originalMessage)}");
        }
    }

I handle the exceptions using the method e.Consumer<T>() with Fault<T>class(UpdateInventoryFaultConsumer).but it is not running when fault message comming. So using the newest Masstransit, how can I consume fault message?

public bool Start(HostControl hostControl)
        {
            _log.Info("Creating bus...");

            _busControl = Bus.Factory.CreateUsingRabbitMq(x =>
            {
                IRabbitMqHost host = BusInitializer.CreateRabbitMqHost(x);

                x.ReceiveEndpoint(host, "Samples.TestQueue", e =>
                {
                    e.UseRetry(Retry.Immediate(5));
                    e.Consumer<UpdateInventoryConsumer>();
                    e.Consumer<UpdateInventoryFaultConsumer>();
                });
            });

            _log.Info("Starting bus...");

            _busControl.Start();

            return true;
        }

Most helpful comment

The _Fault_ is with the message, not the consumer. So change your second method to include:

public class UpdateInventoryFaultConsumer :
    IConsumer<Fault<UpdateInventory>>
 {
    private readonly ILog _log = Logger.Get<UpdateInventoryFaultConsumer>();
    public async Task Consume(ConsumeContext<Fault<UpdateInventory>> context)
    {
        var originalMessage = context.Message.Message;
        var exceptions = context.Message.Exceptions;

        Array.ForEach(exceptions, ex => _log.Info($"received exception:{ex.Message}"));

        await Console.Out.WriteLineAsync($"discarding message:{JsonConvert.SerializeObject(originalMessage)}");
    }
}

All 4 comments

The _Fault_ is with the message, not the consumer. So change your second method to include:

public class UpdateInventoryFaultConsumer :
    IConsumer<Fault<UpdateInventory>>
 {
    private readonly ILog _log = Logger.Get<UpdateInventoryFaultConsumer>();
    public async Task Consume(ConsumeContext<Fault<UpdateInventory>> context)
    {
        var originalMessage = context.Message.Message;
        var exceptions = context.Message.Exceptions;

        Array.ForEach(exceptions, ex => _log.Info($"received exception:{ex.Message}"));

        await Console.Out.WriteLineAsync($"discarding message:{JsonConvert.SerializeObject(originalMessage)}");
    }
}

@phatboyg
Thanks so much it works. When fault message handled,it moved to the queue "_error_skipped"

_error_skipped queue should not be created its wrong

@phatboyg What if I need other specific exception parameters? For example, if the Exception is a FaultException and I need to log the TDetail data? Is that possible?

Thanks in advance,

Eduardo Monteiro de Barros

Was this page helpful?
0 / 5 - 0 ratings