glit/resque
glit/resque brings Resque's Redis-backed background job processing to Laravel. It provides a Laravel-friendly queue integration for dispatching jobs, running workers, and managing failed jobs with familiar Artisan commands and configuration. Ideal for apps needing reliable asynchronous task handling...
This is a fork of chrisboulton/php-resque wrapped for Laravel. Before you composer require it, know what you're buying: its differentiator is a pluggable job factory so job classes can be resolved from Laravel's container instead of new'd statically. Everything else is vanilla Resque — Redis lists full of JSON envelopes, forked worker processes calling perform().
Minimal setup:
composer require glit/resque
php artisan vendor:publish --provider="Glit\Resque\ResqueServiceProvider"
You should pin the version explicitly ("glit/resque": "dev-master#<commit>" or via a private VCS mirror) — the package has no dependents and no upstream support, so floating constraints are unsafe.
Configure config/resque.php with your Redis connection details (host, port, database index, password if any). Verify the file actually exposes those keys; the wrapper is thin and may only accept a subset.
Look first at:
chrisboulton/php-resque. Find the interface (likely JobFactoryInterface with instantiate($className, $args)), and decide whether it's wired by default or you need to bind your own implementation.resque:work is the usual convention) and its flags (--queue, --interval, --max-jobs). These are what you'll run under supervisor.perform() contract — how args are passed, whether setUp()/tearDown() hooks exist, and whether an onFailure() hook is available for building your own retry logic.First use case that justifies the package: a Symfony2/3-era or Silex app that already runs php-resque workers, has a Redis instance dedicated to queues, and wants container-injected jobs. If you're greenfield in Laravel, stop now — the framework's native Redis queue already does container resolution, retries with backoff, failed-job storage, and Horizon observability, and this package does none of those.
Job class shape. A Resque job is a class with a perform() method. Args arrive as an array (they were JSON-encoded at push time). Keep them primitive: strings, ints, arrays of primitives. No closures, no models, no binary blobs — JSON is the wire format.
class SendWelcomeEmail
{
public function perform()
{
$userId = (int) $this->args['user_id'];
Mail::to(User::findOrFail($userId)->email)->send(new WelcomeMail);
}
}
Container resolution — the whole point. Bind your own job factory that pulls the class out of app()->make():
class ContainerJobFactory implements JobFactoryInterface
{
public function instantiate($className, array $args)
{
return app()->make($className, ['args' => $args]);
}
}
Register it in a service provider. From there, jobs can take constructor dependencies (repositories, mailers, HTTP clients) instead of reaching for facades or globals. This is the pattern worth stealing even if you later migrate.
Dispatching from a controller. Most implementations expose a facade or static Resque::push():
Resque::push('emails', SendWelcomeEmail::class, ['user_id' => $user->id]);
Wrap this in a small application-level dispatcher (App\Queue\Dispatch) so job classes never import the package namespace directly. That seam is what makes the eventual migration to Illuminate\Queue mechanical rather than a rewrite.
Named queues as priorities. Resque workers take a comma-separated queue list and pop from the first non-empty one:
php artisan resque:work --queue=critical,default,low --max-jobs=1000
Treat this as your priority mechanism. There is no in-queue priority and no delayed/scheduled queue — if you need "run in 5 minutes", push to a delay queue and poll, or (better) accept that this package isn't the right tool.
Process management. Run workers under supervisor or systemd. Set --max-jobs (or whatever the equivalent recycling flag is called) to ~500–1000 so PHP memory leaks self-heal. Each worker forks a child per job, so --count isn't a thing; run multiple processes.
Testing. Do not test through Redis. Instantiate the job class directly, set $job->args (or pass via constructor), and assert on perform(). If you've gone through the container job factory, this is trivial — the constructor injection you designed for production is the same injection you use in tests.
Failure handling is your responsibility. Resque records failed jobs in a resque:failed list with a stack trace, and that's it. Build:
perform() (or a base Job class that catches exceptions and re-pushes with a delay queue).resque:failed and re-pushes entries.The recommendation is not to adopt this. Every source in your pack — package assessment, PM review, TPM review — lands on the same conclusion: zero stars, zero dependents, zero maintenance, PHP 5/7-era lineage. For a Laravel shop this is a strict downgrade relative to Illuminate\Queue + Redis driver + Horizon. Read it for the container-resolved-job pattern and then implement that pattern with the framework. If a legacy php-resque service already exists, treat this fork as a bridged fork pinned by commit behind a private mirror, and open a retirement ticket the same day.
Forking is non-optional. pcntl and posix extensions must be compiled into your PHP. That rules out Windows entirely and often rules out hardened FPM containers. Verify in staging before writing job code.
Wire format compatibility. The Redis envelope is {"class": "...", "args": [...]} keyed at resque:queue:<name>. If a Ruby resque-web dashboard or a Ruby worker fleet is reading the same keyspace, this is a feature. If you're the only consumer, this is a constraint — Ruby Resque treats class name as a string, not a namespaced FQCN, so you'll need a class-name mapping layer or fully-qualified names will confuse the dashboard.
At-least-once is not exactly-once. A worker that pops a job and dies before recording it as in-progress silently loses it. A worker that crashes mid-perform() strands the job in the in-progress registry with no automatic requeue. Every job must be idempotent — use a unique-key store (Redis SET NX, DB unique constraint) at the top of perform() and short-circuit duplicates.
Durability is Redis's problem, not the package's. RDB snapshots lose minutes of queued work on crash; AOF with everysec loses up to a second. If your ops team hasn't tuned persistence, a Redis restart will drop queued revenue-path work with no signal.
Missing primitives you'll build yourself: retries with backoff, delayed/scheduled jobs, job uniqueness, rate limiting, dead-letter handling, batching/chaining, timeout enforcement, and worker autoscaling. Each is a small thing; together they're the reason Laravel's queue exists.
Debugging:
redis-cli LLEN resque:queue:defaultredis-cli LINDEX resque:queue:default 0 | jqredis-cli HGETALL resque:workersredis-cli LRANGE resque:failed 0 -1resque-web (the Ruby dashboard) works against your Redis, use it — this fork doesn't ship a UI.PHP version compatibility is unverified. The composer.json constraints likely predate 8.0. Expect deprecation noise around dynamic properties and ${var} interpolation, and latent breakage on 8.1+. Add a CI job that boots a worker and drains a single job so PHP bumps fail loudly, not in production.
Extension points worth knowing: the job factory (bind a container-resolved one), the worker's failure callback (if exposed — use it to log and route to your own dead-letter scheme), and the artisan command (extend it to add graceful shutdown signals). Everything else you need, you build in your application layer.
Exit target: Laravel queues + Horizon if you're on Laravel, Symfony Messenger with the Redis or AMQP transport if you're on Symfony. Both preserve container-resolved handlers — the only feature this fork adds — so migration is handler-by-handler with the dispatcher wrapper you wrote in "Implementation Patterns" doing the fan-out during the transition.
How can I help you explore Laravel packages today?