Salta al contenuto principale
Laravel

Laravel Jobs e Queues: Guida Completa all'Elaborazione Asincrona

Impara a usare Jobs e Queues in Laravel per migliorare le performance e l'esperienza utente.

Giovanni D'Ippolito
3 min

Autore

Giovanni D'Ippolito

Pubblicato

19 November 2025

Tempo di lettura

3 minuti

Tags

#Laravel #Queues #Jobs #Performance #Async

Perché Usare le Queue?

Le queue permettono di differire l'esecuzione di task pesanti, migliorando il tempo di risposta dell'applicazione.

Operazioni come invio email, generazione PDF, elaborazione immagini dovrebbero sempre essere eseguite in background.

Configurazione Base

Configura il driver delle queue in .env:

# Development
QUEUE_CONNECTION=database

# Production
QUEUE_CONNECTION=redis

Crea la tabella per le queue:

php artisan queue:table
php artisan migrate

Creare un Job

Genera un nuovo job:

php artisan make:job SendWelcomeEmail
<?php
namespace App\Jobs;

use App\Models\User;
use App\Mail\WelcomeMail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;

class SendWelcomeEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        public User $user
    ) {}

    public function handle(): void
    {
        Mail::to($this->user->email)
            ->send(new WelcomeMail($this->user));
    }

    // Gestione errori
    public function failed(\Throwable $exception): void
    {
        // Log errore, notifica admin, etc.
        logger()->error('Failed to send welcome email', [
            'user_id' => $this->user->id,
            'error' => $exception->getMessage(),
        ]);
    }
}
?>

Dispatch del Job

Diversi modi per accodare un job:

<?php
use App\Jobs\SendWelcomeEmail;

// Dispatch immediato
SendWelcomeEmail::dispatch($user);

// Dispatch con delay
SendWelcomeEmail::dispatch($user)
    ->delay(now()->addMinutes(5));

// Dispatch su una queue specifica
SendWelcomeEmail::dispatch($user)
    ->onQueue('emails');

// Dispatch condizionale
SendWelcomeEmail::dispatchIf(
    $user->wants_emails,
    $user
);

SendWelcomeEmail::dispatchUnless(
    $user->unsubscribed,
    $user
);

// Chain di jobs
SendWelcomeEmail::withChain([
    new SendOnboardingEmail($user),
    new AssignDefaultSettings($user),
])->dispatch($user);
?>

Job con Retry e Timeout

Configura retry automatici e timeout:

<?php
namespace App\Jobs;

class ProcessPayment implements ShouldQueue
{
    // Numero di tentativi
    public $tries = 3;

    // Timeout in secondi
    public $timeout = 120;

    // Delay tra retry (in secondi)
    public $backoff = [10, 30, 60];

    public function handle(): void
    {
        // Logica pagamento che potrebbe fallire
        // Verrà ritentata automaticamente
    }

    // Determina se ritentare in base all'eccezione
    public function shouldRetry(\Throwable $exception): bool
    {
        return $exception instanceof TemporaryPaymentException;
    }
}
?>
Imposta sempre un timeout per evitare che job bloccati consumino risorse indefinitamente.

Batch Jobs

Esegui più jobs in batch con tracking:

<?php
use Illuminate\Bus\Batch;
use Illuminate\Support\Facades\Bus;

$users = User::where('active', true)->get();

$jobs = $users->map(fn ($user) => new SendNewsletterEmail($user));

$batch = Bus::batch($jobs)
    ->name('Monthly Newsletter')
    ->then(function (Batch $batch) {
        // Tutti i job sono completati
        logger()->info('Newsletter sent to all users');
    })
    ->catch(function (Batch $batch, \Throwable $e) {
        // Il primo job è fallito
        logger()->error('Newsletter batch failed');
    })
    ->finally(function (Batch $batch) {
        // Il batch è finito (successo o fallimento)
        logger()->info('Newsletter batch finished');
    })
    ->dispatch();

// Controlla il progresso
$batch = Bus::findBatch($batch->id);
$progress = $batch->progress(); // Percentuale completamento
?>

Worker Configuration

Avvia il queue worker:

# Worker base
php artisan queue:work

# Worker con opzioni
php artisan queue:work redis \
    --queue=high,default,low \
    --tries=3 \
    --timeout=60 \
    --max-jobs=1000 \
    --max-time=3600

# Con supervisord per production
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /path/to/artisan queue:work --sleep=3 --tries=3
autostart=true
autorestart=true
numprocs=4
user=www-data
In production, usa sempre un process monitor come Supervisor per gestire i worker delle queue!

Condividi questo articolo

Articoli Correlati

Laravel

Laravel Eloquent: Query Optimization per Performance Migliori

Tecniche avanzate per ottimizzare le query Eloquent e migliorare le performance della tua applicazio...

03 Nov 2025 2 min
Leggi di più →
Laravel

Laravel Service Container: Dependency Injection Made Easy

Comprendi il Service Container di Laravel e come sfruttare la Dependency Injection per codice più te...

11 Nov 2025 3 min
Leggi di più →
Laravel

Laravel Testing: TDD con Pest PHP

Impara il Test-Driven Development con Pest, il framework di testing moderno per PHP.

27 Nov 2025 1 min
Leggi di più →

Rimani Aggiornato

Iscriviti alla nostra newsletter per ricevere gli ultimi articoli e novità direttamente nella tua casella di posta.