Skip to main content

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 e Debounced Jobs sono mutuamente esclusivi. Non implementare ShouldBeUnique sui job che usano l’attributo DebounceFor.

Unique Jobs — ShouldBeUnique

Finché uno stesso job è presente in coda, i dispatch aggiuntivi vengono ignorati.
Mentre 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.
Se lo stesso job viene dispatchato molte volte in un breve intervallo, viene eseguito solo l’ultimo dispatch. È lo stesso concetto del debounce del frontend web.
  • Il valore restituito da debounceId() identifica il job (viene applicato un debounce indipendente per ogni ID prodotto).
  • Se lo stesso productId viene 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.
In questo esempio, dal primo dispatch il job viene eseguito comunque al massimo entro 120 secondi (anche se il debounce di 30 secondi continua, va in timeout a 120 secondi).

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 job ShouldBeUnique, Laravel acquisisce internamente un lock atomico sulla cache. La chiave del lock ha il seguente formato:
Se il lock non può essere acquisito (perché è già tenuto da un altro job), il job non viene aggiunto alla coda.

Implementazione dei Debounced Jobs

DebounceFor internamente usa una entry di cache per gestire la “finestra di debounce”. Ad ogni nuovo dispatch:
  1. Rimuove il job esistente dalla coda (emette l’evento JobDebounced)
  2. Aggiunge il nuovo job alla coda (con un ritardo pari ai secondi di debounce)
  3. Resetta il timer nella cache
Se è specificato maxWait, viene registrato anche il timestamp del primo dispatch, così da impedire che il debounce superi maxWait secondi da quel momento.

Riferimenti

Ultima modifica il 2 agosto 2026