Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Job Queue Bundle Laravel Package

markup/job-queue-bundle

A Symfony bundle for background job processing and queues. Dispatch, process, and manage asynchronous tasks with pluggable queue backends, keeping time-consuming work out of the request cycle so your application stays fast and responsive.

View on GitHub
Deep Wiki
Context7

Getting Started

Know what you're adopting first. Despite the composer require-and-go feel, this is a Symfony bundle, not a Laravel package: it registers services in a kernel, ships Symfony Console commands, and depends on videlalvaro/RabbitMqBundle (now php-amqplib/rabbitmq-bundle) for the AMQP connection. Laravel's Artisan is built on Symfony Console, so the commands are conceptually familiar, but you cannot composer require this into a Laravel app and expect php artisan to pick it up. Realistic adoption paths:

  1. Full adoption — a small Symfony app/container dedicated to scheduling, running alongside your Laravel app, dispatching work back via HTTP, a shared queue, or Process::run('php artisan ...').
  2. Pattern adoption — read its scheduler/consumer loop and reproduce it with Laravel's Queue + Schedule (usually the better call for a Laravel shop with 0 dependents on this bundle).
  3. Deployment-helpers only — use its queue/exchange declaration commands in CI, keep scheduling in Laravel.

Minimal setup (path 1):

composer require markup/job-queue-bundle php-amqplib/rabbitmq-bundle
  • Register the bundle in config/bundles.php (or AppKernel).
  • Configure the RabbitMQ connection/exchange from RabbitMqBundle, then the bundle's job list (command + cron expression).
  • Run the scheduler process and the consumer process under Supervisor/systemd.
  • Declare exchanges/queues once per environment before the first deploy.

Where to look first: Resources/config/ for the service definitions (that tells you what's swappable), the scheduler command class (that's where cron → delayed-message logic lives), and the README's config sample. Run bin/console list and grep for the bundle's namespace — the command names are the real API surface.

First use case: take one crontab line — say a nightly cleanup command — express it as a job definition, start the consumer, and watch it fire once with RabbitMQ's management UI open. That single loop teaches you the whole model (delay → deliver → execute → re-schedule).

Implementation Patterns

Declarative job registry, one entry per task. The bundle's core value is moving crontab entries into version-controlled config: each job = console command + cron expression + queue/routing. Do this for all recurring work so the schedule is reviewable in a PR rather than on a server someone SSH'd into.

Producer/consumer split. The scheduler publishes a delayed message; the consumer receives it, executes the command, then republishes the next occurrence. Practical consequences:

  • Scheduler and consumer are two long-running processes — two Supervisor programs, two log streams, two restart hooks on deploy.
  • Scale consumers independently of the scheduler. One slow job no longer blocks the others if you route jobs to separate queues.
  • Route noisy/batch jobs to a dedicated queue with its own prefetch and worker pool.

Deployment workflow (the part people actually stay for). The "commands to help with deployment" are meant to run before app code rolls out: ensure exchanges/queues exist and bindings are correct, so a fresh environment or a renamed queue doesn't silently drop messages. Put them in your CI/CD step after migrations, before the new container starts consuming.

Bridging to Laravel. If you keep Laravel as the system of record, make the job's command a thin Symfony command that shells out:

// conceptually: run an Artisan command, inherit exit code, stream output
$process = new Process(['php', base_path('artisan'), 'reports:rebuild', '--quiet']);
$process->setTimeout(3600);
$process->run();

Keep it to recurring, already-idempotent Artisan commands. Anything needing the full Laravel container (Eloquent models, config, facades) is better dispatched as a Laravel job over the same RabbitMQ exchange, with Laravel's own worker consuming it — RabbitMQ doesn't care who the producer was.

Observability. Log job start/end/duration with the job name as a structured field, and alert on queue depth and unacked count rather than on "command failed" alone. A scheduler that stops publishing looks identical to "nothing to do" otherwise.

Gotchas and Tips

Delayed delivery has a prerequisite. RabbitMQ has no native per-message delay. Depending on the version, the bundle relies on either the rabbitmq_delayed_message_exchange plugin or TTL + dead-letter exchanges. If you don't enable the plugin, your "delayed" messages either fail to declare or get delivered immediately — a classic silent misconfiguration. Check the plugin is enabled (rabbitmq-plugins list) and that the exchange type matches what the bundle declares.

At-least-once, always. A consumer crash after execution but before ack means the command runs twice. Every scheduled command must be idempotent or guarded. The bundle will not deduplicate for you.

Overlapping runs. Nothing stops tick N+1 from starting while tick N is still running. Put a lock around the work (Symfony Lock, a DB advisory lock, or a Redis SETNX) rather than assuming the queue serializes it.

Timezone and DST. Cron expressions are evaluated in the process timezone. Pin the timezone explicitly in config/php.ini and be aware that a job scheduled at 02:30 will behave oddly twice a year.

Long-running workers leak. Both processes are daemons; restart them on every deploy (opcache/class changes are invisible otherwise), cap memory_limit, and use --env=prod --no-debug semantics. This is the same discipline as Laravel Horizon's maxTime/maxJobs.

Dependency rot is real. Last release was 2022, 17 stars, 0 dependents. The videlalvaro/RabbitMqBundle it was written against is renamed/superseded — you will likely need php-amqplib/rabbitmq-bundle and may hit config-key or service-id drift. Pin exact versions, keep the bundle behind a small internal adapter, and be ready to fork. Budget for that maintenance cost in the decision.

Debugging checklist:

  • bin/console debug:container | grep -i job to confirm services and aliases registered.
  • RabbitMQ management UI / rabbitmqctl list_queues name messages_ready messages_unacknowledged — is the message in the queue, or stuck delayed?
  • Consume with a throwaway worker and -vvv before blaming the schedule math.
  • Verify the scheduler's computed next-fire time in logs before assuming the cron parser is wrong.

Extension points worth knowing: the job registry/service that maps job names to commands and the publisher/consumer services can usually be decorated (Symfony decorates:) — that's your hook for logging, metrics, per-job retry policies, or swapping in a Laravel dispatcher without forking.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings