简体   繁体   中英

How to use the MessageReceiver.Receive method by sequenceNumber on ServiceBus

I'm trying to resubmit a message from a deadletter queue.

I am can replay a message on a dead letter queue, thats fine. The problem is when I want to now delete this from the deadletter queue.

Here is what I am trying to do:

var subscription = "mySubscription";
var topic = "myTopic";

var connectionString = "connectionStringOnAzure";
var messagingFactory = MessagingFactory.CreateFromConnectionString(connectionString);

var messageReceiver = messagingFactory.CreateMessageReceiver(SubscriptionClient.FormatDeadLetterPath(topic, subscription), ReceiveMode.ReceiveAndDelete);


long messageSequenceNumber = 835;
var brokeredMessage = messageReceiver.Receive(messageSequenceNumber);  // this part fails

// mark message as complete to remove from the queue
brokeredMessage.Complete();

I get following error message:

 Microsoft.ServiceBus.Messaging.MessageNotFoundException : Failed to lock one or more specified messages. The message does not exist..TrackingId:ae15edcc-06ac-4d2b-9059-009599cf5c4e_G5_B15,TimeStamp:8/13/2013 1:45:42 PM

However, instead of specifying a message sequence number and I just use the ReceiveBatch as shown below, it is fine.

// this works and does not throw any errors
var brokeredMessages = messageReceiver.ReceiveBatch(10);

Am I missing something? Or is there another way of reprocessing deadletters and removing them?

The deadletter queue is processed in sequence just like any other queue.

The Receive(seqNo) method is used in combination with Defer(), which puts the message into a different secondary Queue - the "deferral queue". The deferral queue exists for scenarios where you are getting messages out of the expected order (eg. in a state machine) and need a place to put the messages that arrived early. Those you can park with Defer() and make a note of that (probably even in session state) and then pull the messages once you're ready to do so. The Workflow Manager runtime used by SharePoint uses that feature, for instance.

After creating receiver you can politely start receiving all messages (without being picky) till you encounter message with your SequenceNumber, call Complete() on the message and stop iterating the queue. ie

        while (true)
        {
            BrokeredMessage message = receiver.Receive();
            if (message.SequenceNumber == sequenceNumber)
            {
                message.Complete();
                break;
            }
        }

Without completing message it remains in the queue and that's what you want (at least in .NET 4.5. Worth to note that if your Sequence Number is not found Receiver will loop the queue indefinitely.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM