0

I want to use MassTransit to send messages that may have different structures in terms of message.Data, to different Azure Service Bus queues. As long as the router.Name keeps the initial value, it works welll. But, whenever the destination Uri of EndpointConvention.Map<ManyToOneTransferMessage> changes, an exception is thrown by MassTransit as "The endpoint convention has already been created and can no longer be modified". Is there any way to remap the message type with another destination to use MassTransit with multiple queues?

public class AzureServiceBusManager
{
    string ServiceBusConnectionString = string.Empty;

    public AzureServiceBusManager()
    {
        ServiceBusConnectionString = ConfigurationManager.AppSettings["AppSettings:ServiceBusConnectionString"];
    }

    public async Task SendMessageAsyncN1(TransferMessage transferMessage, Router router)
    {
        var message = new ManyToOneTransferMessage
        {
            BlobFileName = transferMessage.BlobFileName,
            Compressed = transferMessage.Compressed,
            Data = transferMessage.Data,
            MessageId = transferMessage.MessageId,
            TransferId = transferMessage.TransferId,
            TransferType = transferMessage.TransferType
        };

        var queueBusControl = Bus.Factory.CreateUsingAzureServiceBus(
                    cfg =>
                    {
                        cfg.Host(ServiceBusConnectionString);
                        EndpointConvention.Map<ManyToOneTransferMessage>(new Uri("queue:" + router.Name));
                        cfg.ReceiveEndpoint(router.Name, e =>
                        {
                            e.RequiresSession = true;
                            e.MaxConcurrentCalls = 500;
                        });
                    });

        await queueBusControl.Send(message);
    }
}

1 Answers1

0

So, first of all, do not use EndpointConvention.Map<ManyToOneTransferMessage>(new Uri("queue:" + router.Name));. It isn't useful, and only adds to the confusion.

You can resolve the endpoint from the bus, but you have to realize that creating a bus for each call is a bad idea. It is best to start the bus at startup (you aren't even starting it in the code above), and stop it at application shutdown.

Then, for each call, you can use that bus to resolve the send endpoint and send the message.

var endpoint = await bus.GetSendEndpoint(new Uri("queue:" + router.Name));

await endpoint.Send(message);

Also, you should remove this since it will cause all messages to be moved to the _skipped queue:

cfg.ReceiveEndpoint(router.Name, e =>
{
    e.RequiresSession = true;
    e.MaxConcurrentCalls = 500;
});

You'll likely need to configure the queues separately, in advance, if you requireSession, although I don't see you setting a SessionId on the message so it likely will not work anyway without one.

Chris Patterson
  • 28,659
  • 3
  • 47
  • 59
  • Thank you @Chris, resolving the endpoint via bus worked well. Injecting bus is a task to do. I have a questions. Why would the lines; cfg.ReceiveEndpoint(router.Name, e => { e.RequiresSession = true; e.MaxConcurrentCalls = 500; }); cause all messages to be moved to the __skipped_ queue – Ahmet Said Feb 04 '21 at 17:21
  • Because there are no consumers or sagas on it. – Chris Patterson Feb 04 '21 at 21:37