Laravel Queue (Kuyruk)
Laravel ile yapılan projelerde bazen işlemleri kuyruklamak gerekebiliyor. Yapılacak işlemin sonucunu response dönmek gerekmiyorsa ve requests olağandan fazla ise işlemleri kuyruklamak gelen tüm request’leri işleyebileceğiniz anlamına gelir. Bir yandan gelen request’leri kuyruğa atarsınız diğer bir yandan ise sıra ile işlersiniz. Veriyi işlemek için yazdığınız kodu (Worker) çoklu şekilde çalıştırarak veri işleme hızınızı da arrtırabilirsiniz.
Queue işlemi basitçe şöyle çalışıyor. bir Job oluşturuyorsunuz. yapılacak işlemleri redis queue atıyorsunuz. artisan work
komutu ile queue ve Job‘u belirterek verileri sırası ile işlemeye başlıyorsunuz.
İşe ilk olarak .env
dosyasında queue için ne kullanılacağını belirterek başlayalım. Bu kısım oldukça önemli ve redis kullanılması öneriliyor.
QUEUE_CONNECTION=redis
Laravel tarafından redis‘in kullanılabilmesi için predis‘i composer ile kurun.
composer require predis/predis
Şimdi ise işlemleri yapacak olan Job‘un oluşturun.
php artisan make:job Test
Yukarıdaki komut app/Jobs/Test.php
dosyasını oluşturur. handle()
fonksiyonu worker tarafından çalıştırılacak kod blogunun yazıldığı fonksiyondur. Örnek olması açışından storage/app/
içinde random txt dosyası oluşturan ufak bir kod yazarak devam edelim.
public function handle()
{
Storage::put(Str::random().'.txt', 'job test');
}
Queue‘ye iş atamamız gerekiyor ben bunun için HomeController@home
action’ını kullanacağım.
public function home()
{
$job = new Test();
$queue = 'fatih';
dispatch($job)->onQueue($queue);
}
Eğer işleme gecikme koymak delay()
fonksiyonunu kullanabilirsiniz.
public function home()
{
$job = new Test();
$queue = 'fatih';
dispatch($job)
->onQueue($queue)
->delay(now()->addMinutes(10));
}
HomeController@home
action’ını çalıştırdığınızda. Redis‘e basit bir iş eklemiş olacaksınız. Eğer Redis-cli içinde key * kodunu çalıştırırsanız
1) "laravel_database_queues:fatih:notify" 2) "laravel_database_queues:fatih"
Şeklinde bir çıktı almanız gerek. Queue‘ye eklediğiniz bu bu işi işlemek içinse artisan work
ile worker çalıştırmak gerekiyor.
php artisan queue:work
Yukarıda ki kod tüm worker‘ları çalıştırır. Oysa biz worker‘ları kuyruk kuyruk ayırarak çalıştırmayı tercih ederiz. Bu şekilde hem yönetmesi daha kolay olur hemde bir worker‘da olan sorun diğerlerini etkilemez. Bunun için aşağıdaki gibi queue ismi vererek çalıştırmakta fayda var.
php artisan queue:work --queue=fatih
İşlenecek verilerin birisinde sorun olursa worker‘ı loop’a girmekten kurtarmak için tries
yani deneme limiti vermemiz gerekiyor.
php artisan queue:work --queue=fatih --tries=3
Artık storage/app/
içinde üretilen .txt dosyasını görebilirsiniz. Buraya kadar her şey tamam ama Queue iş atarken iş için data göndermek de gerekecektir. Onun için aslında Php class’a parametre göndereceğiz. Yani job
classının __construct()
fonksiyonunu kullanacağız.
class Test implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $data = null;
public function __construct($data)
{
$this->data = $data;
}
public function handle()
{
Storage::put(Str::random().'.txt', $this->data);
}
}
app/Jobs/Test.php
dosyasının içeriğini yukarıdaki gibi hazırladıktan sonra. dispatch ettiğimiz HomeController@home
action’dan parametre gönderebiliriz.
public function home()
{
$job = new Test('data');
$queue = 'fatih';
dispatch($job)->onQueue($queue);
}
Artık üretilen .txt
dosyası içerisinde data yazacaktır.
Notlar
- Job içerisinde yapılan değişiklikler worker tarafından algılanmaz. Bunun için çalışan workerları durdurup yeniden çalıştırmak gerekir.
- Worker’ları yönetmek için Supervisor kullanmanızı tavsiye ederim.