Git Product home page Git Product logo

pinkrabbitmq's Introduction

В БИТ:ERP открыты вакансии разработчиков 1С, присоединяйся к нашей команде!

PinkRabbitMQ library

License GitHub release

Sonar bugs Sonar code smells Sonar dublications Sonar lines of code Sonar technical debt Sonar vulnerables

Введение

Внешняя Native API компонента для 1C 8.3, которая реализует методы для работы с сервером Rabbit MQ через TCP IP протокол. Компонента поддерживается командой разработки БИТ.MDT (Мобильный терминал данных), БИТ.Адаптер, БИТ.IIoT (Промышленный интернет вещей) и используется в наших продуктах. Ид компоненты - PinkRabbitMQ. Компонента поставляется для 32 и 64 битной платформы 1С.

Поддерживаемые системы

  • Windows 32 и 64 бит
  • Linux 64 бит

API

Компонента реализует протокол AMQP 0.9.1. Компонента имеет ряд методов для работы из встроенного языка 1С. Параметры с тегом [НЕ РЕАЛИЗОВАНО] имеют пустую реализацию, но передавать их все равно требуется. Параметры с тегом [НЕОБЯЗАТЕЛЬНЫЙ] можно не передавать.

Список свойств комоненты, связанных с сообщением:

  • correlationId - строка, чтение и запись
  • messageId - строка, чтение и запись
  • Type - строка, чтение и запись
  • AppId - строка, чтение и запись
  • ContentEncoding - строка, чтение и запись
  • ContentType - строка, чтение и запись
  • UserId - строка, чтение и запись. В данное свойство разрешается передавать только логин пользователя, использованный для установки соединения
  • ClusterId - строка, чтение и запись
  • Expiration - число строкой, чтение и запись. Передача строки, отличной от числовой, приведет к вызову исключения.
  • ReplyTo - строка, чтение и запись

Эти свойства передаются в качестве метаданных вместе с сообщением в RabbitMQ. Их можно прочитать также на стороне получателя - они реинициализируется в момент вызова basicConsumeMessage().

Список прочих свойств:

  • Version - версия компоненты, только чтение

Список методов:

Connect - устанавливает соединение с сервером RabbitMQ. Таймаут - 5 секунд. Если в течение этого времени сервер недоступен, а также указаны неверные логин, пароль или vhost, то будет возвращена ошибка, которая может быть получена через метод GetLastError.

Параметры:

  • host - Строка - Адрес сервера RabbitMQ
  • port - Число - Порт работы через tcp (обычно 5672 для amqp и 5671 для amqps)
  • login - Строка - Имя пользователя
  • pwd - Строка - Пароль пользователя
  • vhost - Строка - Vhost пользователя
  • pingRate - Число - [НЕ РЕАЛИЗОВАНО][НЕОБЯЗАТЕЛЬНЫЙ]. Частота пульса
  • secure - Булево - [НЕОБЯЗАТЕЛЬНЫЙ] использовать защищенное соединение по протоколу TLS 1.2. По-умолчанию Ложь. Если Истина, то нужно также передавать соответствующий порт для amqps соединения
  • timeout - Число - [НЕОБЯЗАТЕЛЬНЫЙ] время ожидания ответа на команды от сервера в секундах. По-умолчанию 5

DeclareExchange - Объявить точку обмена

Параметры:

  • name - Строка - Имя exchange
  • type - Строка - Тип точки обмена. Поддерживаются "direct", "fanout", "topic"
  • onlyCheckIfExists - Булево - Не создавать новую, выбросить исключение, если такой точки нет.
  • durable - Булево - Сохранять сообщения на диске на случай рестарта RMQ (не рекомендуется)
  • autodelete - Булево - Удалить после того, как от точки будут отвязаны все очереди.
  • arguments - Строка - [НЕОБЯЗАТЕЛЬНЫЙ] произвольные свойства в формате Json-объект. Пример: {"x-message-ttl": 60000}.

DeleteExchange - Удалить точку обмена

Параметры:

  • name - Строка- Имя точки обмена.
  • ifunused - Булево - Удаление будет выполнено, только если точка обмена не используется.

DeclareQueue - Объявить очередь

Параметры:

  • name - Строка - Имя объявляемой очереди.
  • onlyCheckIfExists - Булево - Не создавать очередь с таким именем, использовать существующую
  • save - Булево - Кешировать сообщения на диске, на случай падения RMQ.
  • exclusive - Булево - Только текущее соединение может иметь доступ к этой очереди.
  • autodelete - Булево - Удалить очередь если к ней был подключен, а затем отключен читающий клиент.
  • maxPriority - Число - [НЕОБЯЗАТЕЛЬНЫЙ] устанавливает максимальное значение приоритета, которое может быть затем установлено для отправляемых сообщений через метод setPriority. Если 0 - то приоритет не используется. По-умолчанию 0.
  • arguments - Строка - [НЕОБЯЗАТЕЛЬНЫЙ] произвольные свойства в формате Json-объект. Пример: {"x-message-ttl": 60000}. Документация: https://www.rabbitmq.com/queues.html#optional-arguments

Возвращаемое значение:

  • Имя очереди, заданное явно в 1-м параметре.

DeleteQueue - Удаляет очередь с сервера

Параметры:

  • name - Строка - Имя очереди
  • onlyIfIdle - Булево - Удаление будет выполнено, только если очередь не используется
  • onlyIfEmpty - Булево - Удаление будет выполнено, только если очередь пуста

BindQueue - Установить связь очереди. Создает маршрут от точки обмена до очереди.

Параметры:

  • queue - Строка - Имя очереди
  • exchange - Строка - Имя точки обмена
  • routingKey - Строка - Rлюч маршрутизации.
  • arguments - Строка - [НЕОБЯЗАТЕЛЬНЫЙ] произвольные свойства в формате Json-объект. Пример: {"x-match": "all"}.

UnbindQueue - Отсоединяет очередь от точки обмена.

Параметры:

  • queue - Строка - Имя очереди
  • exchange - Строка - Имя точки обмена
  • routingKey - Строка - Rлюч маршрутизации.

BasicPublish - Отправить сообщение

Параметры:

  • exchange - Строка - Имя точки в которую отправляется сообщение
  • routingKey - Строка - Ключ маршрутизации (см. руководство RMQ)
  • message - Строка - Тело сообщения
  • livingTime - Число - [НЕ РЕАЛИЗОВАНО] Время жизни сообщения в миллисекундах
  • persist - Булево - Сбрасывать сообщение на диск
  • arguments - Строка - [НЕОБЯЗАТЕЛЬНЫЙ] произвольные свойства в формате Json-объект. Пример: {"x-message-ttl": 60000}.

BasicAck Отсылает серверу подтверждение (ack), что сообщение обработано и его можно удалить. Подтвердить можно любое прочитанное сообщение.

Параметры:

  • messageTag - число - тег сообщения, который возвращается в параметре метода BasicConsumeMessage

BasicReject - Отказывается от последнего полученного сообщения. Работает по принципу Ack, но в обратную сторону.

Параметры:

  • messageTag - число - тег сообщения, который возвращается в параметре метода BasicConsumeMessage

BasicConsume - Начать чтение. Регистрирует потребителя сообщений для очереди.

Параметры:

  • queue - Строка - Очередь из которой будем читать сообщения.
  • consumerId - Строка - [НЕ РЕАЛИЗОВАНО] имя потребителя. Если не задан, то имя потребителя сгенерирует сервер и вернет из метода
  • noConfirm - Булево - не ждать подтверждения обработки. Сообщения будут удалены из очереди сразу после отправки на клиента.
  • exclusive - Булево - монопольно захватить очередь
  • selectSize - Число - количество единовременно считываемых сообщений из очереди в кеш компоненты. Оптимизационный параметр, который влияет на скорость забора сообщений. Рекомендуемый диапазон 100-1000. Нежелательно устанавливать слишком высокие значения, т.к. чтение большого числа накопленных сообщений в очереди может спровоцировать нехватку памяти на клиенте 1С и падение компоненты без вызова исключения.
  • arguments - Строка - [НЕОБЯЗАТЕЛЬНЫЙ] произвольные свойства в формате Json-объект. Пример: {"x-stream-offset": "first"}.

Возвращаемое значение:

  • Строка. Имя потребителя, сгенерированное сервером или переданное в параметре ИмяПотребителя.

BasicConsumeMessage - Получить сообщение

Параметры:

  • consumerId - Строка - [НЕ РЕАЛИЗОВАНО] Имя зарегистрированного потребителя
  • outdata - Строка - Выходной параметр. Тело сообщения.
  • messageTag - Число - Выходной параметр. Тег сообщения для подтверждения через метод BasicAck
  • timeout - Число - Таймаут ожидания сообщения в миллисекундах. Не рекомендуется ставить параметр слшком низким, т.к. сообщение просто может не успеть прийти из очереди. Рекомендуемый диапазон 3000-60000.

Возвращаемое значение:

  • Булево. Истина, если из очереди прочитано очередное сообщение. Ложь, если очередь пустая.

BasicCancel - Закрывает канал для чтения сообщений

Параметры:

  • channelId - Строка - Имя созданного ранее потребителя.

SetPriority -устанавливает приоритет для всех отправляемых сообщений. Если значение равно 0, то приоритет не будет установлен.

Параметры:

  • priority - Число - значение в диапазоне разрешенного приоритета для очереди, но не более 255.

GetPriority - получает приоритет для последнего считанного сообщения. Имеет смысл вызывать внутри цикла чтения сообщений методом BasicConsumeMessage

Параметры: Отсутствуют

Возвращаемое значение:

  • числовое значение приоритета от 0 до 255 для сообщения

GetRoutingKey - получает ключ маршрутизации для последнего считанного сообщения. Имеет смысл вызывать внутри цикла чтения сообщений методом BasicConsumeMessage

Параметры: Отсутствуют

Возвращаемое значение:

  • Строка - ключ маршрутизации очереди считанного сообщения.

GetHeaders - получает заголовки для последнего считанного сообщения. Имеет смысл вызывать внутри цикла чтения сообщений методом BasicConsumeMessage

Параметры: Отсутствуют

Возвращаемое значение:

  • Строка - заголовки считанного сообщения в формате объекта json. Пример: {"customIntHeader": 42}.

GetLastError - получает информацию о последней ошибке

Параметры отсутствуют

Возвращаемое значение:

  • Строка - Последнее сообщение ошибки

SleepNative - останавилвает выполнение программы на указанное время

Параметры:

  • timeout - число - время остановки в милисекундах

Правила работы с компонентой из 1С

  1. Завершать работу с компонентой посредством обнуления объекта компоненты. Например:
Компонента = Новый("AddIn.BITERP.PRMQMOBILE");
// Работа с компонентой
Компонента = Неопределено;
  1. Все выходные параметры в методах компоненты передавать как Неопределено или пустая строка, а также обнулять возвращенные значения. Несоблюдение этого простого правила приводит к огромным утечкам памяти!!! Например:
Клиент = Новый("AddIn.BITERP.PinkRabbitMQ");
ТекстСообщения = "";
ТегСообщения = 0;
Пока Клиент.BasicConsumeMessage(Потребитель, ТекстСообщения, ТегСообщения, Таймаут) Цикл
    // Работа с компонентой
    // ...
    //
    ТекстСообщения = ""; 
    ТегСообщения = 0; // при каждой итерации очищаем память по указателю, который неявной хранится в этой переменной
КонецЦикла;
  1. Не вызывать исключения внутри цикла чтения сообщений. Это приводит к потерянной памяти в rphost-е, т.к. внутри компоненты могут остаться закешированные сообщения, которые не попали в алгоритм очистки ссылок.
Клиент = Новый("AddIn.BITERP.PinkRabbitMQ");
ВыходнойПараметр = "";
Пока Клиент.BasicConsumeMessage(Потребитель, ВыходнойПараметр, Таймаут) Цикл
    // Работа с компонентой
    Если Клиент.CorrelationId <> "МОЙ_ИД" Тогда
        ВызватьИсключение "Ошибка чтения свойств!"; // ТАК ДЕЛАТЬ СТРОГО НЕ РЕКОМЕНДУЕТСЯ!!!
    КонецЕсли;
    ВыходнойПараметр = "";
КонецЦикла;
  1. На сервере все исключения компоненты обрабратывать через Попытку ... Иключение с вызовом в секциии исключения метода GetLastError() для получения истинной детальной ошибки. Пример
Клиент = Новый("AddIn.BITERP.PinkRabbitMQ");
Попытка
    Клиент.DeclareQueue(ИмяОчереди, Ложь, Ложь, Ложь, Ложь);
Исключение
    ВызватьИсключение Клиент.GetLastError();
КонецПопытки

Примеры

Подключение внешней компоненты на клиенте

УстановитьВнешнююКомпоненту("ОбщийМакет.PinkRabbitMQ");
ПодключитьВнешнююКомпоненту("ОбщийМакет.PinkRabbitMQ", "BITERP", ТипВнешнейКомпоненты.Native);
Клиент  = Новый("AddIn.BITERP.PinkRabbitMQ");

Создание точки обмена, очереди и их связывание на клиенте

ИмяТочкиОбмена = "data";
ИмяОчереди = "testroute";
ОтправляемоеСообщение = "Test";
ОтветноеСообщение = "";

УстановитьВнешнююКомпоненту("ОбщийМакет.PinkRabbitMQ");
ПодключитьВнешнююКомпоненту("ОбщийМакет.PinkRabbitMQ", "BITERP", ТипВнешнейКомпоненты.Native);
Клиент  = Новый("AddIn.BITERP.PinkRabbitMQ");

Клиент.Connect("127.0.0.1", 5672, "user", "password", "user");
Клиент.DeclareExchange(ИмяТочкиОбмена, "topic", Ложь, Истина, Ложь);
Клиент.DeclareQueue(ИмяОчереди, Ложь, Ложь, Ложь, Ложь);
Клиент.BindQueue(ИмяОчереди, ИмяТочкиОбмена, "#" + ИмяОчереди + "#");

Создание очереди, отправка и получение сообщения на клиенте

    ИмяОчереди = "testroute";
    ОтправляемоеСообщение = "Test";
    ОтветноеСообщение = "";
    ТегСообщения = 0;
    
    УстановитьВнешнююКомпоненту("ОбщийМакет.PinkRabbitMQ");
    ПодключитьВнешнююКомпоненту("ОбщийМакет.PinkRabbitMQ", "BITERP", ТипВнешнейКомпоненты.Native);
    Клиент  = Новый("AddIn.BITERP.PinkRabbitMQ");
    
    Клиент.Connect("127.0.0.1", 5672, "user", "password", "vhost");
    Клиент.DeclareQueue(ИмяОчереди, Ложь, Ложь, Ложь, Ложь);
    Клиент.BasicPublish("", ИмяОчереди, ОтправляемоеСообщение, 0, Ложь);
    Попытка
        Потребитель = Клиент.BasicConsume(ИмяОчереди, "", Истина, Ложь, 0);
        Пока Клиент.BasicConsumeMessage("", ОтветноеСообщение, ТегСообщения, 5000) Цикл
            Клиент.BasicAck(ТегСообщения);
            Сообщить("Успешно! Из очереди прочитано сообщение " + ОтветноеСообщение);
            ОтветноеСообщение = ""; // Обнуляем, чтобы избежать утечку памяти
            ТегСообщения = 0; // Обнуляем, чтобы избежать утечку памяти
        КонецЦикла;
        Клиент.BasicCancel("");
    Исключение
        Сообщить(Клиент.GetLastError());
    КонецПопытки;

Установка в конфигурацию

  1. Скачать архив с релизом компоненты.
  2. Загрузить в конфигурацию в качестве общего макета с двоичными данными

Поддержка TLS

Компонента поддерживает соединение по протоколу TLS версии 1.2. Сертификаты сервера верифицируются при подключении, клиентские сертификаты не поддерживаются. На сервере RabbitMQ необходимо отключить проверку клиентских сертификатов опциями ssl_options.verify и ssl_options.fail_if_no_peer_cert. Подробнее про опции можно узнать из официальной документации: https://www.rabbitmq.com/ssl.html#peer-verification-configuration

Разворачивание окружения разработки на Windows 10 (Рекомендуется)

Вместе с проектом поставляются заранее скомпилированные зависимости в папке libsPrecompiled для 32 и 64 битных платформ в вариантах debug и release. Поэтому для создания окружения разработки нужно сделать только следующее:

  1. Установить Visual Studio 2019 (можно Community). При установке выбрать среди обязательных компонентов также WIndows SDK 10
  2. Скачать исходники репозитория данного проекта.
  3. Запустить файл проекта AddIn.sln в корневом каталоге

Разворачивание окружения разработки на Windows 10 и самостоятельная компиляция всех зависимостей (Не рекомендуется)

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

  1. Установить Visual Studio 2019 (можно Community). При установке выбрать среди обязательных компонентов также WIndows SDK 10
  2. Скачать исходники репозиторий данного проекта.
  3. Скачать исходники либы для работы с протоколом раббита AMQP-CPP 4.1.4. https://github.com/CopernicaMarketingSoftware/AMQP-CPP в папку libs
  4. Скомпилировать дебажную и релизную dll в папкe libs\AMQP-CPP-4.1.4\build с помощью cmake.
mkdir build
cd build
cmake .. 
cd ..
cmake --build

Для компиляции 64-битной release версии либы

  • Открыть файл проекта amqpcpp.sln
  • Выбрать свойства проекта amqcpp => C/C++ => Code generation => Runtime library => Multi-threaded (/MT)
  • Скомпилировать проект Release

Для компиляции 32-битной release версии либы

Нужно создать свой проект с нуля на базе проекта 64-битной компоненты, сгенерированного через cmake

  1. Скачать исходники либы для работы с сокетом POCO 1.9.0. https://github.com/pocoproject/poco/tree/master в папку libs
  2. Скомпилировать дебажную .lib и .dll (debug_shared) и релизную (release_static_mt) для следующих подпроектов Foundation и Net. Компиляцию следует выполнять через sln проекты
  3. Для дебажного запуска компоненты поместить скомпилированные dll-ки PocoFoundationd64.dll и PocoNet64d.dll в папку 1cv8\8.3.10.2667\bin
  4. Запустить файл проекта компоненты NativeRabbitMQClient в каталоге AddIn.sln
  5. Проверить линковку зависимостей для заголовков Properties узла проекта -> С/С++ -> General -> Additional include directories (переключить вкладку debug)
  • ..\libs\poco-poco-1.9.0-release\Foundation\include;
  • ..\libs\poco-poco-1.9.0-release\Net\include;
  • ..\libs\AMQP-CPP-4.1.4\include;
  1. Проверить линковку зависимостей для папок lib и dll файлов Properties узла проекта -> Linker -> General -> Additional include directories
  • ..\libs\poco-poco-1.9.0-release\lib64;
  • ..\libs\AMQP-CPP-4.1.4\build\bin\Debug;
  1. Проверить линкову для lib файлов зависимостей Properties узла проекта -> Linker -> Input -> Additional dependencies
  • amqpcpp.lib;
  • PocoFoundationd.lib;
  1. Скомпилировать компоненту через проект

Разворачивание окружения разработки для Linux из-под WIndows 10

  1. Установить Visual Studio Community 2019 с последними обновлениями
  2. Развернуть Linux system for Windows 10 и подключить VS Studio к своей машине Туториал
  3. Запустить проект PinrRabbitMQ для Linux

Сборка проекта через cmake для Windows 10

mkdir build
cd build
cmake .. 
cmake --build . --config Release

Сборка проекта через Visual Studio для Linux

  1. Запустить проект PinrRabbitMQ для Linux
  2. Открыть свойства проекта и в меню Confugartion properties -> General -> Configuration type выбрать Dynamic library (so)
  3. Скомпилировать проект через f5
  4. Либа будет скомпилирована в каталоге ~/projects/PinkRabbitMQLinux/bin/x64/debug/ удаленной машины

Сборка проекта через cmake для Linux

Сборку необходимо производить на Ubuntu 16 или Debian 8.

# Установить необходимые пакеты
sudo apt install build-essential cmake

# Собрать библиотеку
cd PinkRabbitMQLinux
mkdir build
cd build
cmake .. 
cmake --build .

Запуск unit тестов в Visual Studio 2019

  1. В паке выполнения тестов \windows\tests переименовать файл test.conf.example в test.conf и указать в нем параметры подключения к тестовому кролику
  2. Скопировать в папку выполнения тестов \windows\x64\Debug собранные dll библиотеки poco из \lib\win_x64\cfg_Debug
  3. Запустить тесты из инетрфейса Visual Studio

Лицензия

Лицензировано на условиях MIT. Смотрите файл LICENSE

Используемые сторонние продукты

pinkrabbitmq's People

Contributors

begemoth2 avatar big-town avatar gstalnoy avatar gstalnoy-bit-erp avatar ipalenov avatar olpavel avatar ripreal avatar vdykov avatar volody314 avatar wadus16 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pinkrabbitmq's Issues

Не работает метод GetPriority

При получении сообщения метод GetPriority возвращает неопределено.
Если получить сообщение через веб интерфейс, свойства сообщения:
Properties
priority: 8
delivery_mode: 2

Преобразование из string в wstring

В файле /PinkRabbitMQWindows/NativeAPI/CAddInNative.cpp есть такой код

std::string outdata;
...
setWStringToTVariant(&paParams[1], Utils::stringToWs(outdata).c_str());
...

В методе Utils::stringToWs реализовано такое преобразование из string в широкую строку wstring:

std::wstring Utils::stringToWs(const std::string& s)
{
	std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
	return conv.from_bytes(s);
}

Если строка s будет содержать некоторые спец символы unicode, например такие как неразрывный пробел (U+00A0), то это вызовет ошибку преобразования и исходная строка в лучшем случае получится обрезанной. Может будет более безопаснее использовать проверенную?

boost::locale::conv::utf_to_utf<wchar_t>(s);

Не удается организовать чтение сообщений

Версия компоненты 1.8.

Пример выполняемого кода.

Потребитель = Клиент.BasicConsume(Параметры.Очередь, "", Истина, Ложь, 0);
// После этого вызова Потребитель = ""
// Второй параметр не влияет на дальнейший результат.

Пока Клиент.BasicConsumeMessage(Потребитель, ОтветноеСообщение, ТегСообщения, 1) Цикл
	// В цикл не заходит.
	ОтветноеСообщение = ""; // Обнуляем, чтобы избежать утечку памяти
	ТегСообщения = 0; // Обнуляем, чтобы избежать утечку памяти
КонецЦикла;

Добавить поддержку заголовка x-death

Для обработки сообщений, путешествующих по DLX, нужна информация, хранящаяся в заголовке x-death.

Имеющаяся сложность - x-death имеет не примитивный тип, это массив соответствий.
В веб-морде рэббита заголовки выглядят вот так:

image

BasicConsumeMessage читает только сообщения которые были в очереди на момент вызова

photo_2021-06-08_14-23-07
Привет! То что на картинке это баг или фича? Никита Грызлов в чате написал что возмоджно это баг вот тут https://t.me/ssl1c/86188 Подробное обсуждение было там же в чате, но могу и предоставить доп. информацию если потребуется

Добавить поддержку всех метаданных сообщения RAbbitMQ

В RabbitMQ есть набор свойств, передаваемых вместе с сообщением:
appID
messageID
typeName
correlationID
ContentEncoding
ContentType
UserID
ClusterID
Expiration
ReplyTo

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

Ошибка (Зависание) метод BasicPublish

RMQ.BasicPublish(Exchange, RoutingKey, Message, LivingTime, Persist) - Зависает.

есть точка обмена, у нее 2 очереди, из первой читаем нормально по ключу RoutingKey_1, и сразу же отправляем во вторую очередь по ключу RoutingKey_2 метод зависает. Ничего не происходит, приходится ребутить агента

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

Добавить возможность получать сообщения из нескольких очередей за 1 вызов BasicConsumeMessage

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

Подробное описание проблемы см. https://partners.v8.1c.ru/forum/message/1846350

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

Компонента зависает, если сервер RabbitMQ временно не отвечает из-за нехватки памяти

Если у кролика заканчивается оперативная память, то он не разывает существующие соединения, а "завешивает" т.е. ничего по ним не отвечает, а ждет когда у него память освободится. Соответственно от компоненты ожидается, что:

даже если сам севрер кролика повесил соединение, то по таймауту сама компонента его прервет (не важно при отправке или при получении соединение зависло)

image

Сделать тесты, которые можно было бы поставлять вместе с компонентой

Чтобы можно было проверить работоспособность компоненты при внесении в нее изменений, до пулл-реквеста.

Пока кажется, что это могут быть юнит-тесты, поставляемые вместе с компонентой и интегрированные с гитхаб (травис)

Разрыв соединения через ~3 минуты

Необходимо подключиться к кролику и ожидать сообщения.

Клиент.Connect("127.0.0.1", 5672, "user", "password", "vhost");
Потребитель = Клиент.BasicConsume(ИмяОчереди, "", Истина, Ложь, 0);

Но примерно через 3 минуты соединение разрывается.
Похожая проблема описана здесь и дано решение.
Connection lost error after ~3 minutes.

Как добавить обработку onHeartbeat ?
virtual void onHeartbeat(AMQP::TcpConnection *connection) {
std::cout << "heartbeat" << std::endl;
connection->heartbeat();
}

P.S. Не силен в c++, поэтому обращаюсь к сообществу :)

README.md Добавьте обработку ошибки для соединения с сервером Клиент.Connect…

Поправьте README.md
Пункт «Создание очереди, отправка и получение сообщения на клиенте»

  1. Добавьте обработку ошибки для соединения с сервером Клиент.Connect… и другие обращения к Клиент. (Завернуть в попытку, тогда Клиент.GetLastError() будет возвращать информацию о том, что произошло.) В текущем варианте ошибка соединения не обрабатывается, код падает.

    Попытка // добавить
    Клиент.Connect("127.0.0.1", 5672, "user", "password", "vhost");
    Клиент.DeclareQueue(ИмяОчереди, Ложь, Ложь, Ложь, Ложь);
    Клиент.BasicPublish("", ИмяОчереди, ОтправляемоеСообщение, 0, Ложь);
    Попытка // убрать

Если вы хотите показать, что Клиент и Потребитель существуют отдельно, то разнесите код на несколько Попыток.

  1. Добавить версию кода, например 8.3.10
    Так, например, УстановитьВнешнююКомпоненту - Не рекомендуется использовать, начиная с версии 8.3.16

Не реализована поддержка TLS

В компоненте не реализована поддержка TLS.
Соединение с сервером через защищенное подключение (например, порт 5671) возвращает ошибку "Wrong login, password or vhost".

Падение рабочих процессов 1С в linux при [неправильной] работе с компонентой

Дано:
Компонента версии 1.8
Ubuntu 18.04, платформа 1С 8.3.13-16

При вызове метода Connect("server", "5672", "admin", "1234", "/") падает рабочий процесс сервера 1С.

Ожидаемое поведение:
Как и в Windows, должно выводиться сообщение о том, что в параметре 1 передано значение неправильного типа. В примере "5672" - это Строка, а должно быть 5672 - Число.

Ошибка при сборке компоненты для Linux

При сборке проекта "PinkRabbitMQLinux" возникает ошибка:

Ошибка openssl/ssl.h: No such file or directory
19 | #include <openssl/ssl.h>
| ^~~~~~~~~~~~~~~
compilation terminated. PinkRabbitMQLinux
\PinkRabbitMQLinux\src\amqp\include\amqpcpp\linux_tcp\tcpparent.h

Попытка сборки была под Win 10 с помощью Visual Studio 2019 + WSL.

Какую версию библиотеки openssl нужно добавить?
Можно ли это сделать непосредственно в репозитории?

Добавить отправку внешних событий в 1С (ExternalEvent)

Например, для задач телефонии Asterisk AMI + RabbitMQ + компонента + 1С:

  • Asterisk каким-то образом (я написал скрипт на php с использованием https://github.com/marcelog/PAMI и https://github.com/php-amqplib/php-amqplib) шлет сообщения о событиях (новый звонок на линии, пропущенный звонок и т.д.) в обмен на RabbitMQ;
  • у сообщений есть ключи маршрутизации типа ami.AMIEventName.channel_name... например, ami.Newchannel.PJSIP/trunkname или ami.Hangup.PJSIP/900;
  • каждый компьютер, на котором запущен тонкий клиент 1С, связан со своим внутренним номером телефона (pc01 - PJSIP/900, pc02 - PJSIP/100 и т.д.)
  • все законченные звонки пишутся в регистр сведений ИсторияЗвонков;
  • все новые входящие (текущие) звонки мгновенно показываются нужным пользователям (если событие касается PJSIP/100 и кто-то работает в 1С на pc02) во всплывающих сообщениях.

В 1С нельзя вызвать клиентский метод с сервера. Но компонента может работать на клиенте и на сервере.

В частности, на сервере можно:

  • создать очередь ami_hangups и связать ее с сообщениями ami.Hangup.#;
  • периодически фоновым заданием по расписанию (раз в 60 секунд) читать сообщения и обрабатывать их - писать в регистр сведений ИсторияЗвонков с признаками Пропущен, Успешный и т.д.;
  • этим полностью закрыть потребность в логировании звонков.

На клиенте можно:

  • создать очередь ami_newcalls и связать ее с сообщениями ami.Newchannel.#;
  • или по кнопке "Проверить звонки"подключать компоненту, читать сообщения и обрабатывать их - показывать пользователю (абсурд);
  • или раз в 60 секунд (через обработчик ожидания) подключать компоненту, читать сообщения (начинает тормозить клиент, ибо поток выполнения блокируется.. плюс раз в секунду - это довольно редко);
  • или раз в x секунд (опять через обработчик ожидания) делать запросы к регистру ИсторияЗвонков и смотреть, а нет ли текущих активных незаконченных звонков (быстрее, но не оптимально).

Идея для использования на клиенте:

  • реализовать в компоненте возможность запускать бесконечный цикл чтения сообщений в отдельном потоке, который при получении сообщения будет дергать 1С;
  • в 1С будет вызываться на клиенте стандартная процедура ОбработкаВнешнегоСобытия(<Источник>, <Событие>, <Данные>), в которой мы можем показать всплывающее сообщение пользователю.

Насколько я знаю, это будет работать только на клиенте - на сервере "внешние события не обрабатываются".

Компоненты не читает сообщения при повторном начале чтения в цикле

Описание:
Если запустить последовательно в рамках одной сессии 2 цикла чтения сообщения, то второй цикл не прочитает ни одного сообщения, даже если они есть в очереди
Способ обхода:
Заново инициализировать компоненту при повторном чтении

Псевдокод:

Процедура ПрочитатьСообщениеКлиентСервер(КлиентКомпоненты, Форма)
    
    Попытка
        КлиентКомпоненты.Connect(
            Форма.Адрес,
            Форма.Порт,
            Форма.Логин,
            Форма.Пароль,
            Форма.ВиртуальныйХост);
        
        ИмяОчереди = Форма.ИмяОчереди;
        ТегСообщения = 0;
        
        Попытка
            КлиентКомпоненты.DeclareQueue(ИмяОчереди, Ложь, Ложь, Ложь, Ложь);
            
            Потребитель = КлиентКомпоненты.BasicConsume(ИмяОчереди, "", Истина, Ложь, 0);
            
            ОтветноеСообщение = "";
            
            //Если КлиентКомпоненты.BasicConsumeMessage("", ОтветноеСообщение, 5) Тогда 
            Если КлиентКомпоненты.BasicConsumeMessage("", ОтветноеСообщение, ТегСообщения,1000) Тогда
                КлиентКомпоненты.BasicAck(ТегСообщения);
                Форма.ОтветноеСообщение = ОтветноеСообщение;
                ТекстСообщения = НСтр("ru='Сообщение успешно прочитано!'");
            Иначе
                Форма.ОтветноеСообщение = ОтветноеСообщение;
                ТекстСообщения = НСтр("ru='Очередь пустая!'");
            КонецЕсли;
            Сообщить(ТекстСообщения);
            
            // Обнуляем, чтобы избежать утечку памяти
            ОтветноеСообщение = "";
            ТегСообщения = 0;

            КлиентКомпоненты.BasicCancel("");
        Исключение
            ВызватьИсключение КлиентКомпоненты.GetLastError();
        КонецПопытки;
    Исключение
        СистемнаяОшибка = ОписаниеОшибки();
        ТекстСообщения = "Ошибка чтения сообщения!%СистемнаяОшибка%";
        ТекстСообщения = СтрЗаменить(ТекстСообщения, "%СистемнаяОшибка%", СистемнаяОшибка);
        ВызватьИсключение ТекстСообщения;
    КонецПопытки;
    
КонецПроцедуры

Ошибка при отправке методом BasicPublish

Отправляю сообщение. Размер сообщения 17.1 Мб.
Исключения не происходит.
Но в очереди сообщения не появляется.

Уменьшил сообщение до 10 Мб, отправилось и появилось.

Есть какие-то ограничения по размеру сообщения? Или в методе зашит таймаут ожидания?

Компонента зависает, если неправильно указаны параметры авторизации к серверу RabbitMQ (логин, пароль или vhost)

Способ воспроизведения:
Клиент = Новый("AddIn.BITERP.PinkRabbitMQ");
Клиент.Connect("127.0.0.1", 5672, "user", "password", "wrongvhost"); // МЕТОД ПРОХОДИТ ДАЖЕ ЕСЛИ VHOST НЕВЕРНЫЙ
Клиент.DeclareExchange(ИмяТочкиОбмена, "topic", Ложь, Истина, Ложь); // МЕТОД ЗАВИСАЕТ

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

линукс

Здравствуйте.
Не очень в плюсах, но в линуксе данный цикл грузит ядро на 100%
while(!thiz->connection->closed()) {
event_base_loop(loop, EVLOOP_NONBLOCK);
}

Соединение с сервером RAbbitMQ разрывается при простое

Есть предположение, что в linux версии компоненты после вызовыа метода Connect при бездействии (отсутствия трафика) происходит автоматический разрыв соединения. Нужно проверить и при необходимости исправить. Источник: #21

Высокая нагрузка на процессор при ожидании сообщения.

bool RabbitMQClient::basicConsumeMessage(std::string& outdata, std::uint64_t& outMessageTag, uint16_t timeout) {

updateLastError("");

std::chrono::milliseconds timeoutSec{ timeout };
auto end = std::chrono::system_clock::now() + timeoutSec;
while (!readQueue.empty() || (end - std::chrono::system_clock::now()).count() > 0) {

Последняя строка организует бесконечный цикл с проверкой условий до момента истечения таймаута или появления сообщений в очереди. Это приводит к 100% загрузки одного процессорного ядра. Рекомендуется заменить данную конструкцию на конструкцию "wait_until". Более подробно можно почитать здесь: https://en.cppreference.com/w/cpp/thread/condition_variable/wait_until
Замена приведет к удалению паразитной загрузки процессора.

Добавить возможность подтверждения последний N сообщений из очереди.

В случае, если сообщения обрабатываются пачками по N сообщений, возникает потребность обеспечить подтверждение окончания обработки сразу нескольких сообщений.
Сейчас это реазиуется путем запроса N сообщений, обработки на стороне потребителя, потом повторного получения с отправкой подтверждения на каждое сообщение.

Сборка компоненты v2.1.0.59 под Linux на Ubuntu 18

Доброго дня. Собрал компоненту на Ubuntu 18.04 файл .so сформировался, хотя в тест выдал такую ошибку:

libPinkRabbitMQ64.so: undefined reference to `AMQP::Field::operator std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&() const'
collect2: error: ld returned 1 exit status
CMakeFiles/unittest.dir/build.make:125: recipe for target 'unittest' failed
make[2]: *** [unittest] Error 1
CMakeFiles/Makefile2:104: recipe for target 'CMakeFiles/unittest.dir/all' failed
make[1]: *** [CMakeFiles/unittest.dir/all] Error 2
Makefile:94: recipe for target 'all' failed
make: *** [all] Error 2

собранный файл .so включил в MANIFEST.zip и засунул в конфу. При вызове функции возвращается "Ложь", то есть компонента отказывается подключаться:

КомпонентаПодключена = ПодключитьВнешнююКомпоненту(
		АдресВоВременномХранилище,
		"BITERP",
		ТипВнешнейКомпоненты.Native
	);

Собирал так как это сказано в ридми. Действительно ли компоненту можно собрать только на Ubuntu 16 и это не рекомендация, а жесткое требование?

frame size exceeded

Метод Клиент.GetLastError() возвращает frame size exceeded, что это значит?
Возникает когда канал на чтение еще не закрыт, пытаемся отправить какое то сообщение в кролика.

Проблемы подключения по SSL, подключения в Linux, компиляции проекта

Столкнулся с рядом проблем при попытке использования компоненты:

  1. В windows (Win10x64, 1C:8.3.17x32), не работает защищенное соединение, при вызове метода connect компонента возвращает ошибку (get last error): Timeout. Ошибка вылетает мгновенно, без ожидания.
    PinkRabbitMQ_timout_error
    Не защищенное соединение - работает.
  2. В linux не получилось подключиться к серверу RabbitMQ не по SSL/не без SSL. Linux x64 (Ubuntu 20 и 18), платформа 1C x64 (8.3.16, 8.3.17). Пакеты libssl libjsoncpp libevent установлены, но не исключена проблема с версиями пакетов.
  • На актуальной сборке выпадает с ошибкой во время подключения компоненты
    PinkRabbitMQ_installed_linux_packages
  • На релизах 1.8, 1.9 при вызове метода connect() с ошибкой: RabbitMQ channel is not in usable state. Сетевые проблемы исключены, т.к. с использованием модуля pika (python) получается подключиться по защищенному и незащищенному протоколам.
    PinkRabbitMQ_not_usable_error
  1. Не компилируется актуальный проект в репозитории (по инструкции):
  • Если компилировать только исходники из его репозитория, то не находились хедеры из компоненты poco
  • Скачал исходники ampqccp и poco свежие, они собрались без ошибок, перелинковал на эти пересобранные библиотеки, но при сборке компоненты появились ошибка уровня кода: про состав параметров методов. Похоже, что-то изменилось во внешних проектах.

Ошибка при возникновении AMQP server timeout error

Если подключении компоненты и отправке в цикле сообщений, когда возникает ошибка от компоненты "AMQP server timeout error", то при КлиентКомпоненты = Неопределено, происходит перезапуск всего действия. Например, если выгрузка начата по кнопке - весь алгоритм команды кнопки начинается заново и, соответственно начинается вся выгрузка заново.

Процедура ОтправкаСообщений(ПараметрыПодключения, ТЗ)

Попытка
	КлиентКомпоненты = ПодключитьсяКRabbit(ПараметрыПодключения);
Исключение
	ВызватьИсключение ОписаниеОшибки();
КонецПопытки;

Для каждого стр из ТЗ Цикл
	КоличествоПопыток = 1;
	Пока КоличествоПопыток <= 3 Цикл
		Попытка
			ОтправитьСообщениеRabbit(ПараметрыПодключения, КлиентКомпоненты, стр.ТекстСообщения);
		Исключение
			ТекстОшибки = ОписаниеОшибки();	// Из GetLastError возвращается "AMQP server timeout error"
			Сообщить(ТекстОшибки);	
			КоличествоПопыток = КоличествоПопыток + 1;
			Продолжить;
		КонецПопытки;
	КонецЦикла;
		
	Если НЕ КоличествоПопыток <= 3 Тогда
		КлиентКомпоненты = Неопределено; // Если не получилось переотправить, после этой строки начинается алгоритм заново 
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
КонецЦикла;

КлиентКомпоненты = Неопределено; // Если получилось переотправить, начинается алгоритм заново 		

КонецПроцедуры

BasicConsumeMessage ожидает сообщение ровно столько, сколько установлен timeout

Клиент  = Новый("AddIn.BITERP.PinkRabbitMQ");
TimeOut = 50000;

Попытка
	Клиент.Connect(RabbitMQServerURL, RabbitMQPort, RabbitMQLogin, RabbitMQPassword, RabbitMQVHost,,,10);
	Клиент.DeclareQueue(ИмяОчереди, Ложь, Истина, Ложь, Ложь);
		
	Потребитель = Клиент.BasicConsume(ИмяОчереди, "", Ложь, Ложь, 0);
        Пока Клиент.BasicConsumeMessage("", ОтветноеСообщение, ТегСообщения, TimeOut) Цикл //Тут зависает ровно на время таймаута вне зависимости от размера сообщения
	    Клиент.BasicAck(ТегСообщения);
            ОтветноеСообщение = ""; // Обнуляем, чтобы избежать утечку памяти
            ТегСообщения = 0; // Обнуляем, чтобы избежать утечку памяти
        КонецЦикла;
		
Клиент.BasicCancel("");

При вызове метода BasicConsumeMessage время ожидания сообщения ровняется таймауту, вне зависимости от размера сообщения.
PinkRabbitMQ v2.1.1.132

Сообщения удаляются из очереди, хотя делаю BasicReject(ID)

При обработке, все сообщения удаляются из очереди, хотя я их не АSKаю, использую метод BasicReject(ID).
После выполнения данного кода, все сообщения удаляются из очереди, хотя необходимо, чтобы они вернулись назад в очередь.

Пример кода:

Клиент  = PinkRabbitMQ_Подключиться();

ИмяОчереди = "q.site.1c.test";


Попытка
	//Клиент.DeclareQueue(ИмяОчереди, Ложь, Истина, Ложь, Ложь);
	Потребитель = Клиент.BasicConsume(ИмяОчереди, "", Ложь, Ложь, 1);
	Сообщение = ""; //Первоначально задаем параметры
	ID = 0;		//Первоначально задаем параметры
	Пока Клиент.BasicConsumeMessage("", Сообщение, ID, 5000) Цикл
		// Начало Обработчика сообщения
		Сообщить("Успешно! Из очереди прочитано сообщение " + Сообщение);
		// Конец Обработчика сообщения
		
		Клиент.BasicReject(ID);
		Сообщение = ""; // Обнуляем, чтобы избежать утечку памяти
		ID = 0; // Обнуляем, чтобы избежать утечку памяти
	КонецЦикла;
	Клиент.BasicCancel("");
Исключение
	Сообщить(Клиент.GetLastError());
КонецПопытки;

-

// извините, моя ошибка

Не вызывать исключения внутри цикла чтения сообщений.

Если делать так

Клиент = Новый("AddIn.BITERP.PinkRabbitMQ");
ВыходнойПараметр = "";

Попытка
Пока Клиент.BasicConsumeMessage(Потребитель, ВыходнойПараметр, Таймаут) Цикл
// Работа с компонентой
Если Клиент.CorrelationId <> "МОЙ_ИД" Тогда
ВызватьИсключение "Ошибка чтения свойств!"; // ТАК ДЕЛАТЬ СТРОГО НЕ РЕКОМЕНДУЕТСЯ!!!
КонецЕсли;
ВыходнойПараметр = "";
КонецЦикла;

Исключение
Клиент = неопределено;
КонецПопытки

Это будет корректно? Вызывать исключение в попытке?

Для сборки Windows версии компоненты в репе не хватает заголовочных файлов Poco/Net

При попытке собрать PinkRabbitMQWindows (например Release - x64) в VS (Сборка -> Собрать решение) возникают ошибки:

1>C:\Distr\PinkRabbitMQ\PinkRabbitMQWindows\NativeAPI\RabbitMQClient.cpp(6,10): fatal error C1083: Не удается открыть файл включение: Poco/Net/NetException.h: No such file or directory
1>C:\Distr\PinkRabbitMQ\PinkRabbitMQWindows\NativeAPI\SimplePocoHandler.cpp(7,10): fatal error C1083: Не удается открыть файл включение: Poco/Net/StreamSocket.h: No such file or directory

Для исправления ошибки потребовалось скачать https://github.com/pocoproject/poco/archive/poco-1.9.0-release.zip и скопировать оттуда каталог Net в PinkRabbitMQWindows\libs\poco-poco-1.9.0-release\Net.

З.Ы. Сначала скачал poco 1.10.1 (крайний) и долго не мог понять, почему у меня компонента крашится на методе connect...

Добавить работу с headers сообщения

Добрый день!
Компонента сейчас предоставляет доступ к свойствам сообщения (MessageId, ContentType и пр.), но не к Headers. Можно ли добавить такую возможность?
Это было бы полезно, например, при приеме сообщений MQTT через Rabbit.

Странные таймауты в Linux

В последней версии часто получаем странные ошибки вида
AMQP server timeout error
Например, вызываю Connect, потом сразу DeclareExchange - и с вероятностью ~20% получаю ошибку выше.
При этом если после Connect сделать паузу хотя бы в 500 мс, то ошибки нет.

На версии 1.10 все хорошо в тех же условиях.

Работа компоненты в фоновом задании

Возник такой вопрос по работе кода, приведенного в README.md:

Пока Клиент.BasicConsumeMessage("", ОтветноеСообщение, ТегСообщения, 5000) Цикл
            Клиент.BasicAck(ТегСообщения);
            Сообщить("Успешно! Из очереди прочитано сообщение " + ОтветноеСообщение);
            ОтветноеСообщение = ""; // Обнуляем, чтобы избежать утечку памяти
            ТегСообщения = 0; // Обнуляем, чтобы избежать утечку памяти
КонецЦикла;

Правильно я понимаю, схему работы с компонентой:

  1. Запускается регламентное задание (с заданной периодичностью), которое в фоновом режиме выполняет цикл с методом BasicConsumeMessage().
  2. Если таймаут истекает и нет новых сообщений в очереди, то BasicConsumeMessage возвращает False, мы выходим из цикла и фоновое задание завершается.

ВОПРОСЫ:

  1. Если мое понимание схемы работы правильное, то получается мы читаем сообщения из очереди с периодичностью запуска регламентного задания, верно?
  2. Г. Стальной на партнерсе написал: "Постоянно весит соединение на сервере (на самом деле нет мы его рубим каждые 10 мин и перезапускаем через расписание регл. задание)". Зачем "рубить" выполнение этого цикла с методом BasicConsumeMessage? Возникают проблемы с памятью? Или в каком контексте он это имел ввиду?
  3. Какие есть причины, чтобы не крутить метод BasicConsumeMessage в цикле постоянно (конечно, нужно дорабатывать существующий метод под такую логику), передавая управление в 1С когда у нас есть новые сообщения в очереди? Это связано со спецификой функционала кролика, или проблемами в native API?
  4. (вопрос связан с 3) Здесь вы написали: "Подход с бесконечным циклом некорректный. Внутренняя либа для работы с rabbitMQ - AMQPСPP поддерживает возможность "подписаться" на очередь. Эту возможность и следуюет использовать." Как я понимаю подписка предполагает создание некого колбека, который будет вызываться по событию поступления новых сообщений в очередь. Но на сервере 1С не поддерживаются события, тогда не понятно какую подписку на очередь вы имеете ввиду?

хотим использовать вашу компоненту (а может и сам адаптер) в проекте, но пока нет уверенности, что компонента работает корректно и (самое главное) оптимально.

Как правильно использовать на клиенте и на сервере в асинхронном режиме

Здравствуйте!

Пытаюсь разобраться, как правильно подписываться на очередь. Решаю задачу:

  • клиенты подписываются на какие-то свои очереди (создавая и удаляя их в сеансе), читают и изредка отправляют;
  • сервер подписан на свою очередь (пока не упал).
  1. Я правильно понимаю, что в примере
Пока Клиент.BasicConsumeMessage(Потребитель, ТекстСообщения, ТегСообщения, Таймаут) Цикл
    // Работа с компонентой
    // ...
    //
    ТекстСообщения = ""; 
    ТегСообщения = 0; // при каждой итерации очищаем память по указателю, который неявной хранится в этой переменной
КонецЦикла;

показан бесконечный цикл чтения для поддержания соединения, поскольку сама компонента после вызова метода Connect() через некоторое время разрывает соединение? И мне нужно проверять ТекстСообщения на непустую строку и выполнять нужные мне действия?

  1. Если да, то на сервере этот цикл следует поместить в ФоновоеЗадание, которое нужно один раз запустить, и пускай работает, верно?

  2. А как на клиенте реализовать подобный цикл, чтобы не блокировать интерфейс? Я пока понял только как ПодключитьОбработчикОжидания, который раз в 10 секунд будет выполнять этот цикл (и выходить из него, если ТекстСообщения = "" после вызова метода BasicConsumeMessage).

Спасибо!

BasicPublish никак не реагирует на отсутствие прав записи по ключу маршрутизации

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

Компонента неправильно обрабатывает ситуацию при отправке в несуществующую точку обмена

Способ воспроизведения:

  1. Создать соединение
  2. Отправить первое сообщение через метод basicPublish в несуществующую точку обмена. Метод выполнитсья успешно
  3. Отправить второе сообщение через метод basicPublish туда же. Метод вернет ошибку. Причем метод getLastError вернет некорректную ошибку

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.