kinetis / queue-redis
A Redis-backed queue implementation for kinetis/queue's QueueInterface — finite leases over pending/leased/delayed keys, so a crashed worker's job is redelivered rather than stranded.
Requires
- php: ^8.4
- amphp/redis: ^2.0.4
- amphp/socket: ^2.4.0
- kinetis/framework: ^1.5.0
- kinetis/queue: ^1.3.0
- kinetis/redis: ^1.0.0
Requires (Dev)
- infection/infection: ^0.35.0
- phpstan/phpstan: ^2.2.8
- phpunit/phpunit: ^12.5.33
- vimeo/psalm: ^6.16.1
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
kinetis/queue-redis
A Redis-backed queue implementation for kinetis/queue's QueueInterface
Part of Kinetis, a non-blocking PHP framework for API-first applications, developed in the kinetis-dev/kinetis monorepo.
Adds Redis as a queue backend. push()/pop()/ack()/release()/fail()
work exactly like any other backend — only your configuration changes. A
reservation is a finite lease: pop() moves a job from the queue's
pending list into a leased sorted set scored with an expiry, and any
worker's next pop() returns a lease past its expiry to pending with
attempts incremented. A job whose worker died mid-execution is
redelivered rather than stranded.
use Kinetis\Config\Config; use Kinetis\QueueRedis\RedisQueueFactory; $queue = RedisQueueFactory::fromConfig($config); $queue->push(new SendWelcomeEmail($email, $name), queue: 'default');
RedisQueue declares Kinetis\Queue\ClearableQueueInterface.
Clearing counts and removes the queue's pending and delayed entries in
one Lua script, so the number it reports is what it removed; live leases
are untouched, since they are work a running worker still owns.
size() counts pending, delayed and expired leases, not live ones.
The leased member is the exact envelope string handed back as the job's
handle, and reclaiming rewrites it with the incremented attempt count.
That makes the handle a fence: ack(), release() and fail() act only
on that exact member, so a settlement for a delivery that has been
reclaimed or already settled raises
Kinetis\Queue\Exception\StaleJobHandleException and writes nothing.
Recovery is not renewal. A job still running when its lease expires can
execute alongside its replacement, so set
QUEUE_VISIBILITY_TIMEOUT_SECONDS above normal job duration and keep
handlers idempotent. maxAttempts bounds handlers that throw; it cannot
bound a succession of processes that each die mid-execution.
There is no reaper process. Every pop() promotes due delayed jobs and
reclaims expired leases for each queue it is given, in priority order,
before it waits.
Configuration
QUEUE_CONNECTION=redis
REDIS_HOST=127.0.0.1
QUEUE_VISIBILITY_TIMEOUT_SECONDS=300
QUEUE_VISIBILITY_TIMEOUT_SECONDS is how long a reservation is leased
before any worker may reclaim it. It defaults to 300 and must be a
positive integer. Every other key this backend reads — REDIS_HOST/
REDIS_URL/REDIS_TLS/... — is the exact one kinetis/cache-redis's
RedisSimpleCache already reads, scoped by QUEUE_CONNECTION_NAME the
same way every other backend is. REDIS_CLUSTER is not among them: this
backend is single-node, and it opens its own connection over
kinetis/redis rather than
sharing the cache's, so its connection lifetime is its own. kinetis/queue's own keys
(QUEUE_CONNECTION, QUEUE_MAX_ATTEMPTS, ...) are documented in that
package; full reference:
kinetis.dev/docs/config.html.
Installation
composer require kinetis/queue-redis
Requires PHP 8.4+, kinetis/framework, kinetis/queue, and
kinetis/redis. Full documentation:
kinetis.dev/docs/queue-redis.html.
License
MIT — see LICENSE.