Application::addBackgroundJob — что происходит после ответа клиенту

21.04.2026

Проблема

Метод \Bitrix\Main\Application::addBackgroundJob() часто используют по памяти: передают callback с use и надеются, что «задача выполнится где-то в фоне». На практике у метода строгая сигнатура и несколько неочевидных побочных эффектов из Application::terminate(), о которых молчит PHPDoc. Разберём реальное поведение по коду ядра main/lib/application.php.

Решение

Сигнатура из ядра (main/lib/application.php):

        public function addBackgroundJob(
    callable $job,
    array $args = [],
    $priority = self::JOB_PRIORITY_NORMAL
);

    

Аргументы задачи — это второй параметр $args, а не замыкание с use. Оба варианта работают (внутри вызов идёт через call_user_func_array), но штатный путь — именно $args:

        \Bitrix\Main\Application::getInstance()->addBackgroundJob(
    [\Vendor\Module\Application\Service\Notifier::class, 'sendWelcome'],
    [$userId, $locale],
    \Bitrix\Main\Application::JOB_PRIORITY_NORMAL,
);

    

Доступные приоритеты: JOB_PRIORITY_NORMAL = 100, JOB_PRIORITY_LOW = 50. Очередь построена на SplPriorityQueue — большее число выполняется раньше.

Что именно происходит после отправки ответа, видно в terminate():

        // псевдокод из Application::terminate()
\CMain::RunFinalActionsInternal();
session_write_close();              // 1. Сессия закрыта
$pool = $this->getConnectionPool();
$pool->useMasterOnly(true);         // 2. Только мастер БД
$this->runBackgroundJobs();         // 3. Запуск джобов
$pool->useMasterOnly(false);

    

К моменту запуска джобов HttpResponse::send() уже вызвал fastcgi_finish_request() — клиент получил ответ и закрыл соединение. Отсюда прикладные следствия:

  1. Писать в $_SESSION бесполезно — сессия закрыта. Нужна сессия — используйте отдельное хранилище или перенесите логику в Messenger.
  2. Все SQL-запросы идут в мастер, реплики не используются — держите задачи короткими.
  3. Исключения внутри джобов ловятся и логируются через ExceptionHandler::writeToLog(), но последнее исключение после прогона всей очереди пробрасывается наверх. На ответ клиента это не повлияет, но зафиксируется в логах php-fpm и может оборвать воркер.
  4. Задачи могут добавлять новые задачи — внешний while ($this->backgroundJobs->valid()) дренирует очередь до пустоты. Следите за идемпотентностью, чтобы не получить бесконечный цикл.
  5. Нет гарантии доставки: падение процесса (OOM, таймаут) — задача теряется. Для надёжной обработки с ретраями используйте Messenger.

Итог

addBackgroundJob — это не «очередь», а хвост текущего запроса с уже закрытой сессией и мастер-соединением. Подходит для короткой работы в несколько сотен миллисекунд: метрики, уведомления, отложенные логи. Всё, что требует гарантий, — только через Bitrix\Main\Messenger.

Опубликовано 1 день назад

Комментарии (0)

Пожалуйста, войдите в аккаунт, чтобы оставить комментарий

Оставить комментарий

Пока нет ни одного комментария. Будьте первым!

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

AI Домовой История

0 / 25

Привет! Я помогу с вопросами по 1С-Битрикс.

Спрашивай про D7, ORM, компоненты или события.

Требуется авторизация

Войдите или зарегистрируйтесь, чтобы задавать вопросы AI-ассистенту.

Войти