RabbitMq sequential data processing, missing message design - c#

I have a data queue with numbered messages that must be processed in order. When the subscriber receives a message (basicconsume with manual ack) and determines it missed a message I'm trying to do the following
Nack the message with requeue
Stop listening to data queue (basiccancel)
Start listening to error queue to get missed message, process msg (basicconsume)
Stop listening to error queue (basiccancel)
Start listening to data queue (basicconsume)
When I do this, the NACK message (#1) is immediately picked backup before the Stop Listening (#2). It seems like this should be straight forward and I'm just missing something. I'd like to avoid putting the Nack message into a 3rd queue, but it is what it is.
Thanks

Related

Send messages from Azure Service Bus queue to new asb queue

I have a message host that executes messages from asb queue. I want to create a new message host (scale up)(.NET core) when it first message host's load is up. In order to do so, I want to send some messages from one queue to another queue and then that (new) ,message host reads it from new asb queue. How is this possible?
There are 2 ways by which you can accomplish this:
Auto-forwarding: You can configure auto-forwarding on the 1st queue to forward messages to the 2nd queue automatically. In this case, as soon as the message arrives in the 1st queue, it will be forwarded to the 2nd queue. It will remove the message from the 1st queue though and both queues must be the part of same Namespace. You can learn more about it here: https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-auto-forwarding.
Azure Service Bus Triggered Function with Azure Service Bus Output Binding: In this case, the Function will be triggered when a message arrives in the queue. Because of output binding, this Function will send the message to another queue. You can learn more about it here: https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-service-bus?tabs=in-process%2Cextensionv5%2Cextensionv3&pivots=programming-language-csharp.

Rabbitmq move message to different queue if processing fails

I am working with RabbitMq .net and the message acknowledgements. If the consumer is able to process the message we can send back an ack in the form of
channel.BasicAck(ea.DeliveryTag, false);
which will take it off the queue. I would like to move the message to the "error-queue" if I have issues with deserialization
var message = JsonConvert.DeserializeObject<object>(json);
I have tried using "x-dead-letter-exchange" but it depends on "x-message-ttl" time setting. I do only want to move messages to error-queue if processing fails. How to achieve this funcationality? I couldn't find any help online.
If your consumer rejects the message using basic.reject or basic.nack with the requeue flag set to false, RabbitMQ will republish the message to the dead-letter exchange. This is documented in the article about dead-letter exchanges.
Here are the functions to reject or nack messages in the RabbitMQ .NET 3.6.10 client:
BasicNack(ulong deliveryTag, bool multiple, bool requeue)
BasicReject(ulong deliveryTag, bool requeue)

Can I set an explicit task timeout for RabbitMQ consumer?

I understand that RabbitMQ with ack, by default, will re-queue the message if it detects that the consumer/worker has died.
What about the situation where the consumer/worker is still alive but its process has stalled out for too long and didn't ack?
I would like to set an explicit time that says that if a message has been dispatched to a consumer but that consumer has held the message without ack for too long that the message gets re-queued.
I recognize that this might result in messages getting processed in duplicate but sometimes the consequence of that is not as bad as delayed message delivery.
It can also happen with errant exception handling if something get swallowed, the task terminates, and the message is never ack'd and never re-queued.
Timeout for RabbitMQ consumer could be explicitly set on the consumer side. I think this is clear but just to mention - there must not be any automatic ACKs in this case. The solution would be that the consumer is multithreaded with one thread doing message processing and ACKing the message only after it has been processed, and the other thread being a timeout thread that would:
terminate the connection to broker once the timeout has expired, and
as a consequence the message would be requeued
ACK the received message and re-publish it (explicitly)
NACK the received message, but based on the documentation (instructing the broker to either discard them or requeue them), it seems that some config should be set instructing the broker what should it do with NACKed messages
Now all this implies that at least some part of the process isn't stuck. If the whole process is stuck, perhaps the broker heartbeat towards the consumer is stopped and that is how the broker knows that the consumer died (honestly I didn't test this situation, so I'm assuming), but if this is not the case (or simply to be extra safe) you could add some kind of a watchdog process that would be pinging the consumer(s) and killing them if there's no reply, which again would lead to the messages not being ACKed and being requeued.

With MSMQ AcknowledgeTypes.NegativeReceive, is there a way to know what queue that generated the acknowledgement?

I am sending a message with AcknowledgeTypes.NegativeReceive with a time to be received set so that if the message isn't received off the destination queue within that time frame, a negative receive message is sent to my administration queue. This works fine. The problem is that I want to know which queue the message couldn't be received from.
When I check the message of the negative acknowledgement, there's no hint of the original queue to which the message was sent.
What I'm trying to accomplish is to treat the negative acknowledgement as an event to divert message traffic to a different queue but I need to know the queue to divert away from and that appears not to be retained in the negative acknowledgement message by default.
Is there a way to get the original destination queue out of an acknowledgment message?
UPDATE
What appears to be happening is the DestinationQueue.Path in the acknowledgement message is set to the Outgoing queue on the target machine which is some GUID\ID, e.g.
I found it. It is the ResponseQueue property of the acknowledgment message. Overlooked that.

Why does MassTransit not push messages to MSMQ unless a subscriber is present? How is this worked-around?

I'm using MassTransit + MSMQ as a message passing bus, which seems to be having reasonable success. However, for some tests I want to enqueue messages but never dequeue them. It seems like the right way to do this is to not subscribe to the queue directly. Here is my code:
1) I want to send and receive messages from the same queue in this process [this works]:
var solrMessageBus = ServiceBusFactory.New(sbc =>
{
sbc.UseMsmq();
sbc.VerifyMsmqConfiguration();
sbc.ReceiveFrom("msmq://localhost/my_queue");
sbc.Subscribe(subs =>
{
subs.Handler<MyMessage>(msg => Enqueue(msg));
});
});
2) I want to send messages from this process, but not consume them. MSMQ should build up a large queue of messages [this does not work]
var solrMessageBus = ServiceBusFactory.New(sbc =>
{
sbc.UseMsmq();
sbc.VerifyMsmqConfiguration();
sbc.ReceiveFrom("msmq://localhost/my_queue");
});
I'm not a MassTransit expert, but the above seems like a reasonable way to enqueue without dequeuing messages from that same queue. In 1), I see messages end up in my MSMQ, but in 2) no messages ever get to the queue.
How can I build up the queue without dequeuing the messages?
If you do not register any subscriptions on the bus, the queue will be emptied and all of the message sent to the queue will end up in the _error queue.
If you need to just send messages to a queue, you can use an EndpointCacheFactory (instead of a service bus factory) to get an IEndpointCache, then call GetEndpoint(uri) and use the Send method to send messages to that queue. This has the added benefit of avoiding any thread pool usage for receiving messages that are never consumed.
Also, a quick reminder, every service bus instance must have its own queue.
That sounds reasonable however I've never tried it.
Mass Transit builds the subscription mapping out of your setup and then maps subscriptions to queues (using multicast subscription). Note that messages are never stored in queues assigned to senders, rather they are multicasted to subscribers. No subscribers = nowhere to put your messages.
To queue messages forever, I would add a subscriber but pause its consumer thread until tests are completed.

Categories