Queue (Redis)¶
Note
Not part of core. Install it separately:
composer require kinetis/queue-redis
Adds Redis as a backend for Queue. Application code that already
pushes and pops jobs through QueueInterface needs no changes at all to
switch — only your configuration changes.
QUEUE_CONNECTION=redis
REDIS_HOST=127.0.0.1
vendor/bin/kinetis queue:work --queue=high,default
Configuring¶
This package introduces no configuration keys of its own — every
REDIS_* setting RedisSimpleCache (Persistence) already reads
is the exact one this backend reads too, scoped by
QUEUE_CONNECTION_NAME the same way as everywhere else in Kinetis.
A crashed worker’s job is never lost¶
A naive Redis list pop() removes the item at pop time — if a worker
crashed mid-job, it would just be gone, with no way to detect or retry
it. This backend uses the “reliable queue” pattern instead: pop()
atomically moves a job’s payload from a queue’s pending list to a
separate processing list, rather than deleting it outright. ack()
removes it from processing; release() moves it back onto pending.
A job whose worker crashes before any of ack()/release()/fail()
runs is stranded, not lost — it stays exactly where a future reaper
would find it, though this backend doesn’t ship one yet: closing that
gap is a disclosed, still-open limitation.
The two transitions that could otherwise lose a job outright —
release() (processing → pending) and delayed-job promotion
(delayed → pending) — each run as a single Lua script, which Redis
always executes as one indivisible unit. A process crash can never land
between the two halves of either move. release()’s move is also
conditional, not just indivisible: calling it a second time with the
same QueuedJob — a duplicate call, or a retry after a connection
failure whose server-side outcome wasn’t known — throws
Kinetis\Queue\Exception\StaleJobHandleException instead of enqueueing
a second replacement; QueueWorker already treats this as a benign
“already released through another path” outcome rather than letting it
crash the worker.
Delayed-job promotion also bounds how much it moves in one call
(RedisQueue::DELAYED_PROMOTION_BATCH_SIZE, currently 100) — a large
ready backlog is promoted in batches across successive polls rather than
inside one Lua script, since Redis executes one command at a time and an
unbounded promotion would stall every other client sharing that Redis
for its full duration.
Delayed jobs¶
$this->queue->push(new SendReminderEmail($userId), delaySeconds: 3600);
Checked on this backend’s own polling cycle rather than firing at the exact moment the delay ends, so a delayed job can run slightly later than its exact target time — typically by a few seconds, not less.
Retries and giving up¶
Everything Queue documents about maxAttempts, QUEUE_MAX_ATTEMPTS,
and the log entry written when a job is finally given up on works
identically here — nothing about retry behavior changes by switching to
this backend.
Named connections¶
QUEUE_CONNECTION_NAME=reports
REDIS_REPORTS_HOST=127.0.0.1
Same convention as everywhere else in Kinetis (see Configuration):
QUEUE_CONNECTION_NAME picks which named block of REDIS_* settings a
worker reads, and 'default' (or simply not setting it) reads the plain
keys shown earlier in this page.
If the package isn’t installed¶
Setting QUEUE_CONNECTION=redis without having run
composer require kinetis/queue-redis produces a clear error telling you
which package to install, rather than a confusing crash.
See also¶
Queue — writing jobs, pushing and popping, and everything about retries that applies to every backend equally.
Persistence — the
REDIS_*configuration convention this backend reuses.Configuration — the named-connection convention used above.