zolex/job-queue-bundle
zolex/job-queue-bundle provides a Symfony-based job queue for processing background tasks asynchronously. It supports persistent jobs, worker processes, scheduling, and retries, helping offload time-consuming work so web requests stay fast and applications remain responsive.
Know what you're installing first. zolex/job-queue-bundle is a Symfony bundle wrapping the JMS Job Queue, not a Laravel package. There is no service provider, no artisan command, no config/queue.php driver. If you're a full-time Laravel dev, this is only relevant when you're dropped into a Symfony 5 / PHP 8 codebase (or maintaining a legacy one). The Laravel equivalent mental model is the database queue driver — jobs are rows, a worker polls them, and you get a dashboard.
Install with composer require zolex/job-queue-bundle, then register it in config/bundles.php (new JMS\JobQueueBundle\JMSJobQueueBundle()). Run Doctrine migrations — you'll get tables like jms_job_queue_job, jms_job_queue_job_log, and job-stat tables. Treat these as your jobs/failed_jobs tables.
First job: the bundle's canonical pattern is "the job is a Symfony console command." Create a command (e.g. app:send-newsletter), then enqueue it:
$job = new Job('app:send-newsletter', ['--user=42']);
$em->persist($job);
$em->flush();
Start the worker: bin/console jms-job-queue:run is the direct analogue of php artisan queue:work. Point Supervisor at it in production, exactly like you'd do for a Laravel worker.
First real use case: take an existing slow admin-triggered command (report generation, import) and push it through the queue instead of running it synchronously in a controller.
ShouldQueue job classes, you don't write a dedicated job class — you write a console command and queue it by name + args. All the standard Symfony command niceties (input validation, DI) apply, but job payloads are just CLI argument strings. If you need structured data, serialize it into an argument or add a column to the Job entity.dispatchAfterResponse/afterCommit gives you — enqueue and business write succeed or fail together.Job::createRecurringJob('app:report', '0 2 * * *') for nightly reports/syncs. The scheduler picks it up. This is your $schedule->command(...) equivalent, but stored in the DB rather than in Kernel::schedule.$job->addDependency($priorJob) prevents a job from running until dependencies reach STATE_FINISHED. Use it for multi-stage imports (download → transform → notify) instead of chaining Laravel-style ->then() callbacks.Job entities and flush() once — much cheaper than N flushes on a relational queue.jms-job-queue:run processes (one per queue name or sharded by CPU) under Supervisor. Use the worker's runtime flag so processes recycle — mirror Laravel's --timeout/--memory.horizon/failed_jobs view. Supplement with JobLog rows for command output.JobProcessed events.QUEUE_CONNECTION, queue:listen, or ShouldQueue. If you're greenfield on Laravel, use the native database/redis driver and skip this entirely. Only reach for this bundle if you're already on Symfony 5.zolex fork = do a compatibility sweep first. The package description advertises PHP 8 / Symfony 5 / Doctrine Common 3 — verify your stack matches before adopting. This is a community-maintained fork of the old schmittjoh/JMSJobQueueBundle; API drift and stale docs are real risks. Check the open issues and last commit date.$tries/backoff() have no direct equivalent — a failing command marks the job STATE_FAILED, and re-queueing is on you. Wrap Job creation in a small helper that records attempts and implements your own retry policy.jms_job_queue_job. Keep transactions short and never hold a transaction while a job executes. Watch for lock waits under load.STATE_NEW → STATE_RUNNING → STATE_FINISHED/STATE_FAILED. When a job is "stuck," inspect the row and its JobLog children directly, and check whether the worker crashed without releasing STATE_RUNNING.Job entity if you need extra metadata (there's no free-form payload JSON column out of the box), override the worker command, and lean on Doctrine listeners for cross-cutting concerns. Prefer extending the entity over forking the bundle — the fork is small and you don't want to maintain a vendor patch.How can I help you explore Laravel packages today?