Oracle AQ с ODP.Net. Автоматически отключать при подключении

Я использую Oracle ODP.Net для постановки и снятия с очереди.

Процесс A: постановка в очередь Процесс B: постановка в очередь с событием MessageAvailable

Если процессы A и B запущены, проблем нет. В "Процессе Б" событие всегда запускается.

Но если "Процесс B" выключен, а "Процесс А" включен, то, когда "Процесс В" перезапускается, очереди, вставленные во время отключения, теряются.

Есть ли возможность для запуска события для всех очередей, вставленных в прошлом?

Большое спасибо

2 ответа

Кажется, есть два подхода к решению этой проблемы:

  1. Вызовите метод Listen() класса OracleAQQueue (после регистрации уведомления о сообщении), чтобы забрать "осиротевшие" сообщения, находящиеся в очереди. Обратите внимание, что Listen() блокируется до тех пор, пока не будет получено сообщение или не истечет время ожидания. Таким образом, вы хотите указать (короткий) тайм-аут, чтобы вернуться к потоку обработки, если в очереди нет сообщений.
  2. Вызовите метод Dequeue() и перехватите сообщение об ошибке Oracle 25228 (сообщение не доступно для удаления из очереди). Смотрите следующую ветку на форумах поддержки Oracle: https://forums.oracle.com/forums/thread.jspa?threadID=2186496.

Я почесал голову на эту тему. Если вам все еще нужно "вручную" проверять наличие новых сообщений, в чем преимущество использования обратного вызова события MessageAvaiable? Один из способов, который я обдумал, - обернуть метод Listen() в асинхронный вызов, чтобы вызывающая сторона не блокировала поток (до тех пор, пока не будет получено сообщение или не истечет время ожидания). Я обернул Listen() и Dequeue() в собственный метод Receive() и создал свой собственный обработчик событий MessageReceived, чтобы передать детали сообщения в вызывающий поток. Кажется несколько избыточным, поскольку ODP.NET обеспечивает обратный вызов "из коробки", но мне не нужно иметь дело с описанной вами проблемой (или писать код для "ручного" тестирования "осиротевших" сообщений).

Любые комментарии / мысли о подходе приветствуются.

Я тоже смотрел на это и закончил тем, что делал что-то похожее на Грега. Я не использовал метод Listen(), так как не думаю, что он предлагает мне что-то сверх простой Dequeue() - Listen() кажется полезным, когда вы хотите слушать от имени нескольких потребителей, которые в Мой экземпляр не имеет значения (см. Oracle Docs).

Итак, в моем "Процессе Б" я сначала регистрируюсь на получение уведомлений, прежде чем инициировать процесс опроса для проверки любых существующих сообщений. Он не слушает (), он просто вызывает Dequeue () в управляемом цикле с установленным периодом ожидания в несколько секунд. Если в процессе опроса обнаружен таймаут Oracle, период ожидания истек, и опрос останавливается. Возможно, мне придется рассмотреть вопрос об истечении времени ожидания, если период ожидания еще не истек (хотя не уверен на 100%, если это произойдет).

Я заметил, что любые сообщения, которые ставятся в очередь во время опроса, будут вызывать метод уведомления о сообщениях, но к тому времени, когда это подключается и пытается получить сообщение, процесс опроса, кажется, всегда его принимает. Поэтому внутри метода уведомления о сообщении я фиксирую и игнорирую любые исключения OracleException с номером 25263 (no message in queue <...> with message ID <...>).

Другие вопросы по тегам