Skip to main content

Defining a payload job

A payload job is a class that implements Zeridion\Flare\Worker\Job and is decorated with the #[FlareJob] attribute. The worker calls its handle method with the decoded payload and a JobContext.

<?php

use Zeridion\Flare\Worker\FlareJob;
use Zeridion\Flare\Worker\Job;
use Zeridion\Flare\Worker\JobContext;

#[FlareJob(queue: 'email', maxAttempts: 5, timeoutSeconds: 60)]
final class SendWelcomeEmail implements Job
{
public function handle(mixed $payload, JobContext $ctx): void
{
// at-least-once → make this idempotent
if ($this->alreadySent($ctx->jobId)) {
return;
}

$this->mailer->send($payload['email']);
$ctx->reportProgress(1.0);
}
}

Register it with the worker:

$worker->register(SendWelcomeEmail::class);

The handle method

The method name is fixed to handle. Its signature is always:

public function handle(mixed $payload, JobContext $ctx): void;
  • Returning normally acknowledges the job as succeeded.
  • Throwing any exception acknowledges the job as failed. The server then decides whether to retry (based on the attempt count) or dead-letter the job — the worker never makes that decision itself.

The payload

By default $payload is the decoded JSON straight off the wire — an associative array for an object payload, a scalar, or null.

To receive a typed value object instead, set payloadClass on the attribute:

final class NewUserEvent
{
public string $userId = '';
public string $email = '';
}

#[FlareJob(name: 'SendWelcomeEmail', payloadClass: NewUserEvent::class)]
final class SendWelcomeEmail implements Job
{
public function handle(mixed $payload, JobContext $ctx): void
{
// $payload is a NewUserEvent
$this->mailer->send($payload->email);
}
}

The worker hydrates the class from the decoded array. If the class declares a static fromArray(array): static factory it is used; otherwise public properties are populated by name.

Idempotency

Jobs run at-least-once — if an acknowledgement is lost after the work completes, the same job is delivered again. Guard externally-visible side effects on $ctx->jobId so a redelivery is harmless:

public function handle(mixed $payload, JobContext $ctx): void
{
if ($this->ledger->hasProcessed($ctx->jobId)) {
return;
}
$this->charge($payload['amount']);
$this->ledger->markProcessed($ctx->jobId);
}

Dependencies

The worker constructs your job with a zero-argument new. To inject collaborators, supply a factory when you register the job:

$worker->register(
SendWelcomeEmail::class,
fn () => new SendWelcomeEmail($mailer, $ledger),
);

The factory runs once per job execution.

See also