Package · thread

Queue worker

Pull jobs from a queue and run each one in its own background process, passing per-job data as arguments. New to threads? Start with the Quickstart.

Define the job task

Keep the task small and serializable — plain data in the constructor, resources opened inside run() (see the serialization boundary).

src/SendInvoice.php
<?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(); // open resources here, not in the constructor
      $mailer->sendInvoice($this->orderId, urgent: $urgent);
  }
}

Pass per-run arguments

start() takes an associative array. Values arrive in run() via $args:

  • 'key' => 'value'$args['key'] === 'value' (always a string)
  • 'flag' => true$args['flag'] === true (valueless flag; test with isset())
  • 'skip' => false or 'skip' => nullomitted from $args
php
$thread = new Thread(new SendInvoice($orderId), 'Billing', 'SendInvoice', "order-{$orderId}");

$thread->start([
  'attempt' => '2',
  'urgent'  => true,   // valueless flag
  'skip'    => false,  // dropped
]);

Arguments are strings

Every value is passed on the command line, so numbers arrive as strings — cast them in run() ((int) $args['attempt']). Only scalars and booleans are accepted; see the Runnable reference.

Dispatch the queue

One process per job. For fire-and-forget, start and move on — output goes to /dev/null by default, so there’s no pipe to drain:

worker.php
<?php

require 'vendor/autoload.php';

use Flytachi\Winter\Thread\Thread;

// $queue->pull() returns the next order id, or null when empty
while (($orderId = $queue->pull()) !== null) {
  $thread = new Thread(new SendInvoice($orderId), 'Billing', 'SendInvoice', "order-{$orderId}");
  $thread->start(['attempt' => '1']);
  // no join() — fire and forget; the parent keeps pulling
}

Don't spawn without bound

One OS process per job is fine for modest volumes, but an unbounded loop can fork thousands of processes. To cap how many run at once, use a small pool — see Parallel tasks.