Свой агент и задание по расписанию - создание, шаг, защита
Заводим фоновую задачу: разбираемся, когда достаточно агента, когда нужен отдельный скрипт и как не получить десять одновременных запусков.
Решение
Регистрируем агент:
CAgent::AddAgent( '\\Vendor\\Sync::run();', // строка вызова, а не замыкание 'main', // модуль-владелец 'N', // без проверки на повтор 3600, // период в секундах '', 'Y' // последние параметры: дата первого запуска и активность);// ночные задания ставят на тихие часы: период считают от времени первого запускаАгент хранится в базе строкой вызова, а не ссылкой на функцию. Отсюда требование к коду: вызываемый класс должен быть доступен на любом запросе, поэтому его подключают в файле с обработчиками, а не в шаблоне страницы.
Возвращаем строку перезапуска:
namespace Vendor;
class Sync { public static function run(): string { // полезная работа return '\\Vendor\\Sync::run();'; // без этой строки агент выполнится один раз }}Функция агента возвращает строку своего следующего вызова. Пустой возврат означает разовое выполнение: агент отработает и исчезнет из списка, а поиск причины «задача выполнилась только раз» занимает вечер.
Выносим тяжёлое в отдельный скрипт:
// /home/bitrix/www/local/tools/sync.php, запуск из расписания сервераdefine('NO_KEEP_STATISTIC', true);define('NOT_CHECK_PERMISSIONS', true);require $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php';CModule::IncludeModule('iblock'); // модули подключаются как обычно\Bitrix\Main\Diag\Debug::writeToFile(date('H:i:s') . " старт\n", '', 'sync.log');Скрипт с подключённым ядром получает всё то же, что и агент, но не делит время с посетителем. Многочасовая выгрузка в агенте занимает процесс пула и рано или поздно обрывается по времени выполнения.
Защищаемся от параллельных запусков:
* * * * * /usr/bin/flock -n /tmp/sync.lock /usr/bin/php /home/bitrix/www/local/tools/sync.php# без блокировки долгая задача запускается второй раз поверх первой// агент, запускающий бизнес-процессы, обязан проверять уже идущиеБлокировка нужна любой задаче, работающей дольше своего периода. Без неё расписание запускает второй экземпляр поверх первого, и два процесса пишут в одни данные с предсказуемым результатом.
Свои сообщения стоит писать в журнал событий сайта, а не в вывод. У задачи по расписанию нет экрана, и единственный способ узнать, что она делала ночью, - записи, оставленные ей самой.
Задачу стоит делать способной остановиться и продолжить с того же места. Ночная выгрузка, которая при обрыве начинается заново, на большом объёме не заканчивается никогда, а с сохранённой отметкой доходит до конца за несколько запусков.
Период агента задаёт паузу между запусками, а не точное время. Задача, которую надо выполнить строго в три часа ночи, живёт в расписании сервера, а не в агенте.
Типичные проблемы
Агент выполнился один раз и пропал.
Функция агента не вернула строку своего следующего вызова. Пустой возврат платформа понимает как разовое выполнение этой задачи.
Агент не запускается вовсе.
Указанный в агенте класс не подключён на обычных запросах сайта. Строку вызова платформа выполняет в общем окружении, а не в вашем файле.
Долгий агент тормозит сайт.
Он выполняется в процессе обычного посетителя сайта. Тяжёлые задачи выносят в отдельный скрипт по расписанию сервера.
Задача запускается по нескольку раз сразу.
Выполнение задачи длится дольше её собственного периода запуска. Второй экземпляр отсекается блокировкой на всё время работы первого.
Непонятно, отработала задача ночью или нет.
Задача ничего не пишет в журнал событий сайта. Вывод в консоль при запуске по расписанию никто не читает.
Частые вопросы
Чем агент отличается от задания по расписанию?
Агент живёт внутри платформы и знает её окружение, задание - обычный запуск скрипта сервером. Точное время даёт только второе.
Как удалить свой агент?
Вызовом удаления по той же строке и модулю. Забытые агенты от удалённых решений - частая причина ошибок в журнале.
Можно ли передать агенту параметры?
Только внутри строки вызова: она хранится как есть. Сложные данные держат в настройках модуля, а не в этой строке.
Почему агент выполняется не вовремя?
Период - это минимальная пауза, а не расписание. При запуске агентов на посещениях всё зависит ещё и от трафика.
Смежное
- Агенты изнутри: расписание, хиты, cron, блокировка - что происходит с агентом после регистрации
- Агенты и cron - оглавление подтемы
- Долгая операция шагами: порции, состояние, прогресс - когда работа не влезает в один запуск
- Агенты не выполняются: разбор причин - когда задача не запускается
- Обработчик события: регистрация, аргументы, отмена действия - где подключают код агента
- Прайс поставщика по расписанию: сопоставление, наценка, защита - типовое ночное задание магазина
- Журнал событий: чтение, очистка, свои записи - куда писать сообщения задачи
- Инфраструктура и хостинг - устройство площадки целиком
- Вызов внешнего сервиса из кода: таймауты, повторы, журнал - что чаще всего выносят в задание
- Свой модуль: структура, установка, автозагрузка - где живёт код фоновой задачи
- Своя таблица на ORM: сущность, запросы, изменение структуры - хранилище под свои данные
- Запуск бизнес-процесса из кода: шаблон, документ, повторы - типовая работа для агента
- Очередь обмена со сторонней системой: задания, повторы, сверка - типовая работа для расписания
- Даты в коде: объект, часовой пояс, фильтр по периоду - время запуска и границы периодов