PunchKano begins diphtheria immunisation in five Kano LGsRTP DesportoFrancisco Cabral na final de pares em HangzhouESPN DeportesGrecia derrotó a Alemania por primera vez en la historia y golpeó a Klopp en su debut ante su públicoThe Jerusalem PostIsrair awaits final approval for Tokyo, Miami flights, adds new European destinations for 2027Daily MaverickWe worried AI would make things up, we should also worry when it doesn’tInquirerRains to continue in Visayas, Mindanao due to ITCZ until Sept. 30Bollywood HungamaVinod Kapri's Pyre to release in theaters on October 23, 2026BlickNächstes Amt abgelegt: Jens Spahn zieht sich aus Haushaltsausschuss zurückRapplerPhilippines should fix tax gaps and procurement, not raise tax rates – WBSportstarIndia in Athletics LIVE Updates, Asian Games 2026: Vithya Ramraj breaks National Record to win 400m hurdles bronze; Javelin throw final at 4:45 PM ISTIl Fatto QuotidianoMorto Stefano Milani, il tifoso del Milan diventato famoso su X. Da Bertolucci a Valenti: “Ha lottato come nessuno, mai un passo indietro”7sur7“Pourquoi je perds toujours?”: quand André Agassi taquine Alexander Zverev
The Daily Newsstand · Free, Always
Monday, September 28, 2026

Очереди сообщений в Bitrix Framework

Translate

В статье вместе с Ильей Рупасовым@rpsv, Григорием Бычеком@gbychek и Мариной Павловой @MarinaPav разбираем один такой сценарий: после изменения события в календаре Битрикс24 нужно синхронизировать его с Google Calendar. Вынесем эту операцию в очередь, создадим сообщение и обработчик, настроим очередь и проверим результат в логе.

❗️ Механизм очередей доступен с версии 25.100.300 главного модуля 

Как работают очереди

Очереди нужны, когда какую-то операцию нужно выполнить отдельно от основного действия пользователя.

Вот пример: сотрудник изменил событие в календаре Битрикс24, а его нужно синхронизировать с Google Calendar. При обычной синхронной обработке запрос будет ждать, пока Битрикс24 обратится к Google и получит ответ. Если внешний сервис отвечает медленно, пользователь тоже будет ждать. Если сервис временно недоступен, ошибка может повлиять и на основной запрос.

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

Для этого механизм очередей использует несколько элементов. 

  • Сообщение содержит данные, которые понадобятся для фоновой операции — например, ID события и внешнего календаря.

  • Очередь определяет, какой обработчик должен получить сообщение и с какими настройками оно будет обрабатываться.

  • Брокер сохраняет сообщения до момента обработки. В текущей версии Bitrix Framework поддерживается брокер типа db, поэтому сообщения хранятся в базе данных.

  • Воркер получает доступные сообщения из брокера и передаёт их обработчику. Обработчик выполняет саму фоновую работу. В нашей статье реальную синхронизацию с Google Calendar заменим записью в лог.

Весь путь выглядит так:

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

Очереди могут работать в режимах web и cli. В режиме web обработка запускается через фоновые задачи после завершения веб-запроса. В режиме cli сообщения получает отдельный консольный воркер. Дальше воспользуемся cli, чтобы явно запустить обработку и проверить результат в логе.

Создаём сообщение

Начнём с сообщения — объекта, в котором хранятся данные для фоновой обработки. В нашем случае нужно передать обработчику информацию о событии Битрикс24, которое затем будет синхронизировано с Google Calendar.

Класс сообщения можно создать вручную или сгенерировать встроенной консольной командой Bitrix Framework:

php bitrix.php make:message GoogleEventSync -m my.module -n

Команда make:message создаёт класс сообщения для механизма очередей. Она доступна с версии main 25.900.0. Подробнее о генерации классов можно прочитать в разделе документации о консольных командах Bitrix Framework.

Добавим в сообщение данные, которые понадобятся при синхронизации — ID события, ID внешнего календаря и тип операции:

use Bitrix\Main\Messenger\Entity\AbstractMessage;
use Bitrix\Main\Messenger\Entity\MessageInterface;

class GoogleEventSyncMessage extends AbstractMessage
{
public function __construct(
public readonly int $eventId,
public readonly string $externalCalendarId,
public readonly string $operation
) {}
}

Здесь мы используем только простые типы данных — int и string. AbstractMessage умеет автоматически преобразовывать такие поля при сохранении сообщения и восстанавливать их при обработке, поэтому дополнительный код для сериализации в нашем случае не нужен.

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

use Bitrix\Main\Messenger\Entity\AbstractMessage;
use Bitrix\Main\Messenger\Entity\MessageInterface;

class GoogleEventSyncMessage extends AbstractMessage
{
public function __construct(
public readonly int $eventId,
public readonly string $externalCalendarId,
public readonly string $operation
) {}

public function jsonSerialize(): mixed
{
return [
'eventId' => $this->eventId,
'externalCalendarId' => $this->externalCalendarId,
'operation' => $this->operation,
];
}

public static function createFromData(array $data): MessageInterface
{
return new static(...$data);
}
}

Классы сообщений рекомендуется создавать на основе AbstractMessage. Данные сообщения должны поддерживать JSON-сериализацию: простые типы вроде string и int можно сохранять напрямую. Метод jsonSerialize() определяет, какие данные попадут в сохранённое сообщение, а createFromData() позволяет восстановить объект перед обработкой.

Например, сообщение для нашего сценария может содержать такие данные:

{
"eventId": 123,
"externalCalendarId": "google-calendar-42",
"operation": "update"
}

Само сообщение синхронизацию не запускает. Оно сохраняет данные, которые позже получит обработчик очереди.

Создаём обработчик

Теперь создадим обработчик — класс, который получит GoogleEventSyncMessage из очереди и выполнит нужное действие. В рабочем сценарии здесь находился бы код синхронизации события с Google Calendar, но в нашем примере для демонстрации очереди мы просто запишем полученные данные в лог.

Класс обработчика можно создать вручную или сгенерировать консольной командой make:messagehandler:

php bitrix.php make:messagehandler GoogleEventSync --handler-module=my.module --message-module=my.module -n

Обработчик наследуется от AbstractReceiver. Основная работа выполняется в методе process() — Bitrix Framework вызовет его, когда сообщение дойдёт до обработки.

use Bitrix\Main\Diag\LoggerFactory;
use Bitrix\Main\Messenger\Entity\MessageInterface;
use Bitrix\Main\Messenger\Receiver\AbstractReceiver;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;

class GoogleEventSyncMessageHandler extends AbstractReceiver
{
    private readonly LoggerInterface $logger;

    public function __construct()
    {
        $this->logger = (new LoggerFactory())->createDefault() ?? new NullLogger();
    }

    /**
      @param GoogleEventSyncMessage $message
     /
    protected function process(MessageInterface $message): void
    {
        $this->logger->info(
            "Google Calendar sync: event {$message->eventId}, "
            . "calendar {$message->externalCalendarId}, "
            . "operation {$message->operation}"
        );
    }
}

В process() доступны данные, которые мы сохранили в GoogleEventSyncMessage: ID события, ID внешнего календаря и тип операции. Пока обработчик только записывает их в лог. Логгер создаём через LoggerFactory, а сообщение записываем методом info().

Чтобы проверить результат примера, файловое логирование должно быть настроено заранее. Подробнее о настройке можно прочитать в документации по логгерам Bitrix Framework.

Если process() завершился без исключения, сообщение считается успешно обработанным. Обработку ошибок и повторные попытки в этом сценарии настраивать не будем — для них в документации по очередям тоже есть подробный раздел.

Регистрируем очередь в конфигурации модуля

Обработчик мы создали, но система пока не знает, какую очередь он должен обслуживать. Очереди конкретного модуля настраиваются в его файле .settings.php. Зарегистрируем очередь google_event_sync и свяжем её с созданным GoogleEventSyncMessageHandler. Такая структура соответствует модульной конфигурации очередей в Bitrix Framework.

Если в .settings.php уже есть другие настройки, секцию messenger нужно добавить в существующий массив конфигурации.


return [
'messenger' => [
'value' => [
'queues' => [
// Очередь для синхронизации событий с Google Calendar.
'google_event_sync' => [
// Класс обработчика сообщений этой очереди.
'handler' =>

\My\Module\Internals\Integration\My\Module\MessageHandler\GoogleEventSyncMessageHandler::class,


],
],
],

// Запрещаем изменять настройки через API.
'readonly' => true,
],
];

Ключ google_event_sync — идентификатор очереди. Его будем использовать дальше, когда отправим сообщение на обработку. Параметр handler связывает очередь с GoogleEventSyncMessageHandler: сообщения из этой очереди Bitrix Framework будет передавать этому обработчику. 

Для очереди можно дополнительно указать брокер, ограничения на количество одновременно обрабатываемых сообщений и правила повторных попыток. В нашем сценарии эти настройки не нужны, поэтому оставим только handler. Если брокер отдельно не указан, используется брокер default, который настроим на следующем шаге.

Включаем очереди на уровне проекта

В предыдущем разделе мы зарегистрировали очередь google_event_sync в конфигурации модуля. Теперь настроим механизм очередей на уровне всего проекта.

Глобальные настройки находятся в файле /bitrix/.settings.php. Для нашего сценария нужно указать режим обработки и брокер default, в котором будут храниться сообщения. 

// цитата // Если в /bitrix/.settings.php уже есть другие настройки, секцию messenger нужно добавить в существующий массив конфигурации.

В статье будем использовать консольный режим cli: на последнем шаге вручную запустим обработку очереди и проверим результат в логе.

return [
'messenger' => [
'value' => [
'run_mode' => 'cli',
'brokers' => [
'default' => [
'type' => 'db',
'params' => [
'table' =>
\Bitrix\Main\Messenger\Internals\Storage\Db\Model\MessengerMessageTable::class,
],
],
],
],
'readonly' => true,
],
];

Параметр run_mode определяет способ обработки сообщений. Значение cli означает, что их будет забирать консольный воркер, который мы запустим позже командой messenger:consume.

В brokers перечислены хранилища сообщений. Сейчас Bitrix Framework поддерживает брокер типа db, который сохраняет сообщения в базе данных. Брокер с именем default используется автоматически, если для конкретной очереди не указан другой. Для нашей очереди google_event_sync отдельный брокер мы не задавали, поэтому сообщения попадут именно сюда.

Очередь и обработчик настроены. Теперь система знает две вещи: очередь google_event_sync должен обслуживать GoogleEventSyncMessageHandler, а сообщения этой очереди нужно хранить через брокер default. 

Отправляем сообщение в нужном месте

Сейчас нужно поставить задачу на синхронизацию в тот момент, когда событие Битрикс24 уже изменено и его данные можно передать на фоновую обработку. В этом месте создаём объект GoogleEventSyncMessage и передаём в него данные события.

В контексте нашего примера мы предполагаем, что $eventId и $externalCalendarId уже получены в коде, который обрабатывает изменение события:

$message = new GoogleEventSyncMessage(
$eventId,
$externalCalendarId,
'update'
);

Затем отправляем сообщение в очередь google_event_sync методом send():

$message->send('google_event_sync');

Идентификатор в send() должен совпадать с именем очереди, которое мы указали в .settings.php модуля. В предыдущем разделе мы зарегистрировали именно google_event_sync и связали её с GoogleEventSyncMessageHandler.

После вызова send() Bitrix Framework сериализует данные GoogleEventSyncMessage и передаёт сообщение брокеру default. Основной код может продолжить работу, а сообщение будет ждать обработки в брокере.

В нашем сценарии полный путь теперь выглядит так:

изменили событие → создали GoogleEventSyncMessage → отправили в google_event_sync → брокер default сохранил сообщение

Запускаем обработку и проверяем результат

На предыдущем шаге мы отправили GoogleEventSyncMessage в очередь google_event_sync. Сообщение уже хранится у брокера и ждёт обработки.

В глобальной конфигурации мы выбрали режим cli, поэтому запустим консольный воркер и укажем ему нашу очередь:

php bitrix.php messenger:consume google_event_sync

Команда messenger:consume запускает обработку очередей. Воркер получает доступные сообщения из брокера и передаёт их связанным с очередями обработчикам. Если указать идентификатор очереди после команды, воркер будет обрабатывать именно её.

Сейчас воркер найдёт GoogleEventSyncMessage в очереди google_event_sync и передаст его в GoogleEventSyncMessageHandler. Метод process() выполнится и запишет в лог данные, которые мы передали в сообщении:

Google Calendar sync: event 123, calendar google-calendar-42, operation update

Так мы проверяем весь путь сообщения:

`GoogleEventSyncMessage → 

google_event_sync → 

брокер default → 

GoogleEventSyncMessageHandler → лог`

Открываем лог, настроенный для AddMessage2Log(), и проверяем, что запись появилась.

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

Послесловие

В реальной интеграции с Google Calendar стоит учитывать, что внешний сервис может временно не ответить. Для таких случаев у очереди можно настроить retry_strategy — правила повторной обработки сообщения с количеством попыток и задержками между ними.

Асинхронная обработка также означает, что между отправкой сообщения и его получением обработчиком может пройти некоторое время. За этот период исходные данные могут измениться или исчезнуть, поэтому в сообщение стоит заранее передавать всё, что понадобится для выполнения операции. Для синхронизации с внешними системами это особенно важно.

В статье мы прошли основной сценарий работы с очередью. Для более сложных случаев Bitrix Framework позволяет ограничивать количество одновременно обрабатываемых сообщений, откладывать обработку и использовать отдельную таблицу для их хранения. Подробные настройки и примеры есть в документации по очередям Bitrix Framework.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.