Рабочие процессы в одном файле
Рабочий процесс может быть полностью автономным и находиться в одном файле PHP. Определите классы шагов и конструктор вместе, поместите файл в каталог и загрузите этот каталог с помощью Queuety::load_workflows() (см. ниже). Queuety самостоятельно не сканирует каталоги.
// workflows/onboard-user.php
use Queuety\Queuety;
class CreateAccount implements \Queuety\Step {
public function handle(array $state): array {
$user = create_user($state['email']);
return ['user_id' => $user->id, 'user_name' => $user->name];
}
public function config(): array {
return ['max_attempts' => 3];
}
}
class SendWelcome implements \Queuety\Step {
public function handle(array $state): array {
wp_mail($state['email'], 'Welcome ' . $state['user_name'], '...');
return ['welcomed' => true];
}
public function config(): array {
return [];
}
}
return Queuety::define_workflow('onboard_user')
->then(CreateAccount::class, 'create_account')
->then(SendWelcome::class, 'send_welcome');
Файл возвращает WorkflowBuilder. Каждый класс шага определяется прямо в файле. После загрузки файла классы становятся доступными, а рабочий процесс регистрируется как шаблон.
Загрузка рабочих процессов
Загрузите все файлы рабочих процессов из каталога:
// Load all .php files from the workflows directory
$count = Queuety::load_workflows(__DIR__ . '/workflows/');
Или загрузите один файл:
$template = Queuety::load_workflow_file(__DIR__ . '/workflows/onboard-user.php');
Затем выполните диспетчеризацию по имени:
$workflow_id = Queuety::run_workflow('onboard_user', ['email' => 'user@example.com']);
Рекурсивная загрузка
Передайте true вторым аргументом, чтобы сканировать подкаталоги:
Queuety::load_workflows(__DIR__ . '/workflows/', recursive: true);
Так рабочие процессы можно упорядочить по папкам:
workflows/
├── onboarding/
│ ├── new-user.php
│ └── trial-upgrade.php
├── reports/
│ ├── daily-summary.php
│ └── weekly-digest.php
└── notifications/
└── digest-email.php
Использование всех возможностей рабочих процессов
Рабочие процессы в файлах поддерживают все возможности конструктора, кроме idempotency_key(), который не сохраняется в шаблоне; передавайте его отдельно при диспетчеризации с помощью Queuety::run_workflow( $name, $payload, [ 'idempotency_key' => '...' ] ). Задержки, сигналы, параллельные шаги, условные ветвления, запуск рабочих процессов, обработчики отмены и очистка состояния поддерживаются:
// workflows/approval-flow.php
use Queuety\Queuety;
class SubmitRequest implements \Queuety\Step {
public function handle(array $state): array {
return ['submitted_at' => date('Y-m-d H:i:s')];
}
public function config(): array { return []; }
}
class ProcessApproval implements \Queuety\Step {
public function handle(array $state): array {
return [
'approved_by' => $state['approved_by'],
'processed' => true,
];
}
public function config(): array { return []; }
}
class CleanupRequest implements \Queuety\Handler {
public function handle(array $payload): void {
delete_pending_request($payload['request_id']);
}
public function config(): array { return []; }
}
return Queuety::define_workflow('approval_flow')
->then(SubmitRequest::class)
->delay(hours: 24)
->wait_for_signal('approved')
->then(ProcessApproval::class)
->on_cancel(CleanupRequest::class)
->prune_state_after(2);
Когда использовать рабочие процессы в файлах
Рабочие процессы в файлах подходят, когда:
- LLM или генератор кода программно создает рабочие процессы
- Рабочий процесс достаточно прост, чтобы поместиться в один файл
- Вы хотите держать логику шагов рядом с определением рабочего процесса
- Вы создаете прототип и хотите быстро вносить изменения
Для более крупных рабочих процессов с общими классами шагов, сложным промежуточным ПО или шагами, повторно используемыми в нескольких рабочих процессах, удобнее поддерживать стандартный подход с отдельными файлами классов и автозагрузкой PSR-4.
Как это работает
Внутри рабочие процессы в файлах используют тот же движок, что и конструктор API. Каждый шаг — отдельное задание в базе данных. Состояние передается через таблицу queuety_workflows. Повторного воспроизведения нет, требования детерминированности отсутствуют, разницы в производительности тоже нет.
Каждый вызов загрузки require файл (а не require_once), поэтому загружайте каждый файл один раз за запрос; повторная загрузка приводит к повторному объявлению классов и ошибке. Возвращенный WorkflowBuilder преобразуется в WorkflowTemplate и сохраняется в WorkflowRegistry. Диспетчеризация и выполнение ничем не отличаются от других рабочих процессов.