Событие отброшенных событий веб-хука
[OnWebhookEventsDropped] События веб-хука сверх лимита пачки
На более ранних версиях событие не вызывается, а лишние события пропадают без записи в лог.
Один POST-запрос веб-хука МойСклад может нести несколько событий (массив events). За один запрос модуль обрабатывает не больше событий, чем задано в настройке «Количество событий за раз» на вкладке «Веб-хуки» (webhook_limit_count, по умолчанию 5). Всё, что сверх лимита, в каталог не попадает.
Раньше такие события терялись молча. Теперь модуль:
- пишет в лог модуля блок «Вебхук: события сверх лимита пачки не обработаны» — сколько событий отброшено из скольких и по строке на каждое: тип сущности, действие, ссылка (не больше 100 строк, остаток — одной строкой «…и ещё событий: N»);
- отдаёт отброшенные события вашему коду событием
OnWebhookEventsDropped.
В обычной работе МойСклад присылает одно событие на запрос, даже при массовом изменении товаров. Событие страхует от пачек, которые всё-таки пришли, а сами изменения в любом случае подхватит плановый агент импорта.
Что модуль гарантирует и чего нет
Событие вызывается до разбора событий пачки — сразу после проверки соли и того, что обмен включён. Поэтому в него попадают отброшенные события любых типов: и шести штатных (product, variant, bundle, service, productfolder, specialpricediscount), и сущностей, объявленных в реестре OnBuildWebhookEntityList.
Модуль их не разбирал: ни проверки href на принадлежность API МойСклад, ни нормализации домена, ни проверки действия, ни дедупликации к ним не применялось. Элементы массива events приходят ровно такими, какими были в теле запроса, — это недоверенные данные. Прежде чем обращаться по meta->href, проверьте адрес сами, например \Rbs\MoyskladStocks\ApiNew::isAvailableUrl($href) — предварительно приведя домен вызовом \Rbs\MoyskladStocks\ApiNew::replaceOldDomain($href).
Модуль перехватывает исключение обработчика и пишет его текст в тот же блок лога. Обработчики, зарегистрированные после упавшего, в этом запросе не вызываются. Результат обработчика не читается.
- Описание события
- Пример вызова события
- Примеры использования
Параметры события
| Параметр | Тип | Описание |
|---|---|---|
events | array | Отброшенные элементы events из тела веб-хука, как они пришли от МойСклад |
limit | int | Лимит событий на один запрос, действовавший в момент приёма |
total | int | Сколько событий было в запросе всего |
Число отброшенных — count($events), то есть total - limit.
Возвращаемое значение
Ничего возвращать не нужно — результат не читается.
//Пример кода нужно вставить в файл init.php
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
'rbs.moyskladstocks',
'OnWebhookEventsDropped',
'OnWebhookEventsDroppedHandler'
);
function OnWebhookEventsDroppedHandler(\Bitrix\Main\Event $event)
{
$eventParams = $event->getParameters();
$limit = $eventParams['limit']; // лимит событий на запрос
$total = $eventParams['total']; // сколько событий пришло всего
// $droppedEvents — элементы events из тела веб-хука, без всякой проверки:
// $eventHook->action // 'CREATE' | 'UPDATE' | 'DELETE'
// $eventHook->meta->type // 'product', 'variant', 'consignment', ...
// $eventHook->meta->href // ссылка на сущность — проверяйте перед использованием
$droppedEvents = $eventParams['events'];
foreach ($droppedEvents as $eventHook) {
if (!is_object($eventHook) || !isset($eventHook->meta->href)) {
continue;
}
#WORK_AREA#
}
}
Дообработать отброшенные товары отдельным агентом
Обрабатывать события прямо в обработчике не стоит: МойСклад ждёт ответа на веб-хук. Надёжнее отложить их в свою очередь и разобрать агентом.
function OnWebhookEventsDroppedHandler(\Bitrix\Main\Event $event)
{
foreach ($event->getParameter('events') as $eventHook) {
if (!is_object($eventHook) || !isset($eventHook->meta->type, $eventHook->meta->href)) {
continue;
}
// домен в href модуль не нормализовал — приводим сами, иначе ссылка
// на старый домен МойСклад не пройдёт проверку ниже
$href = \Rbs\MoyskladStocks\ApiNew::replaceOldDomain((string)$eventHook->meta->href);
// данные не проверены модулем — отсекаем чужие адреса сами
if (!\Rbs\MoyskladStocks\ApiNew::isAvailableUrl($href)) {
continue;
}
// Хранение очереди — на стороне разработчика
YourWebhookQueue::push([
'type' => (string)$eventHook->meta->type,
'action' => (string)($eventHook->action ?? ''),
'href' => $href,
]);
}
}
Сигнал, что лимит пора поднять
function OnWebhookEventsDroppedHandler(\Bitrix\Main\Event $event)
{
YourMonitoring::notify(sprintf(
'МойСклад: отброшено %d событий веб-хука из %d, лимит %d',
count($event->getParameter('events')),
$event->getParameter('total'),
$event->getParameter('limit')
));
}