- Laravel
- queue
- concurrency
Run jobs for the same record one at a time
The WithoutOverlapping middleware lets two workers process different orders in parallel but never the same order twice at once.
1 min read
Two workers picking up two jobs for the same order is how a balance gets charged twice. The fix belongs on the job, not in every handler.
use Illuminate\Queue\Middleware\WithoutOverlapping;
public function middleware(): array
{
return [
(new WithoutOverlapping($this->order->id))
->releaseAfter(30)
->expireAfter(180),
];
}While one job holds the lock for that order id, another job with the same key is released back to the queue and tried again after 30 seconds. expireAfter frees the lock if a job dies without releasing it; set it longer than the job can run. Use ->dontRelease() to drop the duplicate instead of retrying it.