Удаление сообщения из очереди, только если пользователь выполняет какую-либо операцию

У нас есть приложение MVC, которое считывает данные из MSMQ. Мы пытаемся найти способ прочитать сообщение из очереди и удалить его из очереди только в том случае, если пользователь выполнил успешную операцию в очереди. Сообщение должно оставаться в очереди до тех пор, пока пользователь не завершит обработку, сообщение не должно быть доступно никому другому, пока пользователь, обрабатывающий объект сообщения, не завершит операцию.

Есть ли свойство для объекта Message, которое должно быть установлено как Peeked, которое не позволит снова прочитать это сообщение, пока оно не будет возвращено в очередь или удалено из очереди?

Мы не уверены, является ли использование MSMQ хорошей идеей в этом случае?


person Balaji    schedule 02.09.2009    source источник
comment
Это похоже на то, что я настраивал. Как я это себе представлял, элементы добавляются в очередь (очередь — это таблица базы данных), а затем, когда они извлекаются процессом, они помечаются как «В процессе» и имеют отметку времени и остаются в таблице. После завершения процесса элемент удаляется из таблицы. Чтобы восстановиться после любых сбоев или потерянных элементов, каждую минуту появляется другой процесс и очищает флаг «В процессе» для всего, отметка времени которого старше 15 минут — намного дольше, чем на самом деле необходимо для завершения. Это как то, что вы предлагаете?   -  person SqlRyan    schedule 03.09.2009
comment
Именно это я и ищу. Также, если процесс не может успешно завершиться, сообщение должно быть добавлено обратно в очередь или сообщение должно быть помечено как доступное для получения на более позднем этапе. Не могли бы вы предложить, если использование MSMQ в этом случае является хорошим вариантом. Не могли бы вы рассказать мне, что вы использовали в своей настройке?   -  person Balaji    schedule 03.09.2009


Ответы (2)


Похоже, вам нужно использовать очереди в транзакционном режиме. Затем ваш клиент может получить сообщение, обработать его и затем зафиксировать транзакцию, после чего сообщение будет окончательно удалено из очереди. Однако, пока транзакция активна, другие клиенты не увидят это сообщение — оно будет храниться в резерве до тех пор, пока транзакция не завершится или не будет прервана.

В этой статье MSDN представлен достойный обзор шаблонов использования надежного обмена сообщениями с помощью MSMQ:

http://msdn.microsoft.com/en-us/library/ms978430.aspx

person rcoder    schedule 02.09.2009
comment
В этом случае мне придется передать объект транзакции на уровень пользовательского интерфейса. Это хорошая идея? Мы никогда не использовали транзакции MSMQ, поэтому любой ввод был бы нам очень полезен. - person Balaji; 03.09.2009
comment
Не зная больше о вашем приложении, я не могу с уверенностью сказать, является ли размещение логики транзакций в вашем слое просмотра хорошей идеей или нет, но в целом я бы не рекомендовал этого делать. - person rcoder; 03.09.2009
comment
В нашем приложении мы читаем сообщение из очереди. Объект сообщения отображается в представлении для пользователя. Пользователь может изменить значения при сохранении. В этот момент сообщение помещается в другую очередь. Мы хотим убедиться, что сообщение не потеряется в процессе чтения данных из очереди и выполнения операции сохранения (которая инициируется пользователем). Не могли бы вы предложить, уместно ли использование транзакции в этом случае? - person Balaji; 04.09.2009
comment
Я думаю, что сделка должна быть полностью уместной. Если ваше представление в настоящее время напрямую извлекает сообщения из очередей, я не вижу реального вреда в расширении его для обработки транзакций. Однако в какой-то момент вы можете захотеть установить уровень контроллера между вашим представлением и внутренними очередями, чтобы убедиться, что транзакции правильно запускаются и разрешаются. Повторная реализация одной и той же логики обработки сообщений в каждом представлении приведет к ненужному дублированию кода. - person rcoder; 04.09.2009

Очередь - правильная идея. Ваш подход «оставить его в очереди, заблокированным, но все еще доступным» неверен.

Вам может понадобиться несколько очередей.

  1. Процесс А ставит что-то в Очередь 1

  2. Процесс B удаляется из очереди из очереди 1 и начинает работу.

    • Если B успешен, это все.

    • В противном случае он ставится в очередь где-то еще (возможно, в той же очереди или, возможно, в очереди 2) для последующей работы.

Если он вернулся в Очередь 1, B в конце концов найдет его снова. Если он перешел в другую очередь, то другой процесс выполняет очистку, регистрацию, исправление ошибок или что-то еще, возможно, помещая что-то обратно в очередь 1.

Очередь не является базой данных — в ней нет состояния (никаких «не смотри на меня, меня обрабатывают»).

Очередь — это временное хранилище. Кто-то пишет, кто-то читает, и все.


Если вам нужна надежность, прочитайте это: http://msdn.microsoft.com/en-us/library/ms978430.aspx

А это: http://blogs.msdn.com/shycohen/archive/2006/02/20/535717.aspx

А это: http://www.request-response.com/blog/PermaLink,guid,03fb0e40-b446-42b5-ad90-3be9b0260cb5.aspx

Надежность — это особенность очереди, а не вашего приложения. Вы можете сделать «восстановимое чтение». Это транзакция, являющаяся частью API очереди.

person S.Lott    schedule 02.09.2009
comment
Если вы против того, чтобы оставить его в очереди, но заблокировать метод, как вы справляетесь со сбоями приложения или потерей подключения, если ваш процессор перестает работать? Я обеспокоен тем, что элементы, которые я удалил из очереди, чтобы я мог их обработать, никогда не вернутся в очередь, если она не завершена. Я могу написать код для исключений и обработать сбой, но боюсь пропустить какой-нибудь пограничный случай. - person SqlRyan; 03.09.2009
comment
Это именно та проблема, которая у нас есть. Как нам убедиться, что сообщение не будет потеряно после того, как мы прочитаем сообщение из очереди. - person Balaji; 03.09.2009