How retrieve single message from queue EasyNetQ? - c#

I am trying to implement the following solution: How to programmatically resend messages that have faulted with EasyNetQ? . One of the goals of this solution is to retrieve a single message from a given queue with the EasyNetQ library and without using subscriptions.
Regarding that, I am opening a new topic, because I cannot find any trace of the method GetMessageAsync in interface IAdvancedBus.
My code with unresolved method looks like that:
var message = await advancedBus.GetMessageAsync(errorQueue);
Do you know where I can find this method or if there is some other way to solve this?

Related

Send Message when NServiceBus Recoverability fails using Notifications

How can I send a message (or publish an event) when a message runs out of retries and moves to the error queue?
When a request comes into my system, I create a Saga to track it. The Saga sends commands to Handlers to do async work. If the handler fails, I want to both move that command to the error queue (the default behavior) and send a message to the Saga to alert the client that originally requested the work.
I have tried customizing the recoverability behavior to use the Saga as the error queue, which sends the command back but does not get it into the error queue:
recoverability.CustomPolicy((config, context) =>
{
// invocation of default recoverability policy
var action = DefaultRecoverabilityPolicy.Invoke(config, context);
if (action is MoveToError)
{
return RecoverabilityAction.MoveToError("SagaEndpoint");
}
return action;
});
Another thing I tried was using a Behavior to hook into the Pipeline, but there does not seem to be a a way to override the "move to error queue" step. I can create an IIncomingLogicalMessageContext and try/catch around the await next();, but that triggers for each retry instead of just the final one. I also tried an IOutgoingLogicalMessageContext, but that does not get invoked when a message moves to the error queue. If I missed something, that could be a solution.
I also know I can use a timeout in the Saga to guess when the Handler fails. But I would rather not wait for a timeout if the failure is quick or risk timing out if the work takes longer than expected.
I found this older question that sounds like it's asking the same thing, but the answer is incomplete and uses the older EventHandler Notifications instead of the newer Task-based Notifications. If there is a way to access an IMessageSession or IEndpointInstance from the Notification callback, I think that would work for me as well.
There's not an "easy" way to do that because at the moment when recoverability is happening, any transaction related to the incoming message (this is different for each transport) is in doubt, so you can't really do anything else within the scope of what's going on right at that moment.
Once you start your endpoint, you can cast the IEndpointInstance to an IMessageSession (same thing without things like the Stop method) and then assign that to a place where your "error queue notifier" will be able to find it. Then any operation you do with the IMessageSession will basically be a separate context, disconnected from the processing of the incoming message.
Just understand that if the message is failing processing because of an underlying problem with the queue, that's not going to report correctly. That's why most people would be doing some sort of call to a reporting/diagnostics service in those callbacks.

Deleting command messages after sending them

I started to write my own bot for a discord server using Discord.net. I already made the first command (which still doesn't work correctly, but that's for another story), and now that I am testing, it has a chat full of commands I sent. My goal is to instantly delete those messages as I send them (let's say I send .command something, and this should appear in a chat just for a little moment). I tried to look it up in documentation and some tutorials but couldn't find anything. I have only basic knowledge of programming, so I would be happy if you could tell me how to achieve this and explain how it works.
To answer the question of how to delete a message, you use the Context.Channel.DeleteMessageAsync function. It takes a message id as the parameter, so you will need to have the message data in memory at the time.
To answer the question of how to delete a message that you have just sent, you can use the above delete function alongside the Context.Message data which gives you the message data of the message that triggered the command. It will look like the following:
[Command("TestDelete")]
public async TestDeleteCommand()
{
await Context.Channel.DeleteMessageAsync(Context.Message.Id);
}
You can find more information of the DeleteMessageAsync function by looking at the Discord.Net docs

EasyNetQ/RabbitMQ - Publishing a message based on topic

I have created a subscriber in EasyNetQ/RabbitMQ with a topic. I think I have atleast because I can see that there is a binding under a queue name. It looks like the following :
The Queue name itself is a random GUID. But I don't think this matters.
However when I try and publish a message via EasyNetQ like so :
await _bus.PublishAsync(new Message<byte[]>(memoryStream.ToArray()), "QueueCallback");
The message never gets published onto the above queue.
Worked this out.
I was publishing inside a message wrapper, however I was subscribing as a byte array only. Even if the routing key is the same, if the object type is not an exact match it will never be routed.

Threaded Windows Service - SmtpClient Issues

We're writing a threaded service using topshelf / windsor / masstransit to pick up messages off of MSMQ and then send an e-mail off with PDF attachment.
Every now and again the SmtpClient.Send() method throws this error message:
An asynchronous call is already in progress. It must be completed or canceled before you can call this method.
I've got the SmtpClient set up as .LifeStyle.Transient in Windsor, so my understanding is that each thread should get its own instance?
Any idea how I can around this, short of locking that part of the code. Which would kind of defeat the purpose of the threads.
Thanks in advance
Transient shouldn't just create a new instance per thread, but a new instance for every request.
I'd try to confirm that you're truly getting a new instance of SmtpClient - make sure you're not sticking it in a static field or otherwise somehow ending up with the same reference. You could try spitting the result from GetHashCode() into the Console each time you send an email to see if they're all using the same object.
Failing that, my only suggestion is to try and strip it down to a really simple example - if you don't find the issue in doing this, you can post the code here and someone might be able to help.

Websphere MQ Message Read

At the moment I have a C# service that is reading messages off the queue (Websphere MQ) and writing them in a database.
Everytime I do a GET the message dissappears from queue. I would like an additional functionality though. I prefer to read a message off the queue and remove it in from the queue only after the write in the database was succesful. Please note I do all these in a multithreaded application. I know there is a way to browse the queue but this doesn't really provide the functionality I need.
I'm writing my firts WMQ application, and I know I'll run into this issue very soon, so I found your question.
I've found this http://www.mqseries.net/phpBB2/viewtopic.php?t=43043&sid=11ad2d587dbd19056836ccc3f8943e5f (specifing MQOO_BROWSE option while opening the queue) in other forum, I haven't tried it yet, but it think it worth a try...
[]'s
I have implemented similar functionality in C++. Hopefully this helps you or someone.
You can browse messages without removing them from the queue using options MQGMO_BROWSE_FIRST and MQGMO_BROWSE_NEXT.
How do I browse a Websphere MQ message without removing it?
Store message identifiers in a list or in any other suitable data structure.
Write messages to the database.
Then get messages from the queue normally without BROWSE option. ImqQueue::Get takes two parameters: options and ImqMessage. Set message identifier to ImqMessage-class before calling get. ImqMessage acts as a filter. You can select
only those messages that have been written successfully to the database.
http://publib.boulder.ibm.com/infocenter/wmqv7/v7r0/index.jsp?topic=%2Fcom.ibm.mq.amqzan.doc%2Fuc10330_.htm

Categories

Resources