Checking status of message insert to Azure Queue - c#

I have 1 problem about Azure Queue. After insert 1 message to Azure Queue, how can I check this message have been inserted successful or not in my code (.net)?
My solution is checking number of message already storage in queue and check again after insert new message queue. I try to find another solution. Thank for helping me

Update:
The design of method 'AddMessageAsync' in Microsoft.WindowsAzure.Storage.Queue is like this:
public virtual Task AddMessageAsync(CloudQueueMessage message);
It returns nothing, so you have two ways:
The first one is like you says, get the number of the messages in queue and check after Add message.
The second one is put the logic in the try-catch, return exception if add message not success.
Original Answer:
Have a look of this API reference:
https://learn.microsoft.com/en-us/dotnet/api/azure.storage.queues.queueclient.sendmessage?view=azure-dotnet
The return type of the sendmessage method is response, so I think you don't need to get the number of the messages. Just check the response status is OK.

Related

Azure Service Bus - Leave message

(FYI - I am new ASB)
A couple of questions around Azure Service Bus:
How do you get a message from a Queue but leave it there until its' TTL expires? I would have thought simply not calling CompleteMessageAsync would do just that, but it appears to get removed regardless.
How do get a message from a Queue, but only dequeue (remove) it when received by a specific receiver?
Message.ApplicationProperties["ReceiverId"].ToString() == "123"
// now you can remove it
Thanks
How do you get a message from a Queue but leave it there until its' TTL expires?
You can peek at messages rather than receive them. The problem is that the message will be picked up again and again until the delivery count exceeds the maximum and the message will dead-letter, which you don't want to happen. I would review what you're trying to achieve here as it's a contradictory setup. You want the message to have a TTL in anticipation that it's not picked up, but then you want to probe it until TTL expires continuedly.
How do get a message from a Queue, but only dequeue (remove) it when received by a specific receiver?
My advice is don't use a queue for that. If you target a specific destination, express it with your entity topology. For example: publish a message on a topic and have different subscriptions based on the subscriber identification. That way you can have messages for specific subscribers, where a logical subscriber can be scaled out.
1-Use the PeekMessage:
You can peek at the messages in the queue without removing them from
the queue by calling the PeekMessages method. If you don't pass a
value for the maxMessages parameter, the default is to peek at one
message.
//-------------------------------------------------
// Peek at a message in the queue
//-------------------------------------------------
public void PeekMessage(string queueName)
{
// Get the connection string from app settings
string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];
// Instantiate a QueueClient which will be used to manipulate the queue
QueueClient queueClient = new QueueClient(connectionString, queueName);
if (queueClient.Exists())
{
// Peek at the next message
PeekedMessage[] peekedMessage = queueClient.PeekMessages();
// Display the message
Console.WriteLine($"Peeked message: '{peekedMessage[0].Body}'");
}
}
https://learn.microsoft.com/en-us/azure/storage/queues/storage-dotnet-how-to-use-queues?tabs=dotnet
2-you can also use PeekMessage, check for the property you want (ReceiverId), and it case it's the right one, just complete the message:
// ServiceBusReceiver
await receiver.CompleteMessageAsync(receivedMessage);

Apache NMS using ActiveMQ: How do I use transactional acknowledge mode but still acknowledging/rolling back a single message every time?

I use Apache NMS (in c#) to receive messages from ActiveMQ.
I want to be able to acknowledge every message I received, or roll back a message in case I had an error.
I solved the first part by using the CreateSession(AcknowledgementMode.IndividualAcknowledge), and then for every received message I use message.Acknowledge().
The problem is that in this mode there is no Rollback option. if the message is not acknowledged - I can never receive it again for another trial. It can only be sent to another consumer, but there isn't another consumer so it is just stucked in queue.
So I tried to use AcknowledgementMode.Transactional instead, but here there is another problem: I can only use session.Commit() or session.Rollback(), but there is no way to know which specific message I commit or role back.
What is the correct way to do this?
Stay with INDIVIDUAL_ACKNOWLEDGE and then try session.recover() and session.close(). Both of those should signal to the broker that the messages are not going to be acknowledged.
My solution to this was to throw an exception if (for any reason (exception from db savechanges event for example)) I did not want to acknowledge the message with message.Acknowledge().
When you throw an exception inside your extended method of IMessageConsumer Listener then the message will be sent again to your consumer for about 5 times (it will then moved to default DLQ queue for investigation).
However you can change this using the RedeliveryPolicy in connection object.
Example of Redelivery
Policy redeliveryPolicy = new RedeliveryPolicy
{
InitialRedeliveryDelay = 5000, // every 5 secs
MaximumRedeliveries = 10, // the message will be redelivered 10 times
UseCollisionAvoidance = true, // use this to random calculate the 5 secs
CollisionAvoidancePercent = 50,// used along with above option
UseExponentialBackOff = false
};
If message fails again (after 10 times) then it will be moved to a default DLQ queue. (this queue will be created automatically)
You can use this queue to investigate the messages that have not been acknowledged using an other consumer.

Service bus topic inserted duplicate message record for same MessageId

[FunctionName("MyProcess")]
public static void Run(BrokeredMessage currentMessage,[ServiceBus("mytopic",
Connection = "ConnServiceBus")]ICollector<BrokeredMessage> mytopicDemo, TraceWriter log)
{
string messageBody = currentMessage.GetBody<string>();
BrokeredMessage brokeredMessage = new BrokeredMessage(result);
//extracted Id and Name from body using some code for simplicity making it as messageBody.Id and messageBody.Name
brokeredMessage.Properties.Add("Id", messageBody.Id);
brokeredMessage.Properties.Add("Name", messageBody.Name);
brokeredMessage.MessageId = "ZZ"; // I also tried GUID here messageBody.Id
mytopicDemo.Add(brokeredMessage);
...
service bus unable to identify duplicate messageId message.
It isinserting multiple records for same messageId why?
It should avoid toinsert duplicate record if it is already present.
The probable causes might be
If an application encounters a fatal error immediately after it sends
a message, and the restarted application instance erroneously
believes that the prior message delivery did not occur, a subsequent
send causes the same message to appear in the system twice.
It is also possible for an error at the client or network level to
occur a moment earlier, and for a sent message to be committed into
the queue, with the acknowledgment not successfully returned to the
client. This scenario leaves the client in doubt about the outcome of
the send operation.
Enabling duplicate detection solves this problem by discarding the duplicate messages.
The duplicate detection time history defaults to 30 seconds for queues and topics, with a maximum value of 7 days.
The duplicate detection time history must be large to detect as much as duplicate messages .Also note that the size of the window directly impact the queue (and topic) throughput.
Click here for more information.

Azure Storage Queue - processing messages on poison queue

I've been using Azure Storage Queues to post messages too, then write the messages to a db table. However I've noticed that when an error occurs processing messages on the queue, the message is written to a poison queue.
Here is some background to the setup of my app:
Azure Web App -> Writes message to the queue
Azure function -> Queue trigger processes the message and writes the contents to a db
There was an issue with the db schema which caused the INSERTS to fail. Each message was retried 5 times, which I believe is the default for retrying queue messages, and after the 5th attempt the message was placed on the poison queue.
The db schema was subsequently fixed but now I've no way of processing the messages on the poison queue.
My question is can we recover messages written to the poison queue in order to process them and INSERT them into the db, and if so how?
For your particular problem, I would recommend solution mentioned in question part of this post: Azure: How to move messages from poison queue to back to main queue?
Please note that name of poison queue == $"{queueName}-poison"
In my current project I've created something what is called: "Support functions" in the FunctionApp. It exposes a special HTTP endpoint with Admin authorization level that can be executed at any time.
Please See the code below, which solves the problem of reprocessing messages from the poison queue:
public static class QueueOperations
{
[FunctionName("Support_ReprocessPoisonQueueMessages")]
public static async Task<IActionResult> Support_ReprocessPoisonQueueMessages([HttpTrigger(AuthorizationLevel.Admin, "put", Route = "support/reprocessQueueMessages/{queueName}")]HttpRequest req, ILogger log,
[Queue("{queueName}")] CloudQueue queue,
[Queue("{queueName}-poison")] CloudQueue poisonQueue, string queueName)
{
log.LogInformation("Support_ReprocessPoisonQueueMessages function processed a request.");
int.TryParse(req.Query["messageCount"], out var messageCountParameter);
var messageCount = messageCountParameter == 0 ? 10 : messageCountParameter;
var processedMessages = 0;
while (processedMessages < messageCount)
{
var message = await poisonQueue.GetMessageAsync();
if (message == null)
break;
var messageId = message.Id;
var popReceipt = message.PopReceipt;
await queue.AddMessageAsync(message); // a new Id and PopReceipt is assigned
await poisonQueue.DeleteMessageAsync(messageId, popReceipt);
processedMessages++;
}
return new OkObjectResult($"Reprocessed {processedMessages} messages from the {poisonQueue.Name} queue.");
}
}
Alternatively it may be a good idea to create a new message with the additional metadata (as information that the message has already been processed in the past with no success - then it may be send to the dead letter queue).
You have two options
Add another function that is triggered by messages added to the poison queue. You can try adding the contents to the db in this function. More details on this approach can be found here. Of course, if this function too fails to process the message you could check the dequeue count and post a notification that needs manual intervention.
Add an int 'dequeueCount' parameter to the function processing the queue and after say 5 retries log the failure instead of letting the message go the poison queue. For example you can send an email to notify that manual intervention is required.
You can use azure management studio(cerulean) and move the message from poison queue to actual queue. Highly recommended tool to access queues and blobs and do any production related activity also. https://www.cerebrata.com/products/cerulean
I am just user of the tool and no way affiliated, i recommended because it is very powerful, very useful and makes you very productive.
Click on move and message can be moved to the actual uploaded queue
Just point your Azure function to the poison queue and the items in that poison queue will be handled. More details here: https://briancaos.wordpress.com/2018/05/03/azure-functions-how-to-retry-messages-in-the-poison-queue/
Azure Storage Explorer(version above 1.15.0) has now added support to move messages from one queue to another. This makes it possible to move all, or a selected set of messages, from the poison queue back to the original queue.
https://github.com/microsoft/AzureStorageExplorer/issues/1064

How to remove message from message queue (only if its well formatted)?

I want to take message from one queue and send it to database. I want to do it only if it's in specific format.
If i use Receive method directly and some exception occurs while accessing Body of the Message, I lose the message since Receive method of the MessageQueue removes the message from the queue.
To avoid loss of message, now i first Peek the message, and if its well formatted, I use Receive method to remove it from the queue to send it to database.
Code I have written is like this:
Message msg = _queue.Peek(new TimeSpan(0, 0, LoggingService.Configuration.ReceiveTimeout));
// LogMessage is my own class which is adding some more stuff to original message from MessageQueue
LogMessage message = null;
if (msg != null)
{
if (!(msg.Formatter is BinaryMessageFormatter))
msg.Formatter = new BinaryMessageFormatter();
message = LogMessage.GetLogMessageFromFormattedString((string) msg.Body);
// Use Receive method to remove the message from queue. This line will we executed only if the above line does not
// throw any exception i.e. if msg.Body does not have any problem
Message wellFormattedMsg =
_queue.ReceiveById(msg.Id);
SendMessageToDatabase(message);
}
Is this logic right to first using Peek and then Receive? Or is there any other better way f achieving the same thing? Please note that I dont want to get all messages at a time. MessageQueue is non transactional.
This is the same approach that I take when manually dequeuing message one at a time and I've not come across any issues with it.
The one thing that you do not appear to dealing with is how to handle a message on the queue that does not have the required format. Is your intention to leave it on the queue? If so, you might end up with a very large queue and have all sorts of issues with peeking at messages further up the queue that have not yet been expected. It would appear to make more sense to also de-queue those messages that do not have the required format and store them elsewhere if they cannot be deleted.
"If i use Receive method directly and some exception occurs while accessing Body of the Message, I lose the message since Receive method of the MessageQueue removes the message from the queue."
You should be using transactional receives so that the message returns to the queue when/if the transaction aborts.
Cheers
John Breakwell

Categories