Contare i crash dei worker come eccezioni dei job in Laravel 13.34
Il team di Laravel ha rilasciato la v13.34.0 con una modalità opt-in per conteggiare i crash dei worker ai fini delle maxExceptions di un job, un segnale di timeout per i job interrompibili, una proprietà duration sull'evento JobProcessed, un'opzione --queue per queue:flush e molto altro.
Conteggiare i crash dei worker verso maxExceptions
William Julian-Vicary ha contribuito con un attributo #[CountCrashesAsExceptions] per i job in coda. Un job che lancia un'eccezione viene conteggiato ai fini di $maxExceptions, ma un job il cui worker muore a metà esecuzione (un kill per memoria esaurita, un segfault o un container che viene fermato) no. Un job che usa retryUntil() con un rate limiter invece di $tries può continuare a far crashare i worker finché non scade la sua deadline.
Con l'attributo, un tentativo andato in crash conta come una eccezione:
use Illuminate\Queue\Attributes\CountCrashesAsExceptions;
use Illuminate\Queue\Attributes\MaxExceptions;
#[MaxExceptions(3), CountCrashesAsExceptions]
class ProcessPodcast implements ShouldQueue
{
public function retryUntil(): DateTime
{
return now()->addHour();
}
}Anche una proprietà public $countCrashesAsExceptions = true; funziona allo stesso modo. Il worker scrive una cache key quando avvia un job che ha aderito all'opt-in e la rimuove quando il tentativo termina. Se la key è ancora presente al tentativo successivo, significa che quello precedente è morto, e il worker lo conteggia ai fini di maxExceptions. Il job necessita di un valore maxExceptions, e ogni tentativo aggiunge due chiamate alla cache: è per questo che la funzionalità è opt-in.
Vedi #61737 per maggiori dettagli.
I job interrompibili vengono avvisati prima di un timeout
Jack Bayliss ha aggiornato il worker in modo che un job che implementa il contratto Interruptible riceva SIGALRM quando raggiunge il proprio timeout. Prima di questa release, il worker passava SIGTERM e segnali simili ai job interrompibili, ma un timeout uccideva il worker senza prima chiamare il job. Ora il job può salvare i propri progressi prima di essere marcato come fallito:
use Illuminate\Contracts\Queue\Interruptible;
class GenerateReport implements ShouldQueue, Interruptible
{
public function interrupted(int $signal): void
{
if ($signal === SIGALRM) {
$this->saveProgress();
}
}
}Il worker invia anche l'evento JobInterrupted aggiunto in Laravel 13.31 e segnala qualsiasi eccezione lanciata da interrupted() senza bloccare il timeout.
Vedi #61651 per maggiori dettagli.
Durata del job su JobProcessed
Jack Bayliss ha anche aggiunto una proprietà duration all'evento JobProcessed, espressa in millisecondi. Prima bisognava ascoltare JobProcessing e JobProcessed e tenere traccia dell'ora di inizio manualmente:
use Illuminate\Queue\Events\JobProcessed;
Event::listen(function (JobProcessed $event) {
Log::info("{$event->job->resolveName()} took {$event->duration}ms");
});Il valore è un float arrotondato a due cifre decimali. È null quando l'evento viene inviato da un punto diverso dal worker.
Vedi #61672 per maggiori dettagli.
Svuotare i job falliti di una sola coda
queue:flush elimina ogni job fallito su tutte le code. Jack Bayliss ha aggiunto un'opzione --queue, così dopo un'interruzione di un'API di terze parti puoi cancellare i fallimenti dalla coda interessata e mantenere tutti gli altri:
php artisan queue:flush --queue=sftp-sync
# Combine with --hours to keep recent failures
php artisan queue:flush --queue=sftp-sync --hours=48Vedi #61630 per maggiori dettagli.
Schema::getColumn()
Francescu Garoby ha aggiunto Schema::getColumn(), che restituisce i dettagli di una singola colonna invece dell'elenco completo di getColumns():
$column = Schema::getColumn('users', 'email');
$column['type_name']; // "varchar"
$column['nullable']; // falseRestituisce un array vuoto quando la colonna non esiste.
Vedi #61759 per maggiori dettagli.
assertDatabaseCount() accetta un array
Jack Bayliss ha aggiornato assertDatabaseCount() per accettare un array di coppie tabella/conteggio, così puoi verificare più tabelle con una sola chiamata:
$this->assertDatabaseCount([
Person::class => 1,
Ticket::class => 2,
'movies' => 10,
]);Vedi #61727 per maggiori dettagli.
Enum nei controlli dell'ambiente
Dennis Petersmann ha aggiornato App::environment() e il metodo environments() dello scheduler per accettare gli enum. Passare un enum a App::environment() lanciava un errore, e passarne uno a environments() su un task schedulato faceva sì che il task non venisse mai eseguito:
enum Environment: string
{
case Staging = 'staging';
case Production = 'production';
}
App::environment(Environment::Production);
Schedule::command('reports:send')
->daily()
->environments(Environment::Production);La direttiva Blade @env viene compilata in App::environment(), quindi accetta anch'essa gli enum. In una PR separata, Jack Bayliss ha aggiornato Queue::isPaused() per accettare gli enum, allineandolo a Queue::pause() e Queue::resume() (#61725).
Vedi #61730 per maggiori dettagli.
requireMorphMap() si applica in lettura
Pauline Vos ha esteso Relation::requireMorphMap() al lato di lettura delle relazioni polimorfiche. Con questa opzione attiva, Laravel lanciava già una ClassMorphViolationException quando si salvava un model senza una voce nella morph map. Durante il caricamento di una relazione morphTo, un valore *_type non mappato veniva comunque usato come nome di classe. Ora Laravel lancia la stessa eccezione quando un valore *_type non è presente nella morph map, sia in lazy che in eager loading.
Le applicazioni che non chiamano requireMorphMap() non sono interessate.
Vedi #61711 per maggiori dettagli.
Note di rilascio
Qui sotto puoi vedere l'elenco completo delle nuove funzionalità e degli aggiornamenti, oltre al diff tra 13.33.0 e 13.34.0 su GitHub. Le seguenti note di rilascio provengono direttamente dal changelog:
v13.34.0
- [13.x] Inclusa la duration nell'evento JobProcessed di @jackbayliss in #61672
- [13.x] Notifica il job quando sta per verificarsi un timeout di @jackbayliss in #61651
- [13.x] Aggiunta l'opzione --queue a queue:flush di @jackbayliss in #61630
- Consenti null nei docblock per allinearli al codice esistente di @miclf in #61679
- [13.x] Supporto ai valori LazyCollection nelle clausole between di @vikas-kushwaha-dev in #61678
- [13.x] Sincronizza gli attributi aggiornati allo stato originale dopo increment / decrement di @ilhammmaulana in #61680
- [13.x] Corretto
Number::parseInt()che restituiva false per valori oltre il range a 32 bit di @sumaiazaman in #61691 - [13.x] Corretto
PhpRedisLock::refresh()quando la serializzazione di phpredis è abilitata di @sumaiazaman in #61690 - [13.x] Corretto Collection::mode() che restituiva valori non presenti nei dati in presenza di null di @MoZayedSaeid in #61686
- [13.x] Sistemati alcuni docblock del worker di @jackbayliss in #61683
- [13.x] Rispetta la owner key della relazione in whereMorphedTo / whereNotMorphedTo di @axlon in #61712
- Applica la morph map sul lato di lettura delle relazioni polimorfiche di @paulinevos in #61711
- [13.x] Mostra un errore in
queue:restartquando il worker non è riavviabile di @jackbayliss in #61706 - [13.x] Miglioramenti ai test di @crynobone in #61697
- [13.x] Lancia ValueError in LazyCollection::combine() in caso di lunghezze non corrispondenti di @mrjavadseydi in #61696
- [13.x] Corretto
trans_choice()che sceglieva la forma plurale sbagliata per i numeri negativi di @sumaiazaman in #61700 - [13.x] Non ignorare i deadlock in
DatabaseLockall'interno di una transazione di @lazerg in #61708 - [13.x] Corretto
sortBy()con più colonne eSORT_NUMERICche troncava i valori frazionari di @sumaiazaman in #61699 - [13.x] Corretto Number::format(), percentage() e currency() che restituivano "-0" di @mrjavadseydi in #61716
- [13.x] Permetti ad assertDatabaseCount di accettare un array di @jackbayliss in #61727
- [13.x] Corretta la perdita dei contenuti degli stream allegati nelle richieste multipart in caso di retry di @mehdishakki in #61728
- [13.x] Permetti gli enum in Queue::isPaused() di @jackbayliss in #61725
- [13.x] Corretta la doppia negazione in Eloquent
whereNot()con condizioni ad array di @Nejcc in #61721 - [13.x] Permetti gli enum nei controlli dell'ambiente di @Taldres in #61730
- [13.x] Restituisci una collection vuota da
shift($count)su una collection vuota di @Nejcc in #61723 - [13.x] Testa con oggetti reali di @jasonmccreary in #61663
- [13.x] Eccezioni Cloud di @timacdonald in #61704
- [13.x] Esegui i workflow su Windows 2025 di @jnoordsij in #61718
- [13.x] Usa lookup a tempo costante per le esclusioni del validator di @owenconti in #61698
- [13.x] Preserva le opzioni PDO esistenti quando si forza il prepared emulato per Cloud Postgres in pool di @laurenschristian in #61735
- [13.x] Corretto l'uso della direttiva blade elsePushIf con condizioni complesse di @mrjavadseydi in #61741
- [13.x] Corretto il lock Memcached superiori a 30 giorni che scadevano immediatamente di @sumaiazaman in #61742
- [13.x] Permetti ai job di conteggiare i crash dei worker verso maxExceptions di @williamjulianvicary in #61737
- [13.x] Corretto il throttle di Redis che restituiva un timestamp come tentativi rimanenti di @sumaiazaman in #61748
- Corretti i typo nei file Markdown di @peter279k in #61746
- [13.x] Supporto ai provider di credenziali S3 con nome e ai dischi Cloud IAM di @kieranbrown in #61676
- [13.x] Supporta
phpstan/phpstan:2.2.15di @crynobone in #61719 - [13.x] feat: aggiunto il nuovo metodo 'Database\Schema\Builder::getColumn' di @fgaroby in #61759
- Applica le correzioni da StyleCI di @taylorotwell in #61763
- [13.x] Corretto through() che restituiva HasOneThrough per le relazioni MorphMany di @mrjavadseydi in #61760
- [13.x] Escludi gli attributi aggiornati durante la replica dei model di @ilhammmaulana in #61751
- [13.x] Corretto
wherePivotBetween()che veniva ignorato dasync(),detach()eupdateExistingPivot()di @sumaiazaman in #61747 - [13.x] Corretto il test di scheduling instabile su Windows di @jasonmccreary in #61768
- [13.x] Corretto findOrFail() con un array di id enum di @jabysa in #61765
- [13.x] Corretto
Builder::with()quando viene passata esplicitamente una callback null di @lazerg in #61769 - Pulizia finale di Mockery di @jasonmccreary in #61739
- [13.x] Tratta le chiavi con punti letteralmente in ArrayStore::touch() di @Button99 in #61777
- [13.x] Corretto la cache taggata memoizzata
many()che restituiva null per chiavi numeriche di @sajjadhossainshohag in #61780 - [13.x] Aggiunto un test di regressione per createPayloadUsing sul queue manager di @fajarwz in #61773
- [13.x] Aggiunto il mime type ai dettagli reportable dei file di @sbourouis in #61772
- [13.x] Abilitata esplicitamente l'estensione imagick per i test CI di @jnoordsij in #61756
Fonte originale:
https://laravel-news.com/laravel-13-34-0Altri articoli recenti
Laravel AI 1.1 e 1.2: Agent Skills, Cohere e structured output più solidi
Le release 1.1.0 e 1.2.0 di laravel/ai portano gli Agent Skills, l'approvazione obbligatoria per i tool built-in e nuovi provider come Cohere e Laya self-hosted. Sul fronte qualità arrivano i fix allo structured output per Bedrock e il supporto alle provider options. Aggiornati anche i modelli di default, con Claude 4.7+ che ignora i sampling params.
Laravel 13.35.0: scheduler più controllabile, code più flessibili e response Markdown
Laravel 13.35.0 porta Schedule::alwaysOnOneServer(), il supporto a schedule:interrupt per i comandi di lunga durata, --memory in percentuale per queue:work e il nuovo metodo markdown() sulla response factory. Tante piccole migliorie anche a test, view compilate in parallelo e dischi local.
BashBox: un interprete Bash in sandbox per agenti AI in PHP
BashBox è un interprete bash scritto in puro PHP che permette di eseguire gli script generati dagli agenti AI senza mai ricorrere a proc_open, exec o shell_exec. Ogni comando è una classe PHP che lavora su un filesystem virtuale, con limiti di esecuzione, quote disco e accesso di rete configurabili. Ideale per chi sviluppa agenti con il Laravel AI SDK o altre librerie simili.