Проблема с вложенным чтением из очереди во внешней компоненте V8RMQClient


#1

Заметил, что компонента себя очень странно ведет в ситуации, когда во время начала чтения одного сообщения необходимо прочитать другое сообщение. Мы это используем, чтобы сначала прочитать данные (справочники, документы), а затем на основании этих данных прочитать нужную версию XSD схемы для них.

Псевдокод, при котором воспроизводится ошибка выглядит так:

Клиент = Новый ("AddIn.V8RMQClient.V8RMQClient")

Клиент.НачатьЧтение() // начинаем чтение из очереди 1 

Клиент.ПолучитьСообщение() // получаем данные из очереди 1

Клиент.НачатьЧтение() // получаем данные из очереди 2

Клиент.ПолучитьСообщение()  //  данные не получаются, никаких ошибок не возвращается, как будто очередь пустая

Клиент.ПодтвердитьСообщение() //  успешно подтверждаем сообщение из очереди 1

Клиент.ПолучитьСообщение()   // и теперь только получаем сообщение из очереди 2

Это глюк компоненты или чтение из компоненты, даже из разных очередей возможно только последовательно?


#2

На 5й строке желательно глянуть в веб морду кролика по этой очереди из которой не получаются данные и посмотреть список consumer’ов. А потом посмотреть открытое соединение в списке соединений и список открытых каналов.
Если каналов таки открылось 2, то скорее всего компонента обрабатывает каналы по-очереди, т.к. многопоточностью внутри одного сеанса 1с не пахнет.
Что-бы реализовать описанный сценарий, лучше создать 2 экземпляра компоненты, то есть будет 2 соединения и их вполне можно обрабатывать в том порядке, в котором нужно.
Но описанный сценарий лучше вообще не реализовывать, т.к. при получении данных из одной очереди ходить проверять наличие данных в другой - довольно странно. Схема довольно статична и ее лучше просто обновлять в отдельном задании.


#3

В этом методе проверяется присутствие канала и объявляется подписчик на очередь,

http://www.rabbitmq.com/amqp-0-9-1-reference.html#basic.consume

Клиент.НачатьЧтение() // получаем данные из очереди 2

Канал действует один на клиента - Один экземпляр компоненты = Один канал к одному серверу.

А вот методы НачатьЧтение - объявляют подписчика в текущем канале. Менять их можно - но метод

Клиент.ПолучитьСообщение() 

Будет заполнять текущие заголовки.

Отсюда

Клиент.ПодтвердитьСообщение() 

Будет работать с очередью на которую в данный момент подписаны. В вашем случае - на вторую.

Если данные НЕ получаются, значит их там нет

Клиент.НачатьЧтение() // получаем данные из очереди 2

Судя по всему - вы объявили подписчика на вторую очередь, достигли времени ожидания и продолжили выполнение кода дальше.

Судя по всему - по логике того что вы хотите сделать: у вас 2 канала доставки.

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


#4

А чем это плохо, и как предлагается делать?
Т.е. мы читаем данные из очереди с данными и обнаруживаем, что пришло сообщение с версией схемы, которой у нас еще нет (т.е. мы его разобрать не сможем). Что концептуально нужно делать в этом случае?:

  1. Прекращать чтение, и ждать следущей итерации (запуска регл. задания) в надежде, что схема появиться
  2. Читать как есть, а разибрать сообщение потом отдельно (когда схемапоявиться)
  3. Пробовать прочитать схему сразу же, и если не получиться, то дальше см. п.1.
  4. Что-то еще, что именно?

#5

@lustin @Bronislav
Разобрались с проблемой, спасибо за советы. Оказалось, что у нас не вызывался метод Клиент.ЗакончитьЧтение(). В итоге, чтобы организовать вложенное чтение сообщение нужно следующее:

  1. Использовать отдельную ком компоненту
  2. Обязательно закрывать канал с помощью метода Клиент.ЗакончитьЧтение()

#6

Чего ? Какую COM компоненту 7


#7

Я имел в виду отдельный экземпляр компоненты V8.RMQ.Client