Laravel Queues (L13 — Attributes-first)
Agent Workflow (MANDATORY)
Before ANY implementation, spawn 3 agents in parallel, one Agent call each with a name:
- fuse-ai-pilot:explore-codebase - Audit job classes, connections, queue routes
- fuse-ai-pilot:research-expert - Verify L13 Queue + Queue::route() via Context7
- mcp__context7__query-docs - Check queue attribute patterns
After implementation, run fuse-ai-pilot:sniper for validation.
Overview
Laravel 13 introduces PHP Attributes on Queueables (Jobs, Listeners, Notifications, Mailables, Broadcast Events) as the primary configuration mechanism. Centralised routing is configured via Queue::route() in AppServiceProvider::boot().
| Attribute (L13 MAIN) | Legacy property |
|----------------------|-----------------|
| #[Connection('redis')] · #[Queue('podcasts')] | public $connection · public $queue |
| #[Tries(5)] · #[Timeout(120)] · #[MaxExceptions(3)] | public int $tries / $timeout / $maxExceptions |
| #[Backoff([10, 30, 60])] · #[FailOnTimeout] | public $backoff · public bool $failOnTimeout |
| #[UniqueFor(3600)] · #[DeleteWhenMissingModels] · #[Delay(60)] | public $uniqueFor / $deleteWhenMissingModels / $delay |
| #[DebounceFor(30, maxWait: 120)] (13.6+, with debounceId()) | — |
| no attribute — ->afterCommit() / ShouldQueueAfterCommit | public $afterCommit |
Applies to Jobs, Listeners, Notifications, Mailables, and Broadcast Events.
Critical Rules
- Declare queue metadata with Attributes -
#[Queue],#[Tries],#[Backoff] - Centralise routing with
Queue::route()inAppServiceProvider::boot() - Implement
failed(Throwable $e)for every production job - Use
->afterCommit()(orafter_commitconnection config) when dispatching inside DB transactions - Monitor Redis queues with Horizon in production
Architecture
app/
├── Jobs/
│ └── ProcessPodcast.php # #[Connection, Queue, Tries, Backoff]
├── Providers/
│ └── AppServiceProvider.php # Queue::route(ProcessPodcast::class, 'redis')
└── Listeners/
└── SendShipmentNotification.php # #[Queue('mail')]
→ See templates/QueueableJob.php.md
Reference Guide
Concepts
- Migration L12→L13: legacy-properties.md
- Jobs lifecycle: jobs.md · dispatching.md · workers.md
- Composition: batching.md · chaining.md · middleware.md
- Reliability: failed-jobs.md · horizon.md · testing.md · troubleshooting.md
Templates
| Template | When to Use | |----------|-------------| | QueueableJob.php.md | Attribute-based job | | BatchJob.php.md | Batchable job | | ChainedJobs.php.md | Job chain | | JobMiddleware.php.md | Custom middleware | | JobTest.php.md | Job test |
Quick Reference
Attribute-based Job (L13 MAIN)
use Illuminate\Queue\Attributes\{Connection, Queue, Tries, Timeout, Backoff, MaxExceptions, FailOnTimeout, UniqueFor};
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
#[Connection('redis')]
#[Queue('podcasts')]
#[Tries(5)]
#[Timeout(120)]
#[Backoff([10, 30, 60])]
#[MaxExceptions(3)]
#[FailOnTimeout]
#[UniqueFor(3600)]
final class ProcessPodcast implements ShouldQueue
{
use Queueable;
public function __construct(public readonly Podcast $podcast) {}
public function handle(PodcastService $service): void { $service->process($this->podcast); }
public function failed(\Throwable $e): void { Log::error('Podcast failed', ['id' => $this->podcast->id, 'e' => $e]); }
}
Queue Routing (centralised)
// app/Providers/AppServiceProvider.php
use Illuminate\Support\Facades\Queue;
public function boot(): void
{
// First argument = job class, or an interface / trait / parent class
Queue::route(ProcessPodcast::class, connection: 'redis', queue: 'media');
Queue::route(ShouldBroadcast::class, queue: 'events');
Queue::route([ProcessVideo::class => ['redis', 'videos']]);
// Forward a queue to another queue / connection (13.26+)
Queue::forward('reports', 'reports.fifo', 'sqs');
}
Other 13.x additions
Bus::bulk($jobs)(13.13+) — push many independent jobs grouped by connection/queue, no batch trackingPreparesForDispatchinterface (13.9+) —prepareForDispatch()returningfalseskips dispatchIlluminate\Queue\Middleware\Releasejob middleware (13.18+) —Release::when($condition, releaseAfter: 60)
→ Legacy public int $tries = 5 style — see legacy-properties.md
Best Practices
DO
- Use Attributes on Jobs, Listeners, Notifications, Mailables, Broadcast Events
- Centralise routing via
Queue::route()inAppServiceProvider::boot() - Use
->afterCommit()when dispatching inside a transaction finaljob classes, implementfailed(), monitor Redis with Horizon
DON'T
- Mix
#[Tries]andpublic int $tries(single source of truth) - Dispatch in a transaction without
->afterCommit()(orafter_commit => true) - Store large objects/closures in job constructor properties
- Use
syncdriver in production
微信扫一扫