Обработчик очереди
Берите задачи из очереди и выполняйте каждую в отдельном фоновом процессе, передавая данные для каждой задачи как аргументы. Впервые с thread? Начните с Быстрого старта.
Опишите задачу
Держите задачу маленькой и сериализуемой — простые данные в конструкторе, ресурсы
открываются внутри run() (см. границу сериализации).
<?php
use Flytachi\Winter\Thread\Runnable;
class SendInvoice implements Runnable
{
public function __construct(private int $orderId) {}
public function run(array $args): void
{
$attempt = (int) ($args['attempt'] ?? 1);
$urgent = isset($args['urgent']);
$mailer = new Mailer(); // открывайте ресурсы здесь, а не в конструкторе
$mailer->sendInvoice($this->orderId, urgent: $urgent);
}
}Передавайте аргументы запуска
start() принимает ассоциативный массив. Значения приходят в run() через $args:
'key' => 'value'→$args['key'] === 'value'(всегда строка)'flag' => true→$args['flag'] === true(флаг без значения; проверяйте черезisset())'skip' => falseили'skip' => null→ исключается из$args
$thread = new Thread(new SendInvoice($orderId), 'Billing', 'SendInvoice', "order-{$orderId}");
$thread->start([
'attempt' => '2',
'urgent' => true, // флаг без значения
'skip' => false, // отбрасывается
]);Аргументы — строки
Каждое значение передаётся через командную строку, поэтому числа приходят строками —
приводите их в run() ((int) $args['attempt']). Принимаются только скаляры и булевы
значения; см. справочник по Runnable.
Разбирайте очередь
Один процесс на задачу. Для fire-and-forget — запустили и пошли дальше: вывод по умолчанию
идёт в /dev/null, так что pipe вычитывать не нужно:
<?php
require 'vendor/autoload.php';
use Flytachi\Winter\Thread\Thread;
// $queue->pull() возвращает id следующего заказа или null, когда очередь пуста
while (($orderId = $queue->pull()) !== null) {
$thread = new Thread(new SendInvoice($orderId), 'Billing', 'SendInvoice', "order-{$orderId}");
$thread->start(['attempt' => '1']);
// без join() — fire and forget; родитель продолжает разбирать очередь
}Не плодите процессы без ограничения
Один процесс ОС на задачу — нормально при небольших объёмах, но неограниченный цикл может наплодить тысячи процессов. Чтобы ограничить число одновременно работающих, используйте небольшой пул — см. Параллельные задачи.
Связанное
- Параллельные задачи — ограничение параллелизма, сбор результатов
- Корректное завершение — таймауты и остановка работы
- Логирование и отладка — как сохранить вывод задачи
- Справочник API —
start()и правила аргументов