Merhabalar,

Bu yazıda Laravel'de kuyruk (queue) kullanımından bahsedeceğim. Senaryomuz şu şekilde olacak. Kullanıcının bilgilerini alıp MERNIS kontrolünden geçiren ve bilgilerin doğruluğuna yönelik kullanıcıya e-posta gönderen ufak bir API fonksiyonu yazacağız. Böylece kullanıcı MERNIS kontrolünün tamamlanması ve e-posta gönderilmesi işlemlerinin bitmesini beklemeden cevabı direkt görmüş olacak. Örnek projeyi Github üzerinden paylaştım. Oradan da indirip inceleyebilirsiniz.

Örnek Proje Linki

İlk olarak komut satırında masaüstü dizinine gelerek aşağıdaki komutu yazıp yeni bir Laravel projesi oluşturuyorum:

composer create-project --prefer-dist laravel/laravel queue

Sonrasında Xampp yardımıyla yerelde bir veritabanı oluşturuyorum. Proje kök dizinindeki .env dosyasını açarak veritabanı bilgilerini aşağıdaki gibi düzenliyorum:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=queue
DB_USERNAME=root
DB_PASSWORD=

defaultStringLength hatasıyla karşılaşmamak için app/Providers/AppServiceProvider.php dosyasını açarak boot() fonksiyonunu düzenliyorum:

public function boot()
{
    Schema::defaultStringLength(191);
}

Şimdi kuyrukta yapılacak işlem için bir job oluşturuyorum.

php artisan make:job SendMernis

Gelen isteği karşılayacak olan fonksiyonum için bir controller oluşturuyorum.

php artisan make:controller UserController

api.php dosyasında istek için route belirtiyorum.

Route::post('register', '[email protected]');

register fonksiyonum tam olarak şu şekilde olacak:

public function register()
{
    $user['name'] = request()->name;
    $user['surname'] = request()->surname;
    $user['birth_year'] = request()->birth_year;
    $user['nationality_id'] = request()->nationality_id;
    $user['email'] = request()->email;
    $this->dispatch(new SendMernis($user));
    return response()->json([
        'message' => 'Bilgileriniz Mernis kontrolünden geçirilerek tarafınıza e-posta gönderilecektir.'
    ], 200);
}

Bu fonksiyonda kullanıcıdan gelen ad, soyad, doğum yılı, TC kimlik numarası ve e-posta adresi bilgilerini kuyruktaki fonksiyonumuza gönderdik ve kullanıcıya direkt olarak bir mesaj döndük.

resources/views klasörü içerisinde email adında bir klasör açıyorum. mernis_control adında bir blade dosyası açarak içeriğini şu şekilde dolduruyorum.

<html>
<head>
  <meta charset="utf-8">
  <title>Mernis Kontrolü</title>
</head>
<body>
  <div>
    {{ $content }}
  </div>
</body>
</html>

SendMernis.php dosyasında kuyruğa gelen işlemi karşılayan kısım olan handle ı şu şekilde dolduruyoruz:

public function handle()
{
  $informations = array(
    "name" => $this->user['name'],
    "surname" => $this->user['surname'],
    "birth_year" => $this->user['birth_year'],
    "nationality_id" => $this->user['nationality_id']
  );
  $response = $this->mernis_control($informations);
  $content = $response == "true" ? 'Bilgileriniz doğru.' : 'Bilgileriniz yanlış.';
  $data = array(
    'content' => $content
  );
  $this->send_mail('email.mernis_control', $data, $this->user['email'], 'Mernis Kontrolü');
}

mernis_control fonksiyonumuz şu şekilde:

public function mernis_control($informations)
{
  $send = '<?xml version="1.0" encoding="utf-8"?>
     <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
          <soap:Body>
            <TCKimlikNoDogrula xmlns="http://tckimlik.nvi.gov.tr/WS">
              <TCKimlikNo>'.$informations["nationality_id"].'</TCKimlikNo>
              <Ad>'.$informations["name"].'</Ad>
              <Soyad>'.$informations["surname"].'</Soyad>
              <DogumYili>'.$informations["birth_year"].'</DogumYili>
            </TCKimlikNoDogrula>
          </soap:Body>
     </soap:Envelope>';
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL,      "https://tckimlik.nvi.gov.tr/Service/KPSPublic.asmx");
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_POST,     true);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($ch, CURLOPT_HEADER,    false);
  curl_setopt($ch, CURLOPT_POSTFIELDS,  $send);
  curl_setopt($ch, CURLOPT_HTTPHEADER,  array(
    'POST /Service/KPSPublic.asmx HTTP/1.1',
    'Host: tckimlik.nvi.gov.tr',
    'Content-Type: text/xml; charset=utf-8',
    'SOAPAction: "http://tckimlik.nvi.gov.tr/WS/TCKimlikNoDogrula"',
    'Content-Length: '.strlen($send)
  ));
  $response = curl_exec($ch);
  curl_close($ch);
  return strip_tags($response);
}

send_mail fonksiyonumuz şu şekilde:

public function send_mail($template, $data, $to, $subject)
{
  Mail::send($template, $data, function ($message) use ($to, $subject) {
    $message->to($to)->subject($subject);
  });
}

Şimdi kuyruk işlemlerini veritabanında tutan jobs tablosunu oluşturmak için şu komutu yazıyoruz:

php artisan queue:table

Kuyruk işlemlerinin veritabanındaki tablodan işlenmesi için .env dosyasında şöyle bir düzenleme yapıyoruz:

QUEUE_DRIVER=database

Şimdi de veritabanı tablolarını oluşturmak için şu komutu yazıyoruz:

php artisan migrate

.env dosyasında mail ayarlarını düzenliyoruz:

MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=f901938115ba94
MAIL_PASSWORD=4e8d739fbd82a1
MAIL_ENCRYPTION=null

Artık herşey hazır olduğuna göre projemizi çalıştırıp sonuca ulaşalım:

php artisan serve
php artisan queue:work (kuyruktaki işlemleri dinlemek için)

Postman'i açıp http://localhost:8000/api/register linkine aşağıdaki şekilde gerekli bilgilerle POST isteği yapıyoruz ve sonucu görüyoruz.

Evet yerel ortamda herşey gayet güzel çalışıyor. Ancak projemizi sunucuya attığımız zaman php artisan queue:work komutunun sürekli çalışıyor olması gerekecek. Bunun içinde supervisor paketini kullanacağız. Eğer sunucumuzda supervisor yoksa şu yazıdan kurulumu yapabilirsiniz: CentOS 7 kurulumu ve kullanımı


Sonrasında /etc dizinindeki supervisord.conf dosyasını nano ile açıyoruz:

nano /etc/supervisord.conf

Ve içeriğine şu satırları ekliyoruz:

[program:laravel-worker]
command=/usr/bin/php /var/www/vhosts/queue/artisan queue:work --sleep=3 --tries=3
process_name=%(program_name)s_%(process_num)02d
numprocs=8
priority=999
autostart=true
autorestart=true
startsecs=0
startretries=3
user=apache
redirect_stderr=true
stdout_logfile=/var/www/vhosts/queue/storage/logs/worker.log

Supervisor servisini durdurup başlatarak işlemi bitiriyoruz:

systemctl stop supervisord
systemctl start supervisord


Umarım yararlı olmuştur. 

İyi çalışmalar.