Дата последнего изменения: 21.12.2023
Приложение не в всегда в состоянии принимать события. Оно может скрываться за фаерволлами, жить во внутренней сети и т.д. В этом случае используется механизм офлайн-событий, когда приложение подписывается на события, но не указывает URL обработчика. Вместо этого приложение указывает, чтобы события копились в базе, пока оно само их не заберет.
Механизм офлайн события используется для работы со сторонними информационными системами. Например, текущая интеграция продукта с 1С целиком построена на офлайн событиях.
Отличительная особенность офлайн событий от обычных: если событие ещё не обработано, то его копии не создаются. Например: сделка изменена 5 раз. При использовании обычных событий - вызов обработчика выполнится 5 раз, а офлайн событий - оставит 1 запись в журнале об изменении сделки.
Записи в очереди аккумулируются по данным событий. Например, если в очереди уже ожидает событие ONCRMLEADUPDATE
для лида с ID=10, то следующее обновление лида 10 не добавит новую запись, а только изменит дату существующей.
В общем виде работы схемы очень проста. Офлайн событие попадает в очередь офлайн событий. Потом внешняя система забирает их из очереди и обрабатывает.
Есть две схемы работы этого механизма - простая и усложнённая. В простой схеме приложение просто подписывается на события и по мере надобности забирает "верхнюю" часть очереди. В усложнённой схеме приложение имеет возможность управлять разбором очереди, самостоятельно разделять записи на отработанные и требующие разрешения конфликта и т.д.
Технологический поток 21.05.2021: Преимущества офлайн-событий, или как использовать REST правильно
Для регистрации офлайн события используется метод /rest/event.bind со значением event_type=offline
. В этом случае параметр handler становится не обязательным, а параметр auth_type - бессмысленным.
Пример вызова:
https://myportal.bitrix24.com/rest/event.bind ?auth=0534845a0000cd7a0000cd5d00000001000003bc52a2dde6b58915beb0a09fcc57ed36 // ключ авторизации &event=ONCRMLEADUPDATE // название события &event_type=offline // тип события &auth_connector=OneC // ключ источника HTTP/1.1 200 OK { "result": true }Все основные параметры описаны в документации метода /rest/event.bind. На параметре &auth_connector остановимся немного подробнее.
&auth_connector=OneC
- ключ источника. Этот важный параметр отличает офлайн события от онлайн, т.к. позволяет исключать ложные срабатывания событий.
Что такое ложное срабатывание события
?. Рассмотрим на примере:
Пусть у нас есть Битрикс24 и 1С. В Битрикс24 зарегистрировано 2 события:
Создали компанию. Сработало событие, по которому компания попала в 1С. Затем в 1С компания была изменена посредством Rest и изменения попали в Битрикс24. В теории, должно сработать офлайн событие на обновление компании и снова попасть в 1С, что нелогично.
Для того, чтобы такие события не регистрировались используется параметр &auth_connector. Этот параметр нужно указывать не только при таком Rest запросе при регистрации офлайн события, но так же в любом Rest запросе, который выходит из учетной системы.
Таким образом это обязательный параметр для rest запросов из внешних систем:
Правильно
https://my.bitrix24.ru/rest/crm.company.add?auth=123456&auth_connector-OneC&fields[TITLE]=Test
Неправильно
https://my.bitrix24.ru/rest/crm.company.add?auth=123456&fields[TITLE]=Test
После вызова установки обработчика метод /rest/event.get выдает нам вот такую картину (обычный обработчик события добавлен для сравнения):
https://myportal.bitrix24.com/rest/event.get ?auth=0534845a0000cd7a0000cd5d00000001000003bc52a2dde6b58915beb0a09fcc57ed36 HTTP/1.1 200 OK { "result": [ { "connector_id": "", "event": "ONCRMLEADUPDATE", "offline": 1 }, { "auth_type": "0", "event": "ONCRMLEADUPDATE", "handler": "http://apphost.com/handler/", "offline": 0 } ] }
Для отписки от события используется тот же самый метод /rest/event.unbind, вызываемый с теми же параметрами, что и event.bind.
Далее происходит разбор очереди событий.
Если приложение вызывает метод /rest/event.offline.get, то портал отдаст первые 50 событий, удовлетворяющих фильтру и в заданном порядке сортировки, и сразу вычистит их из базы.
https://myportal.bitrix24.com/rest/event.offline.get ?auth=0534845a0000cd7a0000cd5d00000001000003bc52a2dde6b58915beb0a09fcc57ed36 HTTP/1.1 200 OK { "result": { "events": [ { "EVENT_ADDITIONAL": { "user_id": "1" }, "EVENT_DATA": { "FIELDS": { "ID": 28 } }, "EVENT_NAME": "ONCRMLEADUPDATE", "ID": "40", "MESSAGE_ID": "438d4ec3d329464c4bb9909db4c7a19b", "TIMESTAMP_X": "2018-02-14T14:20:19+02:00" } ], "process_id": null } }
|
Метод event.offline.get поддерживает многопоточный разбор. То есть допускается несколько параллельных запросов к методу (с соблюдением ограничений на количество запросов в единицу времени), и каждый из них получит разные наборы записей.
Основное отличие этой схемы от простой в том, что выбранные записи не удаляются из базы, а помечаются как обрабатываемые. Они продолжают оставаться в базе, пока приложение не оповестит об окончании их обработки. Если за время обработки появятся новые срабатывания события, то они будут добавлены в очередь как обычно, даже если запись о таком событии уже есть среди обрабатываемых. Другой поток обработки сможет получить сообщение об изменении.
Получение записей
Включается эта схема добавлением параметра clear=0
к вызову event.offline.get.
https://myportal.bitrix24.com/rest/event.offline.get ?auth=0534845a0000cd7a0000cd5d00000001000003bc52a2dde6b58915beb0a09fcc57ed36 &clear=0 HTTP/1.1 200 OK { "result": { "events": [ { "EVENT_ADDITIONAL": { "user_id": "1" }, "EVENT_DATA": { "FIELDS": { "ID": 28 } }, "EVENT_NAME": "ONCRMLEADUPDATE", "ID": "45", "MESSAGE_ID": "438d4ec3d329464c4bb9909db4c7a19b", "TIMESTAMP_X": "2018-02-14T14:43:13+02:00" } ], "process_id": "5xcvetmo5zm5li73qxnj8qu72e2qrxw8" } }
Обратите внимание на поле process_id в ответе. После такого вызова записи остаются в базе, но помечаются как обрабатываемые процессом с этим идентификатором. И далее не учитываются ни при каких последующих выборках и при добавлении новых событий.
После того, как записи выбраны, помечены как обрабатываемые и отданы приложению, приложение может какие-то из них удалить, какие-то пометить как ошибочные, какие-то оставить на потом.
Очистка записей
Очистка производится вызовом метода /rest/event.offline.clear, который принимает на вход process_id и массив идентификаторов записей, которые нужно удалить.
https://myportal.bitrix24.com/rest/event.offline.clear ?auth=0534845a0000cd7a0000cd5d00000001000003bc52a2dde6b58915beb0a09fcc57ed36 &process_id=5xcvetmo5zm5li73qxnj8qu72e2qrxw8 HTTP/1.1 200 OK { "result": true }
result.events[].ID
, а не result.events[].EVENT_DATA.FIELDS.ID
.Обработка ошибок
При создании сложных интеграций, для которых и предназначена усложнённая схема, вполне возможна ситуация, когда возникает конфликт данных различных систем. В этом случает требуется человеческий контроль или использование какого-то другого способа разрешения конфликтов. Чтобы при этом не стопорить процесс и не копить ошибки, некоторые записи о событиях можно оставлять в базе с пометкой об их ошибочности. Для этого используется метод /rest/event.offline.error.
https://myportal.bitrix24.com/rest/event.offline.error ?auth=4742845a0000cd7a0000cd5d0000000100000386a97f24a7f515e9ec5e242fed727af4 &process_id=cal3dm2qg31gb3g8uatca6huqjdtdn6u &message_id[]=438d4ec3d329464c4bb9909db4c7a19b HTTP/1.1 200 OK { "result": true }
После выставления флага об ошибке, помеченные записи перестанут отдаваться приложению при вызове event.offline.get. Перестают отдаваться как сама помеченная запись, так и все последующие срабатывания события с этими данными. Иными словами, изменения этой сущности на стороне Битрикс24 перестанут передаваться в приложение, пока приложение не даст разрешение на передачу. Также запись отвяжется от текущего процесса и не будет удалена при вызове event.offline.clear. Если за время обработки были срабатывания события с такими данными, они также передаются приложению, даже если уже были захвачены другим процессом.
Разрешение ошибок
Чтобы снять пометку об ошибке с записи, нужно вычистить ее из базы при помощи event.offline.get с указанием параметра error=1
. И при необходимости, с дополнительным фильтром, если нужно обработать только часть ошибок. Сразу после вызова ошибочные записи будут вычищены из базы (если указать clear=1
), либо помечены как обрабатываемые (если указать clear=0
). В обоих случаях новые события с такими данными снова начнут регистрироваться и отдаваться приложению.
Простое получение состояния очереди
Иногда может потребоваться считать текущую очередь, не внося изменений в ее состояние, как это делает event.offline.get, и не завися от сложной логики пометки ошибочных событий или раскидывания событий по процессам. Для этого сделан простой списочный метод /rest/event.offline.list:
https://myportal.bitrix24.com/rest/event.offline.list ?auth=4742845a0000cd7a0000cd5d0000000100000386a97f24a7f515e9ec5e242fed727af4 HTTP/1.1 200 OK { "result": [ { "ERROR": "0", "EVENT_ADDITIONAL": { "user_id": "1" }, "EVENT_DATA": { "FIELDS": { "ID": 28 } }, "EVENT_NAME": "ONCRMLEADUPDATE", "ID": "60", "MESSAGE_ID": "438d4ec3d329464c4bb9909db4c7a19b", "PROCESS_ID": "", "TIMESTAMP_X": "2018-02-14T15:34:34+02:00" }, { "ERROR": "0", "EVENT_ADDITIONAL": { "user_id": "1" }, "EVENT_DATA": { "FIELDS": { "ID": 27 } }, "EVENT_NAME": "ONCRMLEADUPDATE", "ID": "65", "MESSAGE_ID": "7bf367ea2e4c9b6a8c3adac4a416627c", "PROCESS_ID": "", "TIMESTAMP_X": "2018-02-14T15:34:55+02:00" } ] }