Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Masstransit EndpointConvention Azure Service Bus

Tags:

masstransit

I'm wondering if I'm doing something wrong, I expected MassTransit would automatically register ReceiveEndpoints in the EndpointConvention.

Sample code:

services.AddMassTransit(x =>
{
    x.AddServiceBusMessageScheduler();
    x.AddConsumersFromNamespaceContaining<MyNamespace.MyRequestConsumer>();
    x.UsingAzureServiceBus((context, cfg) =>
    {
        // Load the connection string from the configuration.
        cfg.Host(context.GetRequiredService<IConfiguration>().GetValue<string>("ServiceBus:ConnectionString"));
        cfg.UseServiceBusMessageScheduler();

        // Without this line I'm getting an error complaining about no endpoint convention for x could be found.
        EndpointConvention.Map<MyRequest>(new Uri("queue:queue-name"));

        cfg.ReceiveEndpoint("queue-name", e =>
        {
            e.MaxConcurrentCalls = 1;
            e.ConfigureConsumer<MyRequestConsumer>(context);
        });

        cfg.ConfigureEndpoints(context);
    });
});

I thought this line EndpointConvention.Map<MyRequest>(new Uri("queue:queue-name")); wouldn't be necessary to allow sending to the bus without specifing the queue name, or am I missing something?

await bus.Send<MyRequest>(new { ...});

like image 502
Stephan Avatar asked Jul 03 '20 10:07

Stephan


1 Answers

The EndpointConvention is a convenience method that allows the use of Send without specifying the endpoint address. There is nothing in MassTransit that will automatically configured this because, frankly, I don't use it. And I don't think anyone else should either. That stated, people do use it for whatever reason.

First, think about the ramifications - if every message type was registered as an endpoint convention, what about messages that are published and consumed on multiple endpoints? That wouldn't work.

So, if you want to route messages by message type, MassTransit has a feature for that. It's called Publish and it works great.

But wait, it's a command, and commands should be Sent.

That is true, however, if you are in control of the application and you know that there is only one consumer in your code base that consumes the KickTheTiresAndLightTheFires message contract, publish is as good as send and you don't need to know the address!

No, seriously dude, I want to use Send!

Okay, fine, here are the details. When using ConfigureEndpoints(), MassTransit uses the IEndpointNameFormatter to generate the receive endpoint queue names based upon the types registered via AddConsumer, AddSagaStateMachine, etc. and that same interface can be used to register your own endpoint conventions if you want to use Send without specifying a destination address.

You are, of course, coupling the knowledge of your consumer and message types, but that's your call. You're already dealing with magic (by using Send without an explicit destination) so why not right?

string queueName = formatter.Consumer<T>()

Use that string for the message types in that consumer as a $"queue:{queueName}" address and register it on the EndpointConvention.

Or, you know, just use Publish.

like image 51
Chris Patterson Avatar answered Oct 16 '22 19:10

Chris Patterson