Kirill Dakhniuk

July 16, 2024

Am I the only one who missed this Laravel Middleware?

Hey Reader,

Recently, I was working on a task that required dispatching a batch with numerous jobs. After deploying the task, I noticed on the Laravel Horizon Dashboard that for some users, one job in the batch failed. I knew that unless allowFailures() is called, the batch will be marked as canceled. So, if job #1 failed, why were the other jobs in the batch not only processed but executed? That’s odd, I thought… 

Well, somehow, I missed a gem in the Laravel docs — SkipIfBatchCancelled.

Let’s go through a quick examples.

In this one, TheOneToSucceed will be processed and executed.

Bus::batch([
    new TheOneToFail,
    new TheOneToSucceed,
])->dispatch();

class TheOneToFail implements ShouldQueue
{
    // ...

    public function handle(): void
    {
        throw new Exception('Innocent victim of our tests...');
    }
}

class TheOneToSucceed implements ShouldQueue
{
    // ..

    public function handle(): void
    {
        echo 'Did not have a chance by design...';
    }
}

To prevent such unexpected behavior, we simply need to assign the SkipIfBatchCancelled middleware to the job. By doing so, the job will be processed but not executed if the batch is canceled. The updated job will look like this:

class TheOneToSucceed implements ShouldQueue
{
    // ..

    public function handle(): void
    {
        echo 'Did not have a chance by design...';
    }

    public function middleware(): array
    {
        return [new SkipIfBatchCancelled];
    }
}

Such a simple and elegant solution, isn’t it?

Best,
Kirill