1

I have a worker service and an api service using Mass Transit - Azure Message Bus. The api acts as a sender, the worker acts as a receiver.

In the worker service, I created a consumer which consumes the message from the queue. However, while the consumer is processing the message from Azure message queue, Mass Transit automatically re-initializes the consumer and triggers the Consume method to handle the same message again.

Are there any configurations on Mass Transit to prevent this from happening? All I need is that for one specific message, only one consumer instance should pick up and process the message, the other consumer instances (on different servers) of the same message type should not pick it up while it is being processed by the other one.

On Azure there is a ReceiveAndDelete mode over the Peek-Mode, but I don't know how to enable this setting on top of Mass Transit.

The API configuration

public static IServiceCollection AddMessageBusConfig(this IServiceCollection services, IDictionary<string, string> messageBusOptions) 
    {
        var queuePrefix = messageBusOptions["QueuePrefix"];
        return services.AddMassTransit(x =>
        {
            EndpointConvention.Map<MigrateAccountancy.Command>(new Uri($"queue:{queuePrefix}-migrate-accountancies-event"));
            x.UsingAzureServiceBus((context, cfg) =>
            {
                cfg.Host(messageBusOptions["ConnectionString"]);
                cfg.ConfigureEndpoints(context);
            });
        });
    }

The Worker service configuration

public static IServiceCollection AddMessageBus(this IServiceCollection services, IDictionary<string, string> messageBusOptions) 
    {
        var queuePrefix = messageBusOptions["QueuePrefix"];
        return services.AddMassTransit(x =>
        {
            x.AddConsumer<MigrateAccountancyConsumer>();
            x.UsingAzureServiceBus((context, cfg) =>
            {
                cfg.Host(messageBusOptions["ConnectionString"]);
                cfg.ReceiveEndpoint($"{queuePrefix}-migrate-accountancies-event", e =>
                {
                    // skip move message to _error queue on exception since errors are logged in Application Insight
                    e.DiscardFaultedMessages();
                    e.ConfigureConsumer<MigrateAccountancyConsumer>(context, c => 
                    {
                        
                    });
                });
            });
        });
    }

Consumer

public class MigrateAccountancyConsumer : IConsumer<MigrateAccountancy.Command>
{
    private readonly IMediator _mediator;
    public MigrateAccountancyConsumer(IMediator mediator) 
    {
        _mediator = mediator;
    }

    public async Task Consume(ConsumeContext<MigrateAccountancy.Command> context)
    {
        await _mediator.Send(context.Message);
    }
}

As you can see above, the Consume method automatically re-triggers during the processing of the same message.

Appreciate for your helps.

Kiet Duong
  • 43
  • 4
  • Similar issue: https://stackoverflow.com/questions/69204011/a-consumer-consumes-the-same-message-many-times-masstransit – Kiet Duong Aug 17 '22 at 06:12

1 Answers1

0

I don't believe you can configure the ReceiveMode with MassTransit. You can try setting the ConcurrentMessageLimit to 1 and see if that solves the issue.

x.UsingAzureServiceBus((context, cfg) =>
{
    cfg.Host(messageBusOptions["ConnectionString"]);

    cfg.ConcurrentMessageLimit = 1 //Broker level

    cfg.ReceiveEndpoint($"{queuePrefix}-migrate-accountancies-event", e =>
    {
        //cfg.ConcurrentMessageLimit = 1 //Endpoint level
    });
});
Sean Ervinson
  • 123
  • 3
  • 12