“Poison Pill” Felaketi
Smart Tech Devs’teki sağlam B2B SaaS platformlarında, ağır görevlerin (PDF raporları oluşturma veya webhook göndermek gibi) arka planda Redis kuyruklarına aktarılması zorunludur. Ancak, bir üçüncü parti API çökerse veya bir kullanıcı hatalı bir e-posta adresi gönderirse ne olur? Görev başarısız olur.
Kuyruklarınızı dikkatlice tasarlamazsanız, Poison Pill senaryosuyla karşılaşırsınız. Çalışan görevi denemeye çalışır, çökme yaşar ve görev kuyrukta geri itilerek üst üste biner. Çalışan tekrar alır, yine çökme yaşar. Çalışanınız, aynı görevin yeniden çalıştırılmasıyla sonsuz bir döngüye girer ve arka planda bekleyen binlerce sağlıklı görevi tamamen bloke eder. Asenkron hatlarınızı korumak için, katı yeniden deneme sınırları ve Dead Letter Queue (DLQ) uygulamanız şarttır.
Çözüm: Başarısız Görevleri Karantina Altına Alma
Dead Letter Queue, maksimum yeniden deneme sınırını aşan görevlerin kalıcı olarak karantinaya alındığı özel bir depolama alanıdır (Laravel’de genellikle failed_jobs veritabanı tablosudur).
Bir görev DLQ’ya taşındığında, çalışan bu görevi aktif Redis kuyruğundan çıkartır ve sonraki sağlıklı göreve geçer. Bu, arka plan işlemenizin asla durmamasını sağlar. Daha sonra, mühendislik ekibiniz DLQ’yi inceleyebilir, temel hatayı düzeltebilir ve karantinaya alınmış görevleri aktif hattınıza tekrar “oynatabilir”.
Adım 1: Görev Sınırlarını Tasarlamak
Her arka plan görevinde fiziksel sınırları açıkça tanımlamanız gerekmektedir. Bunu $tries (toplam deneme sayısı) ve $backoff (denemeler arasında bekleme süresi) ayarları ile yaparız.
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Throwable;
class GenerateEnterpriseReport implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
// 1. SINIRLAR: Bu görevi DLQ'ya geçmeden önce maksimum 3 kez deneyin
public int $tries = 3;
// 2. BEKLEME: Yeniden denemeden önce 10 saniye, ardından 30 saniye, ardından 60 saniye bekleyin
public array $backoff = [10, 30, 60];
public function handle(): void
{
// Ağırlıklı PDF oluşturma mantığını burada yürütün...
}
// 3. ✅ KURULUŞ PATERNI: DLQ Bağlantısı
// Bu yöntem, görev tüm denemeleri tükettiğinde ve resmi olarak başarısız olduğunda ateşlenir.
public function failed(Throwable $exception): void
{
// Slack/Discord üzerinden DevOps ekibinizi, bir görevin karantinaya alındığı konusunda bilgilendirin
app('telemetry.service')->sendSlackAlert(
"DLQ Uyarısı: Kurumsal Rapor oluşturulamadı.",
['error' => $exception->getMessage()]
);
}
}
Adım 2: DLQ’yı İzleme ve Yeniden Oynatma
Laravel, DLQ’yı php artisan queue:failed komutu ile yönetir. Bir satıcı API’si bir saatliğine çevrimdışı kalırsa, yüzlerce webhook görevi DLQ’ya taşınır. Satıcı çevrimiçi döndüğünde, bu webhook’ları tekrar manuel olarak tetiklemek zorunda değilsiniz. Sadece karantinaya alınmış görevleri yeniden oynatmalısınız.
# Karantina tablosunda bekleyen tüm zehirli görevleri görüntüleyin
php artisan queue:failed
# UUID'si ile belirli bir görevi yeniden deneyin
php artisan queue:retry 5c85b1a8-7013-4...
# veya, bir sistem kesintisi çözüldükten sonra tüm karantinaya alınmış görevleri birden yeniden deneyin!
php artisan queue:retry all
Mühendislik ROI’si
Katı yeniden deneme sınırlarını uygulayarak ve başarısız görevleri DLQ’ya yönlendirerek, izole bir veri hatasının sistematik bir kuyruk tıkanmasına neden olamayacağını garanti edersiniz. Uygulamanız kendiliğinden temizlenir, bu sayede yüksek öncelikli görevler (şifre sıfırlama gibi) başarısız analiz görevleri tarafından asla geciktirilmezken, başarısız yük ayrıca kolay manuel kurtarma için saklanır.
Kaynak: Orijinal Makale


