trail / queue
A light queue addon for trail
dev-main / 0.1.x-dev
2026-10-01 03:13 UTC
Requires
- php: >=8.4
- trail/db: ^0.1
- trail/framework: ^0.1
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-01 03:13:11 UTC
README
A light queue addon for trail
install
composer require trail/queue
trail/trail db::migrate
Needs trail/db
a job
Constructor args get stored as json. handle() gets services like pages do
use Trail\Queue\Jobs\Job;
final readonly class SendWelcome implements Job
{
public function __construct(public int $userId) {}
public function handle(Users $users, Outbox $outbox): void
{
...
}
}
- args are plain json. strings, numbers, bools, null, arrays
- objects throw
LogicExceptionwhen pushed
push one
use Trail\Queue\Backlog\Backlog;
public function __construct(private Backlog $backlog) {}
$this->backlog->push(new SendWelcome($user->id));
$this->backlog->push(new SendWelcome($user->id), delay: 3600); // seconds
run a worker
trail/trail queue::work # loops. stops after an hour
trail/trail queue::work --for=600 # stops after 10 minutes
trail/trail queue::work --until-empty # runs everything and stops
A queue runner is a good idea for background tasks. 2 good ways to do that:
- process manager (systemd, supervisor, whatever) running
queue::workthat retarts when it exits - cron every minute running
queue::work --until-empty
Cheeky supervisor example
[program:imma-queue]
command=/usr/bin/php /var/www/example.com/trail/trail queue::work
user=www-data
autostart=true
autorestart=true
stopwaitsecs=60
redirect_stderr=true
stdout_logfile=/var/log/imma-queue.log
autorestartrestarts it after hourly exitsstopwaitsecsis how long it'll wait for a job to finish before stopping. Otherwise its killed and picked up again aftertimeout- restart after a deployment (
supervisorctl restart imma-queue) to get new code
named queues
jobs are default unless someone gives it a real name
final readonly class BuildExport implements Job
{
public const string QUEUE = 'slow';
...
}
trail/trail queue::work # every job starting with oldest
trail/trail queue::work --queue=mail,default # mail then default
trail/trail queue::work --queue=slow # worker just for slow stuff
trail/mailjobs go onmail- no
--queuearg runs everything
when jobs fail
- thrown job gets retried after
backoff × attemptseconds (60, 120, ...) - after
triesit gets marked as failed with error + log - stuck jobs because worker died get picked up again after
timeout - jobs that keep killing the worker are marked failed
- jobs can run more than once
trail/trail queue::failed # list them
trail/trail queue::retry 12 # try it again
trail/trail queue::retry all
trail/trail queue::prune # delete failed ones
jobs can set their own values. otherwise config tells it what to do
final readonly class PingWebhook implements Job
{
public const int TRIES = 10;
public const int BACKOFF = 600; // 10m, 20m, 30m, ...
}
final readonly class ChargeCard implements Job
{
// never twice
public const int TRIES = 1;
}
schedule
cli commands / jobs running on a timer. worker checks once a minute
'queue' => [
'schedule' => [
'sessions::prune' => 'daily',
'auth::prune' => 'daily',
'queue::prune' => 'weekly',
SendDigest::class => '0 8 * * 1', // mondays 8am
],
],
hourly,daily,weekly,monthly, or cron (*,1-5,0,30,*/15)- server timezone
- commands get queued and run by worker
- job classes cant take args
- runs once per slot
- missed runs over last hour play catch up
no worker?!
You can set it to just run right away during a request
'queue' => [
'runNow' => true,
],
all the config stuff
'queue' => [
'runNow' => false,
// before fail
'tries' => 3,
// seconds. times the attempt
'backoff' => 60,
// seconds before stuck job is taken
'timeout' => 900,
// seconds queue::prune keeps failed jobs
'keepFailed' => 604800,
// `what => when`
'schedule' => [],
],
do your own
Bind anything that implements Backlog in a site addon
$box->bind(Backlog::class, MyBacklog::class);