
Разработка заданий
Код задания — обычный PHP-файл, сниппет или процессор. Что доступно внутри каждого типа — в Создании задания.
Передача данных
Данные из второго аргумента schedule() попадают в задание переменной $scriptProperties. Читайте их через getOption() — он подставит значение по умолчанию, если ключа нет:
$clientId = $modx->getOption('client', $scriptProperties, 0);У сниппета в $scriptProperties лежат ещё task и run — объекты задания и запуска. У процессора они достаются через $this->getProperty('task') и $this->getProperty('run').
Возврат результата
Верните из задания строку — она сохранится в поле message запуска и будет видна в админке. Если нужно сохранить структуру, верните JSON:
return json_encode(['processed' => $count], JSON_UNESCAPED_UNICODE);echo и print не перехватываются: напечатанное уйдёт в вывод cron, а не в запуск, так что для отчёта о работе они не годятся. Увидеть результат можно в админке, на вкладке «Прошедшие запуски».
У процессорного задания результат собирается иначе: в message попадает сообщение из ответа процессора, а возвращать строку самому не нужно.
Ошибки
Запуск считается упавшим, если в нём есть хотя бы одна запись об ошибке. Добавляет её addError(): первый аргумент — тип ошибки, второй — массив подробностей. Возврат false на статус не влияет. У процессорного задания своя дорога: в запуск переносятся ошибки полей из ответа процессора, по одной записи на поле.
if (empty($scriptProperties['client'])) {
$run->addError('missing_client', [
'data' => $scriptProperties,
]);
return 'Не передан идентификатор клиента';
}Исключения перехватывает сам Scheduler. Непойманный Exception или Error даёт запуску ошибку с типом по имени класса исключения, а в подробностях — ключи exception (сообщение), code, file, line и trace. Проход cron при этом не прерывается и берётся за следующий запуск. Оборачивать всё задание в try/catch незачем — только если хотите обработать сбой по-своему.
А вот обрыв процесса планировщик не отслеживает: если задание убил таймаут PHP, нехватка памяти или exit, запуск так и останется в статусе «Выполняется» — он не выполнится и не упадёт. Автоматического сброса таких запусков нет, в админке их видно по счётчику «Выполняется».
Статусы и поля запуска
У запуска четыре статуса:
Текущий лежит в поле status, числом:
| Статус | Константа | Значение | Когда |
|---|---|---|---|
| Запланировано | sTaskRun::STATUS_SCHEDULED | 0 | Запуск поставлен в очередь и ждёт своего времени |
| Выполняется | sTaskRun::STATUS_EXECUTING | 1 | Проход cron забрал запуск |
| Успешно | sTaskRun::STATUS_SUCCESS | 2 | Задание отработало и не добавило ни одной ошибки |
| Ошибка | sTaskRun::STATUS_FAILURE | 3 | В запуске есть запись об ошибке |
Что ещё лежит в запуске:
| Поле | Содержимое |
|---|---|
task | Идентификатор задания, которому принадлежит запуск |
timing | Когда выполнять — метка времени из первого аргумента schedule(), округлённая до минуты |
data | Массив, переданный в schedule() — он же $scriptProperties |
message | Значение, которое вернуло задание. Не строку приведёт к строке, ничего не вернули — останется пустым |
errors | Массив записей об ошибках. В каждой — type, timestamp и переданные подробности, разложенные рядом с ними, а не вложенные |
executedon | Метка времени выполнения. У запуска, который ещё не выполнялся, пусто |
processing_time | Длительность в секундах |
retry_count | Номер повторной попытки, 0 — первый запуск |
task_key | Метка из третьего аргумента schedule() |
Чтение результата из кода
У задания нет метода, который отдаёт последний запуск, — запуски читаются запросом. В примере $task — объект задания: внутри самого задания он уже есть, а извне его берут через getTask(), как в Планировании задания.
$c = $modx->newQuery('sTaskRun');
$c->where(['task' => $task->get('id')]);
$c->sortby('executedon', 'DESC');
$c->limit(1);
/** @var sTaskRun|null $lastRun */
$lastRun = $modx->getObject('sTaskRun', $c);
if ($lastRun && $lastRun->hasErrors()) {
print_r($lastRun->get('errors'));
}