我希望能够从死信队列中删除选定的消息。
这是如何实现的?
我不断收到错误:
操作无法完成,因为 RecieveContext 为 Null
我已经尝试了我能想到和读到的所有方法,这就是我现在的位置:
public void DeleteMessageFromDeadletterQueue<T>(string queueName, long sequenceNumber)
{
var client = GetQueueClient(queueName, true);
var messages = GetMessages(client);
foreach(var m in messages)
{
if(m.SequenceNumber == sequenceNumber)
{
m.Complete();
}
else
{
m.Abandon();
}
}
}
/// <summary>
/// Return a list of all messages in a Queue
/// </summary>
/// <param name="client"></param>
/// <returns></returns>
private IEnumerable<BrokeredMessage> GetMessages(QueueClient client)
{
var peekedMessages = client.PeekBatch(0, peekedMessageBatchCount).ToList();
bool getmore = peekedMessages.Count() == peekedMessageBatchCount ? true : false;
while (getmore)
{
var moreMessages = client.PeekBatch(peekedMessages.Last().SequenceNumber, peekedMessageBatchCount);
peekedMessages.AddRange(moreMessages);
getmore = moreMessages.Count() == peekedMessageBatchCount ? true : false;
}
return peekedMessages;
}
不知道为什么这似乎是一项艰巨的任务。
最佳答案
这里的问题是您调用了 PeekBatch,它返回刚刚查看的消息。没有可用于完成或放弃消息的接收上下文。即使将 receiveMode 设置为 PeekLock,Peek 和 PeekBatch 操作也仅返回消息并且根本不锁定消息。它主要用于浏览队列,但您无法对它们采取操作。请注意文档中的“放弃”和“完成”状态,“只能在使用以 Peek-Lock ReceiveMode 操作的接收器接收到的消息上调用”。这里不清楚,但 Peek 和 PeekBatch 操作不计入其中,因为它们实际上并没有获得接收上下文。这就是当您尝试调用放弃时它会失败的原因。如果您确实找到了您要查找的内容,那么当您调用 Complete 时,它会抛出不同的错误。
您想要做的是在 PeekBatch RecieveMode 中使用 ReceiveBatch 操作。这实际上会拉回一批消息,然后当您查看它们以找到您想要的消息时,您实际上可以影响消息的完整性。当您触发放弃时,它会立即将不是您想要的消息释放回队列。
如果您的死信队列非常小,通常这不会太糟糕。如果它真的很大,那么采用这种方法并不是最有效的。您将死信队列更像是一个堆并对其进行挖掘,而不是“按顺序”处理消息。在处理需要手动干预的死信队列时,这种情况并不罕见,但如果您有很多死信队列,那么最好将死信队列处理到不同类型的存储中,这样您可以更轻松地找到和处理死信队列。销毁消息,但仍然可以重新创建可以推送到不同队列进行重新处理的消息。
如果您手动进行死字处理,可能还有其他选项,例如使用 Defer。请参阅How to use the MessageReceiver.Receive method by sequenceNumber on ServiceBus 。
关于azure - 完成 Azure 服务总线上死信队列中的消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33620999/