pixelplan/messenger-job-batch-bundle
A Symfony bundle that adds job batching to Messenger, letting you dispatch, track, and manage groups of related messages as batches with progress and completion handling.
What the package actually is. Unchanged by this release: this is a Symfony bundle, not a Laravel package. It registers through the Symfony bundle/DI system (Kernel::bundles.php, DependencyInjection/Extension, service tags) and hooks Messenger's worker lifecycle events to record per-message completion and emit a "batch finished" signal. There is no service provider, facade, config publish, or Illuminate\Bus\Batch integration. Release 0.0.8 ("Add support for Symfony 8") reinforces this — widening the Symfony constraint is a Symfony-ecosystem maintenance act, not a Laravel one.
Architecture fit. Fit remains conditional on the host being Symfony with Messenger already in production. The 0.0.8 change improves the forward fit: Symfony 8 support means the bundle is not immediately stranded when the host app next takes a major-version upgrade. Two caveats matter architecturally. First, Symfony 8 raises the floor to PHP 8.4, so the package's PHP constraint almost certainly moved up — which can retroactively constrain our PHP version if Composer resolves to 0.0.8. Second, a package claiming ^5.4 || ^6 || ^7 || ^8 is claiming four majors of API stability across two PHP-minimum eras; that is a wide, hard-to-prove surface for a 0.0.x project with no visible CI matrix. The original architectural requirement is untouched: batch state must live in a shared, durable store visible to every worker host and surviving restarts, and mixed-transport topologies still need verification.
Integration feasibility. Still small surface — one stamp class, event subscribers, a persistence entity/schema, a completion dispatcher. composer require remains a five-minute step; the real cost is stamping messages at dispatch, provisioning/migrating the state store, wiring completion handlers, and proving concurrency correctness. Realistic spike: 2–4 engineer-days plus a week of soak testing. Add roughly half a day to re-read the diff for 0.0.8 itself (a version-constraint bump can mask small compatibility shims — a renamed event class, a signature change to accommodate Symfony 8 deprecations) and to resolve the package against our actual PHP version.
Technical risk. Still high, with one item partially improved and one newly introduced:
0.0.x bump can break us on a patch release. Fork-and-own remains the hedge; note that forking now means we inherit the Symfony 8 branch too.0.0.8 resolves to an installable tag rather than dev-main, and check whether the Symfony 8 constraint is ^8.0 (a GA tag) or 8.0.x-dev (which would mean the package now depends on a pre-release and could destabilise our lock file).Key questions for the maintainer / code review (updated).
composer.json for Symfony 8 — constraint only, or code shims? Did the PHP floor move to 8.4, and does 0.0.8 still install on our PHP version?UPDATE … SET done = done + 1 with compare-and-set, or read-modify-write? Is there a unique constraint for idempotency under redelivery?WorkerMessageFailedEvent after retries)? Does the batch go to failed, or hang in pending?catch/finally semantics, or a single success callback only?Stack fit — still the decisive gate. If the consuming application is Laravel, this package remains not applicable and should be closed at triage. Laravel ships Bus::batch() natively with then/catch/finally, allowFailures(), and a migrated job_batches table. Adopting a Symfony-bundle-shaped dependency would mean manually registering a bundle in a framework with no bundle kernel, pulling symfony/messenger alongside Laravel's queue worker, and owning two competing async models. Symfony 8 support does nothing for this — it moves the target version further from anything a Laravel app would want. Recommendation: do not integrate into Laravel. If the team is seriously weighing symfony/messenger inside Laravel, that decision dwarfs this bundle and needs its own evaluation.
If the host is Symfony, fit is reasonable and the path is conventional:
composer.lock is mandatory, and ~0.0.8 style ranges should be avoided.WorkerMessageHandledEvent subscriber + atomic increment). Fork/in-house is still a legitimate outcome given the vendor profile — and with 0.0.8 the fork simply starts from a newer base.Maintenance. Bus factor still one, no published security process, no release cadence to rely on. 0.0.8 is a modest positive signal on liveness, but the 0.0.x versioning is the operative fact: the maintainer reserves the right to break us on any release, including a patch. Treat this as vendored code with a friendly upstream — fork on adoption, mirror internally, expect to carry patches. Mitigating factor is unchanged: total surface is small enough for a mid-level engineer to own in a sprint.
Support. No commercial backing, no SLA. Operational support is ours, so a written runbook is a launch blocker: how to inspect a batch, force-complete or abort one, and identify stuck batches.
Scaling. Dominant cost unchanged: one state write per handled message. Invisible at tens of messages/second; above that, a single hot counter row becomes a lock-contention point and can measurably slow the worker pool. Measure throughput with and against the bundle at peak sustained rate during the spike. Second concern: unbounded table growth — nothing in the package description suggests retention, so we own a purge job from day one. New consideration: if the host is on Symfony 6.4/7.x while the maintainer's focus moves to 8, we should expect no performance work or store-backend improvements on our line.
Failure modes to instrument.
Ramp-up. Low technical curve — an engineer familiar with Symfony Messenger middleware is productive in half a day. Non-obvious cost is organisational: on-call must recognise stuck batches, and the team must accept that "batch complete" is a business-critical signal they own end-to-end. Budget a day of documentation plus a runbook entry, and add a short note on which Symfony version line we validated against.
Portfolio decision — bottom line. As a Laravel dependency: reject, not applicable (unchanged). As a Symfony dependency: still conditional, slightly more attractive — 0.0.8 shows the maintainer tracking the ecosystem and extends the package's useful life into Symfony 8, which removes a near-term "will this rot?" objection. It does not address the two things that actually gate adoption: the pre-1.0/no-BC-promise vendor profile and the distributed-counter correctness at the core. Sensible play is unchanged: a two-to-four-day evaluation spike (plus a half-day diff of 0.0.8), with fork-and-own or a ~300-line in-house equivalent as the likely landing zone unless source review shows a genuinely rigorous, atomic, idempotent implementation and a real CI matrix.
How can I help you explore Laravel packages today?