Задания и cron¶
Всё медленное или подверженное сбоям (отправка почты, доставка уведомлений, чтение почтового ящика, индексация для поиска) выполняется как задание в очереди, а не внутри запроса, который его вызвал. Задания запускают три механизма: встроенная обработка, догоняющая обработка и фоновый процесс в cron.
Настройка cron¶
Фоновый процесс — bin/plugin helpdesk-pro work. Helpdesk Pro добавляет его в планировщик Grav как helpdesk-pro-jobs каждую минуту, поэтому нужно только поместить планировщик Grav в crontab:
PATH=/usr/local/bin:/usr/bin:/bin
* * * * * cd /path/to/site && php bin/grav scheduler >> /dev/null 2>&1
Укажите в строке PATH папку, где находится ваш бинарник PHP. Например, на macOS с Homebrew это что-то вроде /opt/homebrew/opt/php@8.4/bin.
Важно
Строка PATH не является необязательной. bin/plugin начинается с #!/usr/bin/env php, а планировщик запускает его как дочерний процесс, наследующий минимальный PATH из cron. Абсолютный путь к PHP в строке crontab исправляет родительский процесс, но не дочерний, поэтому планировщик может выглядеть здоровым, а каждое задание Helpdesk Pro будет завершаться с env: php: No such file or directory. Запустите bin/grav scheduler -d, чтобы вывести ошибки каждого задания.
Каждый запуск фонового процесса:
- выполняет готовые задания до 50 секунд (
--max-time) и до 50 заданий (--max-jobs); - планирует периодические задания, у которых ничего не ждёт;
- записывает время запуска, чтобы рабочая область могла предупредить об остановке cron;
- запускает тик фонового процесса для дополнений.
Фоновый процесс отказывается работать, пока есть ожидающие миграции.
Встроенная обработка¶
Когда запрос ставит задания в очередь, Helpdesk Pro выполняет эти задания, и только их, сразу после отправки ответа, в пределах jobs.inline_budget_seconds (3). Поэтому письмо с ответом сотрудника уходит через пару секунд. Чей-то клик не оплачивает чужую очередь: задания, поставленные другими запросами, ждут фонового процесса.
На PHP-FPM ответ уже у браузера, когда начинается обработка, поэтому посетителю это ничего не стоит. На mod_php браузер получил страницу, но процесс PHP остаётся занят обработкой, поэтому бюджет маленький.
Установите jobs.inline_drain в false, если работа после ответа создаёт проблемы на вашем хостинге. Тогда все задания забирает cron.
Догоняющая обработка без cron¶
Встроенная обработка запускает только то, что поставил запрос, а письмо-уведомление никогда не готово в том запросе, который его поставил: сначала уведомление ждёт льготный период или окно пакета. На сайте без cron такие письма ждали бы, пока что-нибудь не запустит фоновый процесс.
jobs.catch_up (включена по умолчанию) закрывает этот пробел. После ответа на веб-запрос Helpdesk Pro выполняет несколько готовых заданий, кто бы их ни поставил:
- только если cron-процесс не запускался последние две минуты, поэтому сайт с работающим cron за это не платит;
- не чаще раза в минуту для всего сайта;
- не более пяти заданий и двух секунд за проход;
- никогда до появления базы данных, поэтому сайт, который никогда не пользовался поддержкой, не получит её из-за просмотра страницы.
Проход также планирует периодические задания, которые иначе запланировал бы только фоновый процесс. Страницы фронтенда и вызовы API считаются веб-запросами; CLI никогда не выполняет догоняющую обработку.
Типы заданий из jobs.catch_up_exclude никогда не выполняются проходом. По умолчанию там search.embed, потому что встраивание для семантического поиска — медленная сетевая работа, которая должна выполняться в фоновом процессе. Установите jobs.catch_up в false, чтобы отключить догоняющую обработку; отключение jobs.inline_drain также отключает её.
Примечание
Догоняющая обработка зависит от посетителей. Тихий сайт отправляет почту поздно, поэтому настройте cron. Догоняющая обработка — страховка, а не план.
Повторные попытки и сбои¶
Задание, выбросившее исключение, повторяется с задержкой (30 секунд, затем 60, затем 120, максимум час), до трёх попыток или собственного лимита задания. После этого оно остаётся неудачным с последней ошибкой, пока кто-нибудь не запустит его снова. Неудачные задания никогда не удаляются очисткой по срокам хранения.
bin/plugin helpdesk-pro jobs --state=failed # список неудачных заданий с последней ошибкой
bin/plugin helpdesk-pro jobs --run=<id> # запустить одно снова сейчас
Задание, выполняющееся дольше jobs.job_timeout_seconds (120), считается неудачным и повторяется.
Состояние фонового процесса¶
bin/plugin helpdesk-pro status, Operations → System и GET /helpdesk-pro/status сообщают, когда фоновый процесс запускался последний раз и как, сколько заданий ожидает или завершилось неудачно, а также stale, когда задания ждут больше десяти минут и процесс не запускался столько же. В той же ситуации рабочая область показывает предупреждающую полосу.
Периодические задания¶
| Задание | Частота | Что делает |
|---|---|---|
maintenance.prune |
Ежедневно | Удаляет завершённые задания старше jobs.retention_days и выполняет всю очистку по срокам: старые окна ограничения частоты, истёкшие ссылки для входа, присутствие, отправленные письма, старые события справочного центра, старые прочитанные уведомления, старые запуски правил, старые доставки в каналы. |
rules.sweep |
Каждые десять минут | Выполняет правила по времени и встроенное автоматическое закрытие (Правила и автоматизация). |
sla.scan |
Каждую минуту | Фиксирует наступившие предупреждения и нарушения SLA и уведомляет о них (SLA). Не планируется, пока sla.enabled выключен. |
imap.poll |
Каждые inbound.imap.interval_seconds (две минуты) |
Читает почтовый ящик IMAP, пока приёмник — imap (Входящая почта). |
digest.sweep |
Ежечасно | Отправляет каждому человеку ежедневный дайджест, когда наступает его час дайджеста (Уведомления). |
attachments.gc |
Ежечасно | Истекает невостребованные черновые загрузки и удаляет сохранённые файлы, на которые больше ничего не ссылается. |
kb.sync |
Ежечасно | Переиндексирует базу знаний, когда статья изменилась вне Grav (git sync, FTP, развёртывание). |
Другие задания¶
| Задание | Что делает |
|---|---|
mail.send |
Обрабатывает очередь почты (Исходящая почта). |
notify.deliver |
Письмо-уведомление как запасной вариант для одного человека. |
magic_link.send |
Отправляет ссылку для входа. |
channel.deliver |
Отправляет одно сообщение в один канал уведомлений по своим правилам повторных попыток. |
inbound.process, inbound.fetch |
Обрабатывает полученное письмо или загружает письмо, на которое провайдер только сослался. |
search.index, search.rebuild, search.embed |
Индексация поиска, перестроение и семантическое встраивание (только фоновый процесс). |
sla.recompute |
Пересчитывает сроки SLA после изменения политики или рабочих часов. |
people.erase |
Удаляет человека. |
Настройки¶
На вкладке Advanced настроек плагина:
| Ключ | По умолчанию | Что делает |
|---|---|---|
jobs.inline_drain |
true |
Выполнять задания, поставленные запросом, сразу после отправки ответа. |
jobs.inline_budget_seconds |
3 |
Сколько один запрос может потратить на свои задания после ответа (не более 30). |
jobs.catch_up |
true |
На сайте, где cron не запускался две минуты, выполнять несколько готовых заданий после веб-запроса, не чаще раза в минуту. |
jobs.catch_up_exclude |
[search.embed] |
Типы заданий, которые никогда не выполняет догоняющая обработка. |
jobs.job_timeout_seconds |
120 |
Задание, выполняющееся дольше, считается неудачным и повторяется. 0 отключает ограничение. |
jobs.retention_days |
30 |
Завершённые и отменённые задания удаляются через столько дней. Неудачные задания никогда не очищаются. |