News

Count Worker Crashes as Job Exceptions in Laravel 13.34

Published
Count Worker Crashes as Job Exceptions in Laravel 13.34 image

Release updates

Never miss a Laravel release

Get an email whenever a new Laravel release lands.

The Laravel team released v13.34.0 with an opt-in way to count worker crashes toward a job's maxExceptions, a timeout signal for interruptible jobs, a duration property on the JobProcessed event, a --queue option for queue:flush, and more.

Count Worker Crashes Toward maxExceptions

William Julian-Vicary contributed a #[CountCrashesAsExceptions] attribute for queued jobs. A job that throws an exception counts toward $maxExceptions, but a job whose worker dies mid-run (an out-of-memory kill, a segfault, or a container being stopped) does not. A job that uses retryUntil() with a rate limiter instead of $tries can keep crashing workers until its deadline passes.

With the attribute, a crashed attempt counts as one exception:

use Illuminate\Queue\Attributes\CountCrashesAsExceptions;
use Illuminate\Queue\Attributes\MaxExceptions;
 
#[MaxExceptions(3), CountCrashesAsExceptions]
class ProcessPodcast implements ShouldQueue
{
public function retryUntil(): DateTime
{
return now()->addHour();
}
}

A public $countCrashesAsExceptions = true; property works the same way. The worker writes a cache key when it starts an opted-in job and removes it when the attempt ends. If the key is still there on the next attempt, the previous one died, and the worker counts it against maxExceptions. The job needs a maxExceptions value, and each attempt adds two cache calls, which is why the feature is opt-in.

See #61737 for more details.

Interruptible Jobs Are Notified Before a Timeout

Jack Bayliss updated the worker so a job that implements the Interruptible contract receives SIGALRM when it hits its timeout. Before this release, the worker passed SIGTERM and similar signals to interruptible jobs, but a timeout killed the worker without calling the job first. The job can now save its progress before it is marked as failed:

use Illuminate\Contracts\Queue\Interruptible;
 
class GenerateReport implements ShouldQueue, Interruptible
{
public function interrupted(int $signal): void
{
if ($signal === SIGALRM) {
$this->saveProgress();
}
}
}

The worker also dispatches the JobInterrupted event added in Laravel 13.31, and reports any exception thrown by interrupted() without blocking the timeout.

See #61651 for more details.

Job Duration on JobProcessed

Jack Bayliss also added a duration property to the JobProcessed event, in milliseconds. Before, you had to listen for JobProcessing and JobProcessed and track the start time yourself:

use Illuminate\Queue\Events\JobProcessed;
 
Event::listen(function (JobProcessed $event) {
Log::info("{$event->job->resolveName()} took {$event->duration}ms");
});

The value is a float rounded to two decimal places. It is null when the event is dispatched from somewhere other than the worker.

See #61672 for more details.

Flush Failed Jobs for One Queue

queue:flush deletes every failed job on every queue. Jack Bayliss added a --queue option, so after a third-party API outage you can clear the failures from the affected queue and keep the rest:

php artisan queue:flush --queue=sftp-sync
 
# Combine with --hours to keep recent failures
php artisan queue:flush --queue=sftp-sync --hours=48

See #61630 for more details.

Schema::getColumn()

Francescu Garoby added Schema::getColumn(), which returns the details for one column instead of the full list from getColumns():

$column = Schema::getColumn('users', 'email');
 
$column['type_name']; // "varchar"
$column['nullable']; // false

It returns an empty array when the column does not exist.

See #61759 for more details.

assertDatabaseCount() Accepts an Array

Jack Bayliss updated assertDatabaseCount() to accept an array of table and count pairs, so you can check several tables in one call:

$this->assertDatabaseCount([
Person::class => 1,
Ticket::class => 2,
'movies' => 10,
]);

See #61727 for more details.

Enums in Environment Checks

Dennis Petersmann updated App::environment() and the scheduler's environments() method to accept enums. Passing an enum to App::environment() threw an error, and passing one to environments() on a scheduled task caused the task to never run:

enum Environment: string
{
case Staging = 'staging';
case Production = 'production';
}
 
App::environment(Environment::Production);
 
Schedule::command('reports:send')
->daily()
->environments(Environment::Production);

The @env Blade directive compiles to App::environment(), so it accepts enums too. In a separate PR, Jack Bayliss updated Queue::isPaused() to accept enums, matching Queue::pause() and Queue::resume() (#61725).

See #61730 for more details.

requireMorphMap() Applies on Read

Pauline Vos extended Relation::requireMorphMap() to the read side of polymorphic relations. With it turned on, Laravel already threw a ClassMorphViolationException when saving a model with no morph map entry. When loading a morphTo relation, an unmapped *_type value was still used as a class name. Laravel now throws the same exception when a *_type value is not in the morph map, for both lazy and eager loading.

Applications that do not call requireMorphMap() are not affected.

See #61711 for more details.

Release Notes

You can see the complete list of new features and updates below and the diff between 13.33.0 and 13.34.0 on GitHub. The following release notes are directly from the changelog:

v13.34.0

Paul Redmond photo

Staff writer at Laravel News. Full stack web developer and author.

Sponsored

laravelcloud logo
Laravel Cloud

Easily create and manage your servers and deploy your Laravel applications in seconds.

Visit Laravel Cloud

The latest

View all →
Critical Token Guard Auth Bypass Fixed in Laravel 13.29 and 12.68 image

Critical Token Guard Auth Bypass Fixed in Laravel 13.29 and 12.68

Read article
Run Large PlanetScale Queries in Laravel With DB::olap() image

Run Large PlanetScale Queries in Laravel With DB::olap()

Read article
Fluent Rule Builders for All Laravel Validation Rules image

Fluent Rule Builders for All Laravel Validation Rules

Read article
Laravel URL AI Transformer: Extract Structured Data From URLs image

Laravel URL AI Transformer: Extract Structured Data From URLs

Read article
Rule Builders for Every Validation Rule in Laravel 13.36 image

Rule Builders for Every Validation Rule in Laravel 13.36

Read article
PHP News: A New Site for PHP Releases, RFCs, and Packages image

PHP News: A New Site for PHP Releases, RFCs, and Packages

Read article