rebus-org / Rebus.RabbitMq

:bus: RabbitMQ transport for Rebus
https://mookid.dk/category/rebus
Other
62 stars 44 forks source link

Rebus org - Receive message from one queue 'inputQueue' and send message to another queue 'outputQueue' in Message Handler Transaction #73

Closed bagalsamadhan closed 3 years ago

bagalsamadhan commented 3 years ago

We are reading message from one queue, in handler receiving message, we want to do some code and at last want to send message to another queue using single rebus using handler transaction. As Message handler having parameter bus, its same bus instance which receiving also and sending message from handler using single bus.

Scenario: Receive message in handler and send message from handler using same bus is possible. Receiving message could be redelivered if rejected or nack, once succeeded we want to send message to other queue which is difference than receiving queue. Do you have any example to do better way or took inspiration from it.

bagalsamadhan commented 3 years ago

Welcome for quick update.

mookid8000 commented 3 years ago

I guess this is one of the most basic use cases for Rebus: Receiving a message and sending another 🙂 check this out!

To configure Rebus, you go

Configure.With(...)
    .(...)
    .Start();

or

services.AddRebus(configure => (...));
// followed by
serviceProvider.UseRebus();

depending on which type of IoC container you are using. You can read more about that on the Container adapters page.

When you pick the transport, you also choose which input queue you'd like to receive messages from – so e.g. if you're using Azure Service Bus and you want to receive messages from the queue good-stuff, then you'd do something like

services.AddRebus(config=> config.Transport(t => t.UseAzureServiceBus(connectionString, "good-stuff")));

Now this Rebus instance will receive everything put into the good-stuff queue. If you then want it to be able to handle a specific type of message, e.g. DoGood, then you'd add a handler for that message like this

services.AddRebusHandler<DoGoodHandler>();

and then the handler could look like this:

public class DoGoodHandler : IHandleMessages<DoGood>
{
    readonly IBus _bus;

    public DoGoodHandler(IBus bus) //< this is ALWAYS the receiving bus!
    {
        _bus = bus;
    }

    public async Task Handle(DoGood message)
    {
        // do good in here
    }
}

So now we should be able to receive AND handle messages of type DoGood put into the good-stuff queue – last thing is to send a new message somewhere else.

Let's pretend that there's another queue, somewhere-else, where we have to send another message of type AnotherMessage. There's a couple of ways of doing that, where the one you're encouraged the most to use, is by using an endpoint mapping.

Endpoint mappings is a configuration that tells Rebus who OWNS each type of message, which to Rebus will mean that any attempt to await bus.Send(thatMessage) will result in that message being sent to the owner.

In your case, we would extend the configuration to look like this:

services.AddRebus(
    config=> config
        .Transport(t => t.UseAzureServiceBus(connectionString, "good-stuff"))
        .Routing(r => r.TypeBased().Map<AnotherMessage>("somewhere-else"))
);

and then inside our message handler we can simply do

await _bus.Send(new AnotherMessage());

and it will be sent to somewhere-else.

Rebus will automatically handle ACK/NACK depending on whether your handler throws an exception, and re-delivery will by default happen 5 times before Rebus gives up and moves the incoming message to a queue named error.

I hope this gives a clear example on how you can achieve what you're after – let me know if you have any more questions 🙂