Com pausar i controlar cues a Laravel pas a pas

Darrera actualització: 5 de desembre de 2025
  • Laravel ofereix una API unificada de cues amb múltiples drivers (database, Redis, SQS…) i separació entre connexions i cues lògiques.
  • Els Jobs permeten moure tasques pesades a segon pla, amb suport per serialitzar models, middleware, treballs únics, xifrat, lots i cadenes.
  • Els workers es gestionen amb queue:work, Supervisor i ordres com queue:pause/queue:continue, controlant reintents, timeouts i prioritats.
  • Hi ha un ecosistema complet per a fallades, monitorització i proves (failed_jobs, queue:retry, queue:monitor, Queue::fake) que fa les cues fiables en producció.

Gestió de cues a Laravel

Treballar amb cues a Laravel és gairebé obligatori en qualsevol projecte mig seriós: enviament de correus, processament de CSV, generació de PDFs, redimensionat d'imatges, trucades a APIs externes… Si tot això es fa a la petició HTTP principal, la web es torna lenta, apareixen errors 500 i l'usuari acaba desesperat mirant una pantalla en blanc.

La bona notícia és que Laravel porta una infraestructura de cues molt potent i flexible que permet delegar aquests treballs pesats a processos en segon pla, gestionar-los per prioritat, agrupar-los en lots, monitoritzar-los, reintentar-los quan fallen i fins i tot pausar temporalment els workers quan toca manteniment. Anem a veure amb calma (i sense deixar res al tinter) com treure-li tot el suc, incloent com pausar, reprendre i controlar el seu comportament en producció.

Conceptes bàsics: connexions, cues i drivers

A Laravel, abans de ficar-se a pausar res, cal entendre bé la diferència entre connexions de cua i cues en si. En la config/queue.php tens un array connections on defineixes cada backend: database, redis, beanstalkd, sqs, sync, null, failover, rabbitmq (si ho afegeixes), etc.

Cada connexió pot tenir diverses cues lògiques (noms com default, emails, high, low, imports). L'atribut queue de cada connexió indica quina és la cua per defecte on aniran els treballs si no se n'especifica una altra mitjançant onQueue(). Així pots fer coses com:

  • Una cua ràpida per a emails o operacions curtes.
  • Una altra de baixa prioritat per a tasques llargues com processar vídeos o informes grans.
  • Cues segmentades per tipus de tasca: imports, notificaciones, reportes, Etc

Quan llences el worker amb php artisan queue:work, per defecte escolta la cua indicada com defecte a la connexió seleccionada. Si vols prioritzar, pots passar diverses cues separades per comes:

php artisan queue:work redis --queue=high,default,low

Amb això el worker processa primer high , després default i només després low , una cosa crucial quan el sistema va carregat i no vols que un informe de 30 minuts bloquegi els correus d'alta prioritat.

Drivers de cues i requisits previs

Laravel ofereix una API unificada per a diversos drivers de cues , però cadascun té les seves particularitats i dependències. Triar bé el driver és clau abans de parlar de pausar workers.

Driver database

el driver database desa els treballs en una taula SQL (normalment jobs). És fàcil de muntar i perfecte per a projectes petits o entorns de desenvolupament on no vols embolicar-te amb Redis o SQS.

Passos bàsics:

  • Generar la migració: php artisan queue:table (o en versions noves, ve com create_jobs_table per defecte).
  • Executar migracions: php artisan migrate.
  • Configura QUEUE_CONNECTION=database al .env i confirmar a config/queue.php que 'default' => env('QUEUE_CONNECTION','database').

És còmode i prou robust, però amb moltes cues i molt de trànsit es pot tornar un coll d'ampolla , ja que tot passa per la mateixa base de dades relacional.

Driver redis

El driver redis és el cavall de batalla habitual en producció. És ràpid, permet característiques avançades (bloqueig, rate limiting, locks atòmics, Horizon…) i escala molt bé.

Punts importants:

  • Has de configurar la connexió Redis a config/database.php.
  • les opcions serializer y compression de Redis no són compatibles amb el driver de cues.
  • si fas servir Redis Cluster, els noms de les cues han de portar una etiqueta de hash, per exemple {default}, perquè totes les claus d'aquesta cua caiguin al mateix slot.
  • L'opció block_for permet que el worker es bloquegi esperant feines uns segons, en lloc de fer polling continu: estalvia CPU i redueix consultes al servidor Redis.

Per exemple:

'redis' => ,

Si poses block_for = 0, el worker es queda bloquejat indefinidament fins que hi hagi una feina disponible, alguna cosa a tenir en compte si vols que respongui ràpid a senyals com SIGTERM oa ordres de pausa.

Altres drivers: SQS, Beanstalkd, null, failover…

A més de database i redis, Laravel suporta altres sistemes :

  • Amazon SQS: cues gestionades a AWS, amb suport per a FIFO, grups de missatges, deduplicació i configuració avançada de visibilitat. Requereix el SDK aws/aws-sdk-php.
  • Beanstalkd: molt ràpid i senzill, usant el paquet pda/pheanstalk.
  • sync: executa els treballs IMMEDIATAMENT en el mateix procés. Útil en desenvolupament o testing, però en producció pràcticament és com no fer servir cues.
  • nul: descarta els treballs així que es “despatxen”. S'usa per desactivar completament el sistema de cues.
  • migració per error: permet configurar diverses connexions i, si la primària falla, Laravel intenta empènyer el treball a la següent de la llista. Perfecte per a entorns on la alta disponibilitat és crítica.
  Electron JS: Tot allò que Necessites Saber

A nivell de pausar i reprendre workers, la lògica és pràcticament la mateixa independentment del driver, perquè es gestiona des de les comandes d'Artisan i la classe Worker , no des del backend de cua.

Creació de treballs (Jobs) i serialització de models

Un treball a Laravel és simplement una classe que encapsula una tasca que s'executarà a la cua. Normalment es genera amb Artisan i es guarda a app/Jobs.

Per crear-ne un:

php artisan make:job ProcessPodcast

La classe generada implements ShouldQueue i sol fer servir els traits Dispatchable, InteractsWithQueue, Queueable y SerializesModels. El cor està en el mètode handle(), que és el que executa el worker quan li arriba la feina.

Un detall molt potent és la serialització automàtica de models Eloquent . Si al constructor del Job acceptes un model, Laravel no fica l'objecte sencer a la cua, només el seu identificador. Quan el treball es processa, reconstrueix el model des de la base de dades amb les relacions carregades.

Exemple típic (en pseudocodi, per no repetir tal qual):

  • Constructor rep Podcast $podcast.
  • El trait SerializesModels s'encarrega de desar l'ID.
  • En handle(AudioProcessor $processor) fas el treball dur (processar àudio, per exemple).

Si no vols que les relacions d'un model es serialitzin (perquè el payload no sigui enorme), pots fer servir $model->withoutRelations() oa PHP 8 l'atribut # a la propietat promoguda del constructor.

Injecció de dependències en el mètode handle

Un altre avantatge és que pots injectar serveis directament al mètode handle (com si fos un controlador), perquè Laravel utilitza el contenidor de serveis també als Jobs. Per exemple, podeu demanar un AudioProcessor, clients HTTP, repositoris, etc., i el framework s'encarrega de resoldre'ls.

Si necessites un control ultra fi de com es truca al handle, Pots utilitzar Container::bindMethod() en un servei provider i definir tu mateix la lògica d'injecció, però en la majoria de casos no cal complicar-se tant.

Middleware de treballs

Igual que les rutes tenen middleware, els Jobs també poden tenir middleware específics que s'executen abans i després de la feina. Això redueix molt el codi repetitiu en els mètodes handle() i és especialment útil per a:

  • Limitació de taxa (rate limiting) amb Redis.
  • evitar solapaments treballs que toquen el mateix recurs.
  • Regular excepcions per a APIs inestables.
  • Saltar treballs en certes condicions (Skip middleware).

Els middleware se solen col·locar a app/Jobs/Middleware i es tornen des del mètode middleware() del Job. Exemple conceptual:

public function middleware(): array { return ;

Tipus especials de treballs: únics, xifrats i amb bloqueig

Laravel permet marcar certs treballs com únics perquè mai hi hagi dues instàncies iguals a la cua al mateix temps. Això es fa implementant la interfície ShouldBeUnique o ShouldBeUniqueUntilProcessing, i suporta definir una clau uniqueId() i un temps uniqueFor.

Això és ideal per a coses com:

  • Recalcular un índex de cerca d'un producte: només una vegada per producte fins que acabi.
  • Sincronitzacions amb serveis externs que no admeten peticions concurrents per al mateix recurs.

Per sota, Laravel utilitza un lock atòmic de memòria cau (Redis, memcached, database, etc.). També pots triar el driver de cache per a aquest lock amb uniqueVia().

A més, existeix la interfície ShouldBeEncrypted, amb què indiques que el Job complet es xifre abans d'entrar a la cua. Molt útil quan passes dades sensibles i no vols que viatgin clar per Redis, SQS o la base de dades.

Despatxar, retardar i executar treballs en diferents maneres

Quan el teu Job està definit, ho llances amb Job::dispatch() des de controladors, listeners d'esdeveniments, comandes Artisan o fins i tot closures. Els paràmetres que passes a dispatch van directes al constructor del Job.

Variants interessants:

  • dispatchIf() y dispatchUnless() per condicionar la tramesa en una sola línia.
  • delay() perquè el treball no es pugui processar fins a una data/hora concreta.
  • dispatchAfterResponse() o afterResponse() en dispatch() de closures, que difereixen lexecució fins que sha enviat la resposta HTTP, però dins del mateix procés PHP.
  • dispatchSync() per executar el Job de forma síncrona (sense passar per la cua) però reutilitzant la mateixa classe.
  • Connexions especials com deferred o background per executar després de la resposta, en el mateix procés o en un procés PHP nou.

Finalment, pots indicar connexió i cua amb mètodes encadenats onConnection() y onQueue(), ja sigui en despatxar o dins del constructor del Job.

Control fi: reintents, backoff, timeouts i maneig derrors

Una bona part del treball amb cues a Laravel és decidir quantes vegades reintentar una feina , quant de temps esperar entre intents i en quin moment considerar-ho fallit.

  Què és un desenvolupador front-end i què fa?

Opcions disponibles:

  • --tries en queue:work per fixar el màxim d'intents per a tots els treballs d'aquest worker (tret que el Job defineixi el seu propi $tries o tries()).
  • $tries o un mètode tries() a la classe Job per a un control per-Job.
  • retryUntil() per dir: “reintenta el que vulguis fins a aquesta hora, a partir d'aquí, fallo”. Si coincideix amb tries, mana retryUntil.
  • $maxExceptions per tallar quan el problema és per excepcions no controlades repetides.
  • $timeout o --timeout per indicar quants segons es pot executar un Job abans que el worker mati el procés fill.
  • $failOnTimeout per marcar el treball com a fallit en cas de timeout.
  • $backoff el mètode backoff() per definir quant esperar entre reintents, fins i tot amb valors exponencials.

Si un treball llança una excepció sense capturar, Laravel ho allibera de nou a la cua fins a esgotar els intents configurats. Pots controlar-ho manualment amb release($segundos) o fail($exception) quan vulguis marcar adrede una feina com a fallida.

Treballs fallits, taula failed_jobs i poda

Quan un Job esgota els seus intents, passa a considerar-se treball fallit i Laravel ho insereix a la taula failed_jobs (o en DynamoDB si així ho configures). Aquesta taula guarda UUID, connexió, cua, payload del Job i l'excepció que va rebentar.

Ordres útils:

  • php artisan queue:failed per llistar els fallits.
  • php artisan queue:retry <id|all> per reintentar-los.
  • php artisan queue:forget <id> per esborrar-ne un.
  • php artisan queue:flush per esborrar-los tots (amb opció d'hores en versions noves).
  • php artisan queue:prune-failed --hours=48 per podar registres antics automàticament.

Als Jobs pots definir un mètode failed(Throwable $exception) per fer neteja extra: notificar a l'usuari, revertir accions parcials, escriure logs especialitzats, etc. Tingues en compte que es crea una instància nova del Job per trucar a failed(), així que no confiïs en canvis de propietats fets a handle().

Job batching: lots de treballs i combinació amb cadenes

Quan has de llançar centenars o milers de Jobs relacionats (per exemple, importar un CSV gegant per trossos, processar fitxers per lots, netejar dades, etc.), convé fer servir la funcionalitat de batxes de Laravel.

Flux bàsic:

  • Crear la taula job_batches amb php artisan queue:batches-table && php artisan migrate.
  • Marcar els Jobs que formaran part de lots amb el trait Batchable.
  • Utilitza Bus::batch() per enviar un conjunt de Jobs, amb callbacks then, catch y finally.
  • Accedir al lot des de cada Job amb $this->batch() i comprovar si està cancel·lat.
  • Possibilitat d'afegir més Jobs a un lot en marxa amb $this->batch()->add().

Els batxes s'integren de meravella amb cadenes ( chains ): pots tenir cadenes dins d'un lot o lots com a elements d'una cadena més gran. És especialment útil quan vols que diverses cadenes s'executin “en paral·lel” i disparar alguna cosa quan totes s'han completat.

Execució de workers, prioritats i desplegament

Tota la màgia de les cues passa perquè tens un o diversos workers executant la comanda queue:work (o queue:listen, encara que aquest últim és menys eficient). Aquests processos són dimonis de llarga durada que es queden escoltant la cua corresponent.

Opcions clau de queue:work:

  • Connexió: php artisan queue:work redis, queue:work database, Etc
  • Cues: --queue=high,default,low per prioritzar.
  • –onze: processa una sola feina i surt.
  • –max-jobs: processa X treballs i acaba (per reiniciar workers periòdicament i alliberar memòria).
  • –max-time: processa durant N segons i després surt.
  • –sleep: segons d'espera quan no hi ha feines disponibles.
  • –stop-when-empty: buida la cua i es tanca de forma neta (ideal en entorns Docker o jobs puntuals).
  • –timeout: segons de timeout per feina, com comentàvem abans.
  • –Force: per processar treballs fins i tot si l'app està en mode manteniment.

Com que aquests processos són de llarga durada, en producció gairebé sempre es fa servir un monitor de processos com Supervisor (en Linux) per aixecar X workers, reiniciar-los si cauen i gestionar logs. Un típic bloc de configuració de Supervisor per a Laravel defineix:

  • comanda amb el php artisan queue:work ... concret.
  • numprocs per indicar quants workers llançar en paral·lel.
  • Rutes de logs, usuari, reinicis automàtics, etc.

Pausar i reprendre cues a Laravel

Anem al que moltes vegades interessa en manteniment: com pausar workers de cues sense parar-los a matxet i sense deixar jobs a mitges. Laravel ofereix diversos mecanismes, alguns de més nous, altres de clàssics, per controlar això.

Pausar: queue:pause i senyals dinterrupció

En versions recents, Laravel afegeix ordres específiques per pausar i continuar l'execució de workers:

  • php artisan queue:pause: indica al sistema que els workers deixin d'agafar nous treballs, però deixin acabar els que ja estan en curs.
  • php artisan queue:continue: reprèn el processament de nous treballs des d'on es va deixar.
  Càlcul del Variance Inflation Factor VIF a C# i Disseny de Programari

Aquestes comandes treballen enviant senyals als workers a través del mecanisme de cache que Laravel usa internament. Per això és important tenir un driver de memòria cau ben configurat (memcached, redis, database, file…) fins i tot si la teva cua com a tal és una altra cosa.

Important: pausar una cua o un worker no cancel·la ni elimina els treballs ja encolats , simplement evita que se segueixin retirant més treballs de la cua mentre duri la pausa.

Polling d'interrupcions i impacte en el rendiment

Cada vegada que un worker acaba un treball, Laravel consulta a la memòria cau si hi ha senyals de restart, pause o continue . Això té un cost minúscul, però n'hi ha. Si vas al mil·límetre amb el rendiment i saps que no necessitaràs pausar o reiniciar workers des d'ordres, pots desactivar aquest polling trucant a:

Queue::withoutInterruptionPolling();

O fins i tot ajustar propietats estàtiques de Illuminate\Queue\Worker per desactivar tocs concrets ($restartable, $pausable). Això sí, si fas això i després intentes fer servir queue:pause o queue:restart, els workers no se n'assabentaran. És una decisió de disseny que cal pensar bé.

Pausar “a mà” amb Supervisor o Docker

A més de les comandes pròpies de Laravel , en entorns productius moltes vegades es “pausa” de forma indirecta:

  • Aturant el programa a Supervisor (supervisorctl stop laravel-worker:*), que mata o atura els workers.
  • usant –stop-when-empty en desplegaments per deixar que els workers acabin el que hi hagi a la cua i després s'apagui.
  • A Docker, deixant que el contenidor processi amb --stop-when-empty i després s'apagui.

La diferència amb queue:pause és que, en parar completament els processos, deixaràs de processar treballs fins que s'aixequin de nou els workers. Amb pausa interna pots mantenir els processos en memòria, atents a l'ordre continue, una cosa útil en desplegaments roll-back ràpids o manteniments curts.

Transaccions de base de dades i after_commit

Un clàssic: despatxar Jobs dins de transaccions de base de dades. Si no aneu amb compte, el worker pot executar el Job abans que es faci el commit i el model o les dades que esperes encara no estiguin a la base de dades.

Per evitar aquest ball, tens dues maneres:

  • Activar 'after_commit' => true a la configuració de la connexió de cua. Així, qualsevol Job despatxat dins una transacció es posposa internament fins que es confirmi.
  • Usar mètodes per-job afterCommit() o beforeCommit() en despatxar, per forçar el comportament només a Jobs concrets.

Si la transacció es reverteix, els treballs despatxats durant aquesta es rebutgen sense arribar a entrar a la cua, que és just el que sol interessar per mantenir la consistència.

Monitorització, neteja de cues i proves

Quan ja tens cues funcionant de debò, no n'hi ha prou amb llençar Jobs i oblidar-se; convé monitoritzar i provar com es comporta tot.

Eines i ordres útils:

  • queue:clear per buidar una cua específica (SQS, Redis, database).
  • queue:monitor per vigilar el nombre de treballs a certes cues i disparar l'esdeveniment QueueBusy si es passen dun llindar.
  • Esdeveniments de Job com a Queue::before, Queue::after, Queue::looping y Queue::failing per enganxar lògica custom (logs, mètriques, rollbacks, etc.).
  • Fakes en proves usant Queue::fake() y Bus::fake() per comprovar que s'han despatxat Jobs, cadenes o lots sense executar-los de debò.

En tests pots afirmar coses com “s'ha encolat aquest Job X vegades” , “s'ha despatxat una cadena amb aquests Jobs en aquest ordre” o “no s'ha encolat cap Job determinat”, cosa que dóna molta seguretat en fluxos complexos.

Amb tot aquest ecosistema —drivers com Redis o SQS, Jobs ben dissenyats, middleware per a control fi, lots, cadenes, configuració de reintents, workers gestionats per Supervisor i ordres com queue:pause y queue:continue— Laravel et permet dominar el processament en segon pla gairebé al mil·límetre, des del típic enviament de correus fins a arquitectures de cues distribuïdes amb failover, garantint que la teva aplicació segueixi responent ràpid a la capa HTTP mentre a sota es couen feines pesades sense bloquejar l'usuari.

Framework Laravel
Article relacionat:
El Poderós Framework Laravel