Bir müşteride sipariş onaylandığında 12 farklı işlem tetikleniyordu: fatura oluşturma, e-posta gönderme, stok düşme, muhasebe kaydı, kargo API, SMS... Tüm bunlar HTTP isteği içinde yapılıyordu ve sayfa yüklemesi 8-12 saniye sürüyordu. Laravel Queue sistemi devreye girdikten sonra sipariş yanıt süresi 200 milisaniyeye indi. Tüm bu işlemler arka planda gerçekleşiyor.

Temel Kavramlar

  • Job: Arka planda yapılacak iş birimi (PHP sınıfı)
  • Queue: Job'ların sıralandığı kuyruk (Redis, database, SQS)
  • Worker: Queue'yu dinleyip job'ları çalıştıran süreç
  • Horizon: Redis queue worker'larını yönetmek için Laravel'in dashboard'u

Job Oluşturma

php artisan make:job SendOrderConfirmationEmail

// app/Jobs/SendOrderConfirmationEmail.php
class SendOrderConfirmationEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public int $tries = 3;
    public int $backoff = 60;       // retry arası 60 sn
    public int $timeout = 120;      // max çalışma süresi

    public function __construct(
        private readonly Order $order
    ) {}

    public function handle(MailService $mailer): void
    {
        $mailer->sendOrderConfirmation($this->order);
    }

    public function failed(\Throwable $e): void
    {
        Log::error('Sipariş maili gönderilemedi', [
            'order_id' => $this->order->id,
            'error'    => $e->getMessage(),
        ]);
        // Slack bildirimi, admin paneline kayıt vb.
    }
}

// Dispatch etmek
SendOrderConfirmationEmail::dispatch($order);
SendOrderConfirmationEmail::dispatch($order)->onQueue('emails');
SendOrderConfirmationEmail::dispatch($order)->delay(now()->addMinutes(5));

Queue Önceliklendirme

# Worker öncelik sırasına göre tüketir
php artisan queue:work --queue=critical,high,default,low

# Job dispatch ederken queue belirt
ProcessPayment::dispatch($order)->onQueue('critical');
SendWelcomeEmail::dispatch($user)->onQueue('low');

Horizon Kurulumu ve Konfigürasyonu

composer require laravel/horizon
php artisan horizon:install

// config/horizon.php
'environments' => [
    'production' => [
        'supervisor-1' => [
            'connection' => 'redis',
            'queue' => ['critical', 'high', 'default', 'low'],
            'balance' => 'auto',
            'autoScalingStrategy' => 'time',
            'minProcesses' => 1,
            'maxProcesses' => 10,
            'balanceMaxShift' => 1,
            'balanceCooldown' => 3,
            'tries' => 3,
            'timeout' => 120,
        ],
    ],
],

Supervisor ile Production'da Çalıştırma

# /etc/supervisor/conf.d/horizon.conf
[program:horizon]
process_name=%(program_name)s
command=php /var/www/html/artisan horizon
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/log/horizon.log
stopwaitsecs=3600

Failed Job Yönetimi

# Failed job'ları listele
php artisan queue:failed

# Belirli bir job'u yeniden dene
php artisan queue:retry {id}

# Tüm failed job'ları yeniden dene
php artisan queue:retry all

# Failed job'ları temizle
php artisan queue:flush

Batch Jobs ile Paralel İşleme

$batch = Bus::batch([
    new ProcessInvoice($order),
    new UpdateInventory($order),
    new NotifyWarehouse($order),
])->then(function (Batch $batch) {
    SendOrderReadyNotification::dispatch($batch->options['order_id']);
})->catch(function (Batch $batch, \Throwable $e) {
    Log::error('Batch başarısız', ['batch_id' => $batch->id]);
})->dispatch();