News

Count Worker Crashes as Job Exceptions in Laravel 13.34

Published
Count Worker Crashes as Job Exceptions in Laravel 13.34 image

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

serpapi logo
SerpApi

The Web Search API for Your LLM and AI Applications

Visit SerpApi

The latest

View all →
Mailbox for Laravel: Preview and Test Rendered Email image

Mailbox for Laravel: Preview and Test Rendered Email

Read article
Elastic Bridge: Eloquent-Style Queries for Elasticsearch and OpenSearch image

Elastic Bridge: Eloquent-Style Queries for Elasticsearch and OpenSearch

Read article
Laravel Release Cycle: Versions, Support Policy, and Dates image

Laravel Release Cycle: Versions, Support Policy, and Dates

Read article
Unlearn.dev goes free for a weekend, October 10 and 11 image

Unlearn.dev goes free for a weekend, October 10 and 11

Read article
Tashil: Laravel Subscription Plans and Feature Usage Limits image

Tashil: Laravel Subscription Plans and Feature Usage Limits

Read article
Decide with Jev: Laravel AI That Answers with a Probability image

Decide with Jev: Laravel AI That Answers with a Probability

Read article