Queuety
Механизм рабочих процессов WordPress.
wp plugin install https://github.com/inline0/queuety/releases/latest/download/queuety.zip --activateПоследний выпуск v0.22.0 GPL-2.0-or-later WordPress 6.4+, PHP 8.2+
use Queuety\Queuety;
Queuety::register( 'send_email', SendEmailHandler::class );
Queuety::dispatch( 'send_email', [
'to' => 'user@example.com',
'subject' => 'Welcome',
'body' => 'Hello from Queuety!',
] );На практике
Рабочий процесс, заданный в PHP, и команда исполнителя, которая его запускает.
Рабочий процесс с подтверждением
Рабочий процесс выполняет шаг, ждёт 24 часа, затем приостанавливается на wait_for_approval() до тех пор, пока другой процесс не отправит сигнал approval.
Задержка хранится в базе данных, поэтому она сохраняется после перезапуска исполнителя и развёртывания обновлений, а сигнал, отправленный заранее, записывается и обрабатывается, когда рабочий процесс доходит до ожидания. При отмене запуска вызывается обработчик on_cancel().
$workflow_id = Queuety::workflow( 'approval_flow' )
->then( SubmitRequestHandler::class )
->delay( hours: 24 )
->wait_for_approval()
->then( ProcessApprovalHandler::class )
->on_cancel( CleanupHandler::class )
->dispatch( [ 'request_id' => 99 ] );
// Later, from another process:
Queuety::signal( $workflow_id, 'approval', [ 'approved_by' => 'admin@example.com' ] );# Single worker on default queue
wp queuety work
# Process a specific queue
wp queuety work --queue=emails
# Process multiple queues in priority order
wp queuety work --queue=critical,default,low
# One-shot mode
wp queuety work --once
# Multi-worker mode
wp queuety work --workers=4
# Adaptive worker pool
wp queuety work --queue=providers --min-workers=2 --max-workers=6Прямое получение MySQL
Каждый исполнитель работает в длительно работающем процессе WP-CLI и получает задачи напрямую из MySQL с помощью FOR UPDATE SKIP LOCKED.
Надёжные рабочие процессы
Многоэтапные процессы с постоянным состоянием, переживающим тайм-ауты PHP, сбои и повторные запуски.
Конечные автоматы
Длительно живущее состояние, управляемое событиями, с Queuety::machine(): определяйте состояния и переходы, отправляйте события, просматривайте хронологию.
Сигналы и подтверждения
wait_for_signal(), wait_for_approval() и wait_for_input() приостанавливают рабочий процесс до поступления внешнего ввода.
Уровни приоритета
Четыре уровня: от низкого до срочного. В очереди задачи с более высоким приоритетом берутся первыми.
Ограничение частоты запросов
Лимиты для каждого обработчика в скользящем окне. Исполнитель, получивший задачу с ограничением частоты, возвращает её в очередь и ждёт.
Повторяющиеся задачи
Расписание по интервалу и на основе cron. Встроенный анализатор cron без внешних зависимостей.
Параллельные шаги
Запускайте шаги рабочего процесса параллельно и ждите завершения всех перед переходом дальше.
Метрики и журналы
Постоянный журнал в базе данных с пропускной способностью, средней длительностью, длительностью p95 и долей ошибок для каждого обработчика.
Резервный режим WP-Cron
Без доступа к оболочке событие WordPress cron, запускаемое раз в минуту, выполняет одноразовый исполнитель для очереди по умолчанию.
Промежуточное ПО
Промежуточное ПО задач в стиле «луковицы» для ограничения частоты, регулирования исключений, обеспечения уникальности, тайм-аутов и защиты от параллельного выполнения.
PHP 8.2+
Перечисления, классы только для чтения, выражения match, продвижение свойств конструктора и атрибуты PHP.
Почему Queuety
Состояние хранится в MySQL
Строки очереди, состояние рабочих процессов, журналы, сигналы и переданные потоком фрагменты хранятся в MySQL, поэтому после перезапуска исполнителя состояние оркестрации не теряется. На границе каждого шага обновление состояния, завершение задачи и постановка следующей задачи в очередь фиксируются одной транзакцией.
Вне запроса страницы
WP-Cron запускается только при посещении страницы, а 60-секундный вызов LLM завершается из-за 30-секундного тайм-аута PHP. Исполнители Queuety работают в длительно работающем процессе WP-CLI и принимают задачи без ожидания трафика.
Ограничения для запусков агента
for_each() с режимом кворума, этапами подтверждения и ограничениями, такими как max_transitions() и max_state_bytes(), удерживает длительные запуски агента в заданных пределах.
Можно использовать вне WordPress
Ядро с базой данных работает в любом процессе PHP, который может подключиться к той же базе данных, поэтому другое приложение может отправлять задачи, сигналы и запрашивать состояние рабочих процессов. Для триггеров действий, моста WP-Cron и команд WP-CLI всё ещё нужен WordPress.
Сравнение с
Как Queuety соотносится с планировщиками и механизмами рабочих процессов, уже знакомыми разработчикам WordPress.
| Инструмент | Подходит для | Отличия от Queuety |
|---|---|---|
| WP-Cron | Подходит дляВстроен в WordPress, не требует доступа к системному планировщику на общем хостинге, а задача, пропущенная по времени, запускается при следующей загрузке страницы, а не теряется. | Отличия от QueuetyИсполнители Queuety работают независимо от трафика сайта и требуют длительно работающего процесса wp queuety work. Мост WP-Cron преобразует повторяющиеся события в расписания, но пока не запускает их хуки, поэтому за ними продолжает следить WP-Cron. |
| Action Scheduler | Подходит дляСоздан для распространения в составе плагинов и тем без доступа к серверу; ежемесячно обрабатывает миллионы платежей для Subscriptions и вебхуков для WooCommerce, а все действия записывает в интерфейс администратора. | Отличия от QueuetyAction Scheduler запускает хук позднее, например с отложенным do_action(). Queuety добавляет многоэтапные рабочие процессы с состоянием, сохраняющимся между шагами, ожиданием сигналов и подтверждений, а также конечные автоматы. Их можно просматривать с помощью команд WP-CLI, например wp queuety workflow timeline. |
| Temporal | Подходит дляПлатформа надёжного выполнения: журнал событий фиксирует каждый шаг рабочего процесса, поэтому после сбоя или перебоя запуск продолжается с последнего записанного события; также предлагается Temporal Cloud как альтернатива самостоятельному размещению службы. | Отличия от QueuetyСлужба Temporal — это сервер на Go и база данных, работающие рядом с вашим приложением. Queuety хранит состояние в таблицах MySQL через подключение к базе данных WordPress и запускает исполнителей с помощью WP-CLI. |
Вопросы и ответы
Краткие ответы из документации Queuety.
Для простых задач в очереди по умолчанию — нет. Плагин каждую минуту запускает одноразовый исполнитель через WordPress cron, если срабатывает WordPress cron; за один запуск он обрабатывает одну задачу. Для повторяющихся расписаний, собственных очередей и меньшей задержки нужен постоянно работающий процесс wp queuety work.
Нет. Нужен либо mysqli, либо pdo_mysql; по умолчанию в WordPress используется mysqli. Чтобы принудительно выбрать драйвер, задайте QUEUETY_DB_DRIVER значение auto, mysqli или pdo.
Задачи получают с помощью SELECT ... FOR UPDATE SKIP LOCKED; эта функция поддерживается в MySQL начиная с версии 8.0, а в MariaDB — с 10.6. В CI проекта используется MySQL 8.0.
Да. Ядро с базой данных — задачи, исполнители, рабочие процессы, сигналы, конечные автоматы, артефакты, журналы, метрики и расписания — работает через прямое подключение Connection. Для пулов исполнителей также нужны константы DB_HOST, DB_NAME, DB_USER и DB_PASSWORD. Queuety::on_action(), replace_wp_cron(), загрузка плагина и команды wp queuety по-прежнему требуют WordPress.
Пока нет. Queuety::replace_wp_cron() преобразует повторяющиеся события wp_schedule_event() в расписания Queuety, но их хуки пока не запускаются, поэтому продолжайте использовать WP-Cron для событий, которые должны срабатывать. События от wp_schedule_single_event() остаются в WP-Cron.
wp queuety work --workers=N создаёт пул фиксированного размера и перезапускает аварийно завершившиеся дочерние процессы; для этого нужны расширения pcntl и posix. --min-workers и --max-workers запускают адаптивный пул, который растёт при увеличении очереди задач и сокращается, когда она затихает.
Установите плагин, запустите исполнителя и следуйте руководствам — от первой задачи до рабочих процессов с подтверждением и конечными автоматами.