Перейти к содержимому

Модуль Pull в 1С-Битрикс - события в браузере в реальном времени

Модуль Pull заменяет периодический опрос сервера на доставку событий по инициативе сервера: счётчик обновляется сам, уведомление появляется мгновенно, открытые вкладки синхронизируются. Разберём прикладную сторону - как отправить команду и как её принять.

Как это работает

Два режима работы. Рекомендуемый - постоянное подключение к серверу очередей: браузер держит долгоживущее соединение с отдельным push-сервером, что требует настройки инфраструктуры. Без неё модуль работает в режиме опроса: клиент обращается к серверу раз в минуту, при наличии данных интервал сокращается до десяти секунд, а затем при пустых ответах снова растёт.

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

Отправка - это команда в очередь получателю. Есть отправка конкретному пользователю или гостю, рассылка подписанным на тег и отдельная сущность push-уведомлений на устройства. В новом коде серверная отправка выполняется через D7-класс события.

Структура команды - три поля: идентификатор модуля-отправителя, имя команды и объект произвольных параметров. Ровно эта тройка приходит на клиент.

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

Инфраструктурная настройка push-сервера - ключ подписи, порты, служба на Node.js - описана в статье про окружение.

Примеры

1. Отправка команды пользователю

\Bitrix\Main\Loader::requireModule('pull');
\Bitrix\Pull\Event::add($userId, [
'module_id' => 'mymodule',
'command' => 'orderStatusChanged',
'params' => [
'orderId' => $orderId,
'status' => $status,
],
]);

Идентификатор модуля и имя команды на клиенте используются для фильтрации - берите осмысленные и уникальные значения.

2. Рассылка подписанным

// подписать пользователя на тег
\CPullWatch::Add($userId, 'ORDER_' . $orderId);
// отправить всем подписанным на тег
\CPullWatch::AddToStack('ORDER_' . $orderId, [
'module_id' => 'mymodule',
'command' => 'orderUpdated',
'params' => ['orderId' => $orderId],
]);

Модель подписки на тег удобна, когда получателей заранее не знаешь: подписались все, кто открыл страницу заказа, и они же получат обновление.

3. Приём на клиенте

BX.PULL.subscribe({
moduleId: 'mymodule',
callback: (data) => {
if (data.command === 'orderStatusChanged') {
updateStatus(data.params.orderId, data.params.status);
}
},
});
// подписка на конкретную команду
BX.PULL.subscribe({
type: BX.PullClient.SubscriptionType.Server,
moduleId: 'mymodule',
command: 'orderUpdated',
callback: (params) => refresh(params.orderId),
});

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

Справочник API

APIНазначениеОсобенности
Bitrix\Pull\Event::add()отправка события в D7-стилеактуальный способ
CPullStackотправка конкретному пользователю или гостюлегаси-класс
CPullWatch::Add()подписка пользователя на тег
CPullWatch::AddToStack()рассылка подписанным на тегполучатели заранее неизвестны
CPushManagerpush-уведомления на устройстваотдельная от команд сущность
CPullOptionsпроверка состояния модуля
структура командымодуль, команда, параметрыэта же тройка приходит на клиент
pull.clientклиентская библиотекаподключается в публичной части
BX.PULL.subscribe()подписка на командыфильтрация по модулю и команде
режим для гостейreal-time без авторизациивключается отдельно

Частые ошибки

События не приходят вообще. Первым делом проверьте, в каком режиме работает модуль: без настроенного push-сервера это опрос с интервалом до минуты, и «мгновенность» получить нельзя в принципе.

Ключ подписи не совпадает. Сайт и push-сервер должны использовать одно значение, иначе соединение не установится.

Порты закрыты за балансировщиком. Служебные порты push-сервера должны быть доступны, иначе соединение не поднимется.

Обработчик ловит чужие события. Подписка без фильтра по модулю и команде получает всё подряд.

Через Pull пытаются передавать большие данные. Это канал уведомлений, а не транспорт: правильнее прислать идентификатор и признак изменения, а данные запросить обычным AJAX-запросом.

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

Частые вопросы

Нужен ли отдельный push-сервер?

Без него модуль работает, но в режиме опроса: клиент обращается к серверу примерно раз в минуту, ускоряясь до десяти секунд, когда события идут. Для уведомлений это приемлемо, для настоящей мгновенности - нет, к тому же опрос создаёт лишнюю нагрузку на основной веб-сервер. Постоянное соединение требует настройки инфраструктуры, зато снимает и задержку, и нагрузку.

Как отправить событие группе пользователей?

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

Что можно передавать в параметрах команды?

Небольшой набор данных, достаточный чтобы понять, что произошло: идентификатор объекта, тип изменения, новое значение счётчика. Полные данные через этот канал не гонят - получив уведомление, клиент запрашивает актуальное состояние обычным запросом. Так и канал не перегружается, и данные всегда свежие.

Можно ли использовать Pull для неавторизованных посетителей?

Да, режим для гостей существует и включается отдельно. Он полезен для витринных сценариев - обновление остатков, счётчик просмотров, live-уведомления в каталоге. Помните только, что гостевые подключения увеличивают число соединений с push-сервером, и это стоит учитывать при планировании нагрузки.

Связанные темы

Первоисточники