Panoramica
Le code di Laravel offrono due tipi di controllo dell’esecuzione dei job: la deduplicazione (Unique) e il debounce. Entrambi servono a “evitare esecuzioni inutili quando lo stesso job viene dispatchato più volte”, ma si comportano in modo diverso.Unique Jobs — ShouldBeUnique
Finché uno stesso job è presente in coda, i dispatch aggiuntivi vengono ignorati.
UpdateSearchIndex è in coda (o in elaborazione), il tentativo di dispatchare lo stesso job viene ignorato.
Restringere il vincolo di unicità tramite chiave — UniqueFor + uniqueId()
Se all’interno della stessa classe di job vuoi trattare “aggiornamento del prodotto A” e “aggiornamento del prodotto B” come job distinti, definisci una chiave con il metodo uniqueId().
- Il valore restituito da
uniqueId()diventa la chiave del lock di cache. - Specificando
#[UniqueFor(secondi)], dopo tale numero di secondi il lock viene rilasciato automaticamente (fail-safe nel caso il job non venga elaborato).
Specificare il driver di cache — uniqueVia()
Se vuoi usare un driver di cache diverso da quello predefinito, implementa uniqueVia().
Gli Unique Jobs richiedono un driver di cache che supporti i lock atomici (
redis, database, memcached, dynamodb, file, array).ShouldBeUnique vs ShouldBeUniqueUntilProcessing
Il lock di ShouldBeUnique viene mantenuto fino a quando il job è completato o raggiunge il limite di retry. Ci sono casi in cui questo diventa un problema.
Esempio: in coda c’è un UpdateSearchIndex(product_id: 42) e vuoi ridispacciare lo stesso job subito dopo che il worker inizia a processarlo. Con ShouldBeUnique il secondo dispatch non entra in coda fino al completamento del primo.
In questo caso usa ShouldBeUniqueUntilProcessing. Il lock viene rilasciato appena prima dell’inizio dell’elaborazione, quindi nel momento in cui il worker preleva il job è possibile un nuovo dispatch.
Riepilogo del confronto
Debounced Jobs — #[DebounceFor]
L’attributo
DebounceFor è una funzionalità aggiunta in Laravel 13.- Il valore restituito da
debounceId()identifica il job (viene applicato un debounce indipendente per ogni ID prodotto). - Se lo stesso
productIdviene dispatchato 10 volte in 30 secondi, viene eseguito solo l’ultimo.
maxWait — limite massimo del tempo di attesa
Su dati aggiornati frequentemente, il debounce potrebbe continuare all’infinito e il job non venire mai eseguito. Con maxWait puoi impostare il ritardo massimo.
Specificare il driver di cache — debounceVia()
Evento JobDebounced
I job sovrascritti da un dispatch successivo emettono l’evento Illuminate\Queue\Events\JobDebounced e vengono rimossi dalla coda. Ascoltando questo evento puoi tracciare e monitorare i job che hanno subito il debounce.
Quale usare
Implementazione interna
Meccanismo di lock degli Unique Jobs
Quando viene dispatchato un jobShouldBeUnique, Laravel acquisisce internamente un lock atomico sulla cache. La chiave del lock ha il seguente formato:
Implementazione dei Debounced Jobs
DebounceFor internamente usa una entry di cache per gestire la “finestra di debounce”. Ad ogni nuovo dispatch:
- Rimuove il job esistente dalla coda (emette l’evento
JobDebounced) - Aggiunge il nuovo job alla coda (con un ritardo pari ai secondi di debounce)
- Resetta il timer nella cache
maxWait, viene registrato anche il timestamp del primo dispatch, così da impedire che il debounce superi maxWait secondi da quel momento.