stancl/jobpipeline
Turn any series of Laravel jobs into an event listener. Build pipelines that pull data from events, run jobs sequentially, and choose sync or queued execution (with optional queue name). Ideal for workflows like tenant setup, migrations, and seeding.
OrderCreated → ProcessOrderPipeline). Reduces tight coupling between services and simplifies cross-cutting concerns (logging, retries, monitoring).OrderProcessingPipeline composed of ValidateOrderJob, ChargePaymentJob, FulfillOrderJob instead of a single ProcessOrderJob.tenant, order) through all pipeline steps, critical for multi-tenancy and transactional workflows.false to cancel subsequent jobs), enabling conditional logic (e.g., skip shipping if payment fails).high-priority for payments), improving resource allocation and SLA compliance.Event, Queue, Jobs), requiring zero framework changes. Compatible with Laravel 11–13 and PHP 8.1+.ShouldQueue or non-queued job, including third-party jobs (e.g., Spatie\MediaLibrary\Jobs\ProcessOptimizedImage).Event::listen() and EventServiceProvider, enabling event-driven architecture without custom listeners.ApplyDiscountJob conditionally) via closures, reducing boilerplate.| Risk Area | Mitigation Strategy |
|---|---|
| Queue Failures | Use Laravel’s retry-after and fail callbacks to handle job failures gracefully. |
| Data Consistency | Ensure pipeline steps are idempotent or use database transactions for critical steps. |
| Performance | Monitor queue backlogs; avoid long-running pipelines (>5 mins). Use shouldBeQueued() to optimize. |
| Debugging | Implement structured logging (e.g., JobPipeline::make()->logProgress()) and Sentry integration. |
| Version Compatibility | Lock to v2.x for Laravel 13 support; monitor for breaking changes in minor releases. |
| Error Handling | Use try-catch in pipeline steps or leverage Laravel’s Handle interface for global exception handling. |
| Testing Complexity | Mock JobPipeline in unit tests; use JobPipeline::fake() (if available) or Queue::fake() for integration tests. |
spatie/laravel-sagas).job:batch) or strict ordering (pipelines)?send().pipeline_duration_ms).OrderCreated, UserRegistered).// Before: Monolithic job
class ProcessOrderJob implements ShouldQueue {
public function handle() {
$this->validateOrder();
$this->chargePayment();
$this->fulfillOrder();
}
}
// After: Pipeline
Event::listen(OrderCreated::class, JobPipeline::make([
ValidateOrderJob::class,
ChargePaymentJob::class,
FulfillOrderJob::class,
])->send(fn (OrderCreated $event) => $event->order)->shouldBeQueued());
shouldBeQueued('high-priority') for payments).FulfillOrderJob if ChargePaymentJob fails).v1.x).v2.0.0-rc4).Illuminate\Contracts\Queue\ShouldQueue or non-queued job.QUEUE_CONNECTION in .env).php artisan queue:work).composer require stancl/jobpipeline
EventServiceProvider:
protected $listen = [
OrderCreated::class => [
JobPipeline::make([...])->send(...)->toListener(),
],
];
Queue::fake():
use Illuminate\Support\Facades\Queue;
public function test_order_pipeline() {
Queue::fake();
event(new OrderCreated(...));
Queue::assertPushed(ValidateOrderJob::class);
Queue::assertPushed(ChargePaymentJob::class);
}
EventServiceProvider).ChargePaymentJob without touching the pipeline).How can I help you explore Laravel packages today?