Очередь Azure генерирует исключение для DeleteMessage

Я работаю над проектом на основе Azure для некоторых исследований и столкнулся с некоторыми проблемами при удалении сообщений из экземпляра CloudQueue. Код довольно прост, поэтому я немного сбит с толку, почему возникает исключение, когда я пытаюсь удалить сообщение из очереди.

Вот код, который производит данные для очереди:

foreach (var cell in scheme(cells))
{
    string id = Guid.NewGuid().ToString();
    var blob = sweepItemContainer.GetBlobReference(id);
    using (BlobStream stream = blob.OpenWrite())
    {
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(stream, cell);
    }
    sweepItemQueue.AddMessage(new CloudQueueMessage(id), new TimeSpan(1, 0, 0));
}

Вот код, который потребляет данные из очереди:

var msgs = sweepItemsQueue.GetMessages(MsgAmt);
foreach (var msg in msgs)
{
     _handleMessage(msg, sweepItemsContainer);
     sweepItemsQueue.DeleteMessage(msg);
     mergeItemsQueue.AddMessage(new CloudQueueMessage(msg.AsString), new TimeSpan(1, 0, 0));
}

Я не понимаю, почему сообщение не может находиться в очереди. Ничто другое не изменяет очередь, кроме других потребителей. Но я уверен, что они не могут получить одно и то же сообщение (пока не истечет временной интервал), так как же это происходит?


person Nicholas Mancuso    schedule 06.04.2011    source источник
comment
Есть ли разница во времени между вызовом первого блока кода (добавление сообщений в очередь) и вторым блоком (когда вы удаляете сообщения из очереди)? Также каково значение MsgAmt в вашем вызове GetMessages ()?   -  person Gaurav Mantri    schedule 06.04.2011
comment
Должна быть разница во времени. Код находится в разных ролях: производитель отправляет все сообщения, а «рабочие роли» являются потребителями. MsgAmt определен в файле конфигурации, но в настоящее время равен 5.   -  person Nicholas Mancuso    schedule 06.04.2011
comment
Причина, по которой я спросил разницу во времени, заключается в том, что при создании сообщения вы устанавливаете TTL сообщения равным 1 часу, поэтому сообщение будет автоматически собираться мусором через 1 час. Если разница во времени между 1-м и 2-м блоками кода превышает час, вы не найдете сообщения.   -  person Gaurav Mantri    schedule 06.04.2011
comment
Всего несколько секунд или несколько минут прямо сейчас, максимум. Не прошло и часа.   -  person Nicholas Mancuso    schedule 06.04.2011
comment
Я забыл спросить, какое исключение вызывает ваш код? И вы получаете исключение, когда вызываете DeleteMessage (), правильно?   -  person Gaurav Mantri    schedule 06.04.2011
comment
MessageDoesNotExist выбрасывается строкой sweepItemsQueue.DeleteMessage (msg);   -  person Nicholas Mancuso    schedule 06.04.2011


Ответы (2)


Есть два тайм-аута, о которых вам нужно беспокоиться: как долго сообщение находится в очереди (которое вы указали в своем вызове .AddMessage(), и тайм-аут видимости, который устанавливается при вызове .GetMessages() (по умолчанию это 30 секунд, там это перегрузка, которая позволяет указать время ожидания). Когда вы звоните .GetMessages() все возвращенные сообщения невидимы для других потребителей в течение периода visibilityTimeout. По окончании этого периода все сообщения, которые вы еще не удалили, становятся видимыми для всех других потребителей.

Чтобы проверить, является ли это проблемой, я бы попытался использовать перегрузку .GetMessages() с максимальным таймаутом видимости 2 часа. Если это проблема, вы можете уменьшить это значение до более разумного. Другой вариант - просто получать по одному сообщению за раз.

person knightpfhor    schedule 06.04.2011
comment
Вот и все! Спасибо. Я понятия не имел о том втором тайм-ауте. Я изменил его на .GetMessages (MsgAmt, ts), и теперь он отлично работает. - person Nicholas Mancuso; 06.04.2011

Другой ответ от Стива Маркса: в основном посмотрите на исключение хранилища и двигайтесь дальше. Я видел это и в других фреймворках: блог Стива Маркса сообщение

 try
 {
    q.DeleteMessage(msg);
 }
 catch (StorageClientException ex)
 {
 if (ex.ExtendedErrorInformation.ErrorCode == "MessageNotFound")
 {
     // pop receipt must be invalid
     // ignore or log (so we can tune the visibility timeout)
 }
 else
 {
    // not the error we were expecting
     throw;
 }
}
person ElvisLives    schedule 29.05.2012