Installation
Add the bundle to your composer.json:
composer require ddereszewski/job-queue-bundle
Register the bundle in config/bundles.php:
return [
// ...
Ddereszewski\JobQueueBundle\DdereszewskiJobQueueBundle::class => ['all' => true],
];
Enable the Worker
Run the worker process in a terminal (preferably in a screen/tmux session or as a systemd service):
php bin/console jms:job:worker
Note: Requires a running Symfony application (e.g., php bin/console server:run in another terminal).
First Job Tag a console command to be queueable:
// src/Command/MyCommand.php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use JMS\JobQueueBundle\Annotation as JMS;
class MyCommand extends Command {
protected static $defaultName = 'app:my-command';
#[JMS\Job]
public function execute(InputInterface $input, OutputInterface $output) {
$output->writeln('Running in background!');
return Command::SUCCESS;
}
}
Dispatch a Job
Enqueue the command via the jms:job:dispatch command:
php bin/console jms:job:dispatch app:my-command
config/packages/jms_job_queue.yaml – Default configuration (adjust queues, retries, etc.).src/Command/ – Scan for existing commands tagged with @JMS\Job to understand usage patterns.Use the @JMS\Job annotation on any console command method to enable queuing:
#[JMS\Job(
queue: 'high_priority', // Optional: Custom queue name
delay: 3600, // Optional: Delay in seconds
priority: 10 // Optional: Priority (higher = sooner)
)]
public function execute(InputInterface $input, OutputInterface $output) {
// ...
}
Inject the JobDispatcherInterface service to enqueue jobs from controllers/services:
use JMS\JobQueueBundle\Job\JobDispatcherInterface;
class MyService {
public function __construct(private JobDispatcherInterface $dispatcher) {}
public function triggerJob() {
$this->dispatcher->dispatch('app:my-command', [], 'high_priority');
}
}
Use @JMS\JobResult to capture output/return values:
#[JMS\JobResult]
public function execute(InputInterface $input, OutputInterface $output) {
return ['status' => 'success', 'data' => $this->processData()];
}
Retrieve results via:
php bin/console jms:job:result <job-id>
Pass arguments when dispatching:
php bin/console jms:job:dispatch app:my-command -- --param="value"
Access in the command:
$param = $input->getArgument('param');
config/app.php under extra.bundles.app: (e.g., app:my-command) to avoid conflicts..env:
JMS_JOB_QUEUE_CONNECTION=doctrine
JMS_JOB_QUEUE_DSN=mysql://user:pass@localhost/db
php bin/console jms:job:worker --queue=high_priority &
php bin/console jms:job:worker --queue=low_priority &
--limit=N to process N jobs per run (useful for long-running tasks).php bin/console jms:job:list
php bin/console jms:job:show <job-id>
var/log/jms_job_queue.log.Worker Must Be Running
php bin/console jms:job:worker --verbose
Annotation Parsing Issues
jms/serializer-bundle is installed (required for annotation parsing).composer require jms/serializer-bundle if missing.Queue Locking
--timeout=300 to limit runtime.Symfony 6+ Compatibility
symfony/console and symfony/dependency-injection are compatible.Doctrine DBAL Dependency
JMS_JOB_QUEUE_DSN:
JMS_JOB_QUEUE_DSN=pgsql://user:pass@localhost/db
var/log/jms_job_queue.log for errors.DELETE FROM jms_job_queue_job WHERE id = <job-id>;
config/console or use the full namespace (e.g., App\Command\MyCommand).Custom Queues
Define multiple queues in config/packages/jms_job_queue.yaml:
jms_job_queue:
queues:
high_priority:
max_jobs: 10
timeout: 60
low_priority:
max_jobs: 50
timeout: 300
Retry Logic
Use @JMS\JobRetry to auto-retry failed jobs:
#[JMS\JobRetry(maxAttempts: 3, delay: 10)]
public function execute(InputInterface $input, OutputInterface $output) {
// ...
}
Event Listeners
Hook into job lifecycle events (e.g., jms_job_queue.job.enqueue):
// src/EventListener/JobListener.php
use JMS\JobQueueBundle\Event\JobEvent;
class JobListener {
public function onJobEnqueue(JobEvent $event) {
// Log or notify when a job is queued
}
}
Register in services.yaml:
services:
App\EventListener\JobListener:
tags:
- { name: kernel.event_listener, event: jms_job_queue.job.enqueue, method: onJobEnqueue }
Testing
Use JobDispatcherInterface in tests to mock job dispatching:
$dispatcher = $this->createMock(JobDispatcherInterface::class);
$dispatcher->expects($this->once())->method('dispatch');
$this->container->set(JobDispatcherInterface::class, $dispatcher);
Performance
--batch-size=N to reduce database overhead.jms_job_queue.transport).How can I help you explore Laravel packages today?