Как запускать в фоне обработку (получение) данных. Очереди.

Laravel

Как запускать в фоне обработку (получение) данных. Очереди.

Как создать задание и отправить в очередь, что бы оно обрабатывалось в фоне.

Документация на русском.

https://laravel.su/docs/10.x/queues

1. Создать таблицу в бд

php artisan queue:table

php artisan migrate

2. В файле .env

QUEUE_CONNECTION=database


3. Создать задание

php artisan make:job TestJob

Появится файл app/Jobs/TestJob.php

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

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

protected $data;
/**
* Create a new job instance.
*/
public function __construct($data)
{
$this->data = $data;
}

/**
* Execute the job.
*/
public function handle(): void
{
for ($i=0;$i<1000000;$i++) {
for ($j=0;$j<1000;$j++) {
}
}

info('Задание выполнено');
info($this->data);
}
}


Здесь в handle - то что надо выполнить. $data - данные, переданные оттуда, где задание было отправлено в очередь.

4. В контроллере отправить задание в очередь

use App\Jobs\TestJob;
Route::get('/queue-test', function (Request $request) {
TestJob::dispatch('Hello');

//Или так
// $job = new TestJob('Hello');
// dispatch($job);

return 'Hello';
});


5. Запустить в консоли команду

php artisan queue:work

Пока она работает, задания из очереди будут выполнятся. Изменения кода в заданиях при запуске этой команды не будут учитываться. Только после перезапуска команды.

Для локальной разработки нужно использовать

php artisan queue:listen

Эта команда будет отслеживать изменения кода в заданиях и выполнять задания уже с измененным кодом.


На сервере для стабильной работы queue:work необходимо запустить через супервизор.

Для этого

1. Создать файл laravel-worker.conf в директории etc/supervisor/conf.d 

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /home/den/Документы/dailygrow/test_task_integrate_with_b24/back/artisan queue:work database --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=den
numprocs=4
redirect_stderr=true
stdout_logfile=/home/den/Документы/dailygrow/test_task_integrate_with_b24/back/worker.log
stopwaitsecs=3600


здесь command - команда, которую надо запустить. Примечание: после queue:work у меня стоит слово database. Это означает, что queue:work запустить с драйвером database. В документации в примере стоит sqs, это означает запустить с драйвером sqs. Для sqs нужна зависимость aws/aws-sdk-php ~3.0 и ключи доступа из аккаунта амазон. Если не указывать, то должно запуститься с драйвером по дефолту

stdout_logfile - путь, где будет создан worker.log

2. запустить

sudo supervisorctl reread

sudo supervisorctl update

sudo supervisorctl start laravel-worker:*

3. После обновления файлов кода надо перезапустить.

sudo supervisorctl stop laravel-worker:*


Примечание:

Если создать уникальное задание (задание с уникальным ключом), то если его очистить командой php artisan queue:clear, или вручную удалить из таблицы jobs, то оно уже при выполнении dispatch оно не попадет в таблицу jobs и не запуститься. Решением является почистить кэш командой php artisan cache:clear.