How I can subscribe to one queue by multiple consumers using MassTransit? - c#

I'm using Azure Service Bus as transport for MassTransit and I'm trying to send message(command) to queue:
var sendEndpoint = await busControl.GetSendEndpoint(sericeUri);
sendEndpoint.Send<ISimpleRequest>(new SimpleRequest(customerId));
Also I try to connect to this queue by two consumers:
var _busControl = Bus.Factory.CreateUsingAzureServiceBus(cfg =>
{
var host = cfg.Host("...", h =>
{
h.OperationTimeout = TimeSpan.FromMinutes(1);
});
cfg.ReceiveEndpoint(host, "queueName",
e => { e.Consumer<RequestConsumer>(); });
cfg.UseServiceBusMessageScheduler();
});
The same code with same queue name for second consumer.
After I send message only one consumer get the response. So how I can config this to work with two or more consumers?

If you want to get two copies of the message, one for each consumer, you should use two separate queues and Publish the message. In this case, MassTransit will send it to the topic, and each queue will receive a copy forwarded from the topic.

Related

RabbitMQ queue name define

I started working on Microservices. So I have made two Restful APIs.
Organisations API ( GET, PUT, POST, DELETE )
Customers API ( GET, PUT, POST, DELETE )
These two are separate APIs and hosted on different ports on my local IIS.
Now I want to consume them in my main application.
So the requirement is to call them only by Network connection.
I found that I need to use Rpc, gRpc or Kafka.
so, I have decided to use Rpc by using RabbitMq and EasyNetQ.
By this, I have configured rabbiqMq in docker and it is running successfully.
What I am not understanding is that in my Organisations and Customers API there are multiple actions. GET, PUT, POST, DELETE
So, Where I need to define the queue name for those method, so I can consume it in my main app by calling with some name. and it will directly call that method.
e.g.
var factory = new ConnectionFactory() { HostName = "localhost" };
var connection = factory.CreateConnection();
var channel = connection.CreateModel();
var body = Encoding.UTF8.GetBytes(entity);
channel.BasicPublish(exchange: "organisations", routingKey: "organisations.add", basicProperties: null, body: body);
Where in the organisations api, I will define this organisations.add, organisations.update, organisations.search ?
Can I add them dynamically through some mediator ?
Or I need to add manually in the rabitmq ui .. to adding queue ?
I usually use IBus.Publish for publishing message it supports strong type and also it detects the Exchange and Queue name automatically.
Let's assume you have a Message class for adding organizations like this:
[Queue("Organisations.Add", ExchangeName = "Organisations.Add")]
public class Message
{
public string Text { get; set; }
public DateTime Date { get; set; }
}
And for publish a message to broker:
using (var bus = RabbitHutch.CreateBus("host=localhost"))
{
var message = new Message() { Text = "Hello World", Date = DateTime.Now };
bus.Publish<Message>(message);
}
So you can create multiple messages based on api and use them in Mediator.

Unable to set default tags for every queues in Amazon SQS using nservice bus

Currently, I have to switch our messaging system to use AmazonSQS and due to pricing policy, we are obliged to put tags. But I do not found any method to add tags.
Below the method which won't work due to fact that this approach is expecting that the queues already exist and I can get URL of the queue:
public static EndpointConfiguration CreateEndpointConfiguration(BusConfig config)
{
var endpointConfiguration = new EndpointConfiguration(config.QueueName);
endpointConfiguration.LicensePath("license.xml");
endpointConfiguration.SendFailedMessagesTo($"{config.QueueName}.Errors");
endpointConfiguration.EnableInstallers();
endpointConfiguration.UseSerialization<NewtonsoftSerializer>();
endpointConfiguration.LimitMessageProcessingConcurrencyTo(10);
endpointConfiguration.Conventions()
.DefiningEventsAs(type => typeof(IMessage).IsAssignableFrom(type))
.DefiningCommandsAs(type => typeof(ICommand).IsAssignableFrom(type));
var transport = endpointConfiguration.UseTransport<SqsTransport>();
transport.ClientFactory(() =>
{
var amazonSQSConfig = new AmazonSQSConfig()
{
RegionEndpoint = RegionEndpoint.USWest2
};
var client = new AmazonSQSClient(amazonSQSConfig);
var addedTags = new Dictionary<string, string>();
addedTags.Add("Team", "Development");
addedTags.Add("Accounting ID", "number");
var tagQueueRequest = new TagQueueRequest()
{
Tags = addedTags
};
client.TagQueueAsync(tagQueueRequest);
return client;
});
transport.QueueNamePrefix("some-prefix");
endpointConfiguration.Recoverability()
.AddUnrecoverableException<CustomException>();
return endpointConfiguration;
}
Can you provide solution for adding automatically tags during configuring endpoints?
Thank you for any help
The NServiceBus integration with SQS doesn't seem to support configuration of tags at the moment. You'd have to manually create your queues upfront with the appropriate tags or manually add tags to existing queues.
You can raise feature requests for tag support on Particular Software's SQS transport repository here: https://github.com/Particular/NServiceBus.AmazonSQS

Creating Azure Service Bus with Rule with MassTransit

I'm using masstransit to consume messages from an azure service bus. It's going greate for nom but I need now to add filter rules to my subscription.
I found some posts on the subject, like this one:
Is there a way to define a Azure Service Bus rule/filter when setting up a consumer?
but without many success...
My subscription is created properly when configuring my consumers like this, but it has the $Default 1=1 filter.
cfg.SubscriptionEndpoint<MyMessage>(mySubscription, cfg =>
{
se.Consumer<MyConsumer>(x => x.UseConcurrentMessageLimit(1));
});
I would like to add a different filter, but when I do this, the creation of the subscription seems to fail silently
cfg.SubscriptionEndpoint<MyMessage>(mySubscription, cfg =>
{
cfg.Rule = new CreateRuleOptions
{
Name = "Receiver filter",
Filter = new SqlRuleFilter("receiver='all'")
};
se.Consumer<MyConsumer>(x => x.UseConcurrentMessageLimit(1));
});
I'm I missing something?
I found my mistake... Everything is fine except for one thing. The rule name does not support spaces.
cfg.Rule = new CreateRuleOptions
{
Name = "ReceiverFilter", // instead of "Receiver filter"
Filter = new SqlRuleFilter("receiver='all'")
};

Exchanging NServiceBus messages with native implementation of Azure Service Bus

Consuming a message published with NServiceBus, using IQueueClient/Functions-ServiceBusTrigger (Microsoft.Azure.ServiceBus)
I'm working in a WebJob using .NET Core and Microsoft.Azure.ServiceBus to consume a message that has been published by a separate service using NServiceBus. My initial approach with this WebJob was to use a class Functions.cs with a method ProcessMessage that uses the attribute ServiceBusTrigger
Below is an example of how my Function.cs looks like:
public class Functions
{
public Task ProcessAuditLogMessage([ServiceBusTrigger("MyQueue")]
Message message)
{
var messageBody = Encoding.UTF8.GetString(message.Body);
var auditLogMessage = JsonConvert
.DeserializeObject<MyMessage>(messageBody);
_logger.Information("Hello World");
return Task.CompletedTask;
}
}
In Program.cs, I have:
class Program
{
static async Task Main()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddWebJobs(o => o.AllowPartialHostStartup = true);
var builder = new HostBuilder()
.UseServiceProviderFactory(
new AutofacServiceProviderFactory(serviceCollection))
.ConfigureContainer<ContainerBuilder>(b =>
{
BuildAutofacContainer();
})
.ConfigureWebJobs(b =>
{
b.AddServiceBus(o =>
{
o.ConnectionString = configProvider.AuditLogServiceBus;
});
});
var host = builder.Build();
using (host)
{
await host.RunAsync();
}
}
private static IContainer BuildAutofacContainer(IServiceColletion
serviceCollection)
{
...
}
}
I was expecting that this logic would consume the messages published in the Queue but so far the messages get moved to the Dead-letter count with a DeadLetterReason: MaxDeliveryCountExceeded and the error description Message could not be consumed after 10 delivery attempts which gives me the indication that at least there is an attempt to get these messages delivered to my consumer.
Unfortunately that's all I have in terms of error messages/logs (I'm in the process to set up some logs from my Azure Dashboard and see if I can get more detailed logs)
Has anyone come across the scenario o having to consume messages, that have been published with NServiceBus, using Microsoft.Azure.ServiceBus instead of NServiceBus (on the consumer side). Maybe I'm missing something...

RabbitMQ what will happen if service that consumed the message will shut down

I created consumer and producer using MassTransit:
var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
var host = cfg.Host(messageBrokerUri, h =>
{
h.Username(communicationConfiguration.MessageBrokerUsername);
h.Password(communicationConfiguration.MessageBrokerPassword);
});
cfg.ReceiveEndpoint(host, communicationConfiguration.FileResultAggregationServiceAddress, ec =>
{
ec.Consumer(serviceCollection.GetRequiredService<IFileResultAggregationConsumer>);
});
});
busControl.Start();
My question is: if the consumer consume message1 and in the middle i will shut down the consumer service then rabbitMQ will not get an ack. after 2 minutes the consumer will be alive.
What will happen to message1?
If the message will gone, how can i use Masstransit to make the message not disappear

Categories

Resources