Как писать многопроцессные очереди в Laravel 4.2 (с настроенным супервизором)? - PullRequest
2 голосов
/ 01 апреля 2019

У меня есть веб-сайт, где пользователи могут экспортировать отчеты в формате CSV. Когда они нажимают кнопку «Экспорт», я добавляю новую строку в таблицу базы данных, указывающую на наличие нового запроса на создание отчета.

Я хочу установить доступ к базе данных для 2 процессов, потому что 1 недостаточно. Моя текущая конфигурация супервизора следующая:

    [program:csv_export]
    command=php /var/www/mywebsite.com/artisan queue:listen --tries=1 --timeout=3000 --queue=csv_export
    numprocs=2
    process_name=csv_export_%(process_num)02d
    directory=/var/www/mywebsite.com/
    stdout_logfile=/var/log/mywebsite/csv_export.log
    autostart=true
    autorestart=true
    stopsignal=KILL
    loglevel=debug
    redirect_stderr=true

Моя очередь fire() код выглядит так:

public function fire($job, $data){
    $reports = \CSVReport::where('status', '=', CSVReport::CSVNEW)->take(1)->get();

    foreach ($reports as $key => $value){
        // prepare data and file
        $value->status = 'done';
        $value->save();
    }

    $job->delete();
}

Я использую Laravel 4.2, обновление пока невозможно. Я хочу избежать ситуации, когда два процесса будут обращаться к одной и той же строке таблицы в базе данных. Как я могу избежать этого в моем классе очереди?

1 Ответ

1 голос
/ 01 апреля 2019

Предположим, вы помещаете свое задание в очередь, например:

$csv = new CSVReport;
// $csv->... = ...;
$csv->save();
Queue::push('ExportCSV', array('csvID' => $csv->id));

Метод запуска задания использует параметр $data для передачи определенных значений, чтобы убедиться, что задание выполняет что-то конкретное.Теперь в задании ExportCSV, в пожарном методе:

public function fire($job, $data){
    $report = \CSVReport::find($data['csvID']);

    // prepare data and file
    $report->status = 'done';
    $report->save();

    $job->delete();
}

Таким образом, каждое задание будет иметь идентификатор CSVReport, сериализованный в его $ data, и в то время, когда супервизор выполнит его, задание будет обрабатывать только свой определенный CVSReportИдентификатор в базе данных.

Вы все еще можете проверить статус выполненного, если какой-либо случай может обработать их вне очереди:

public function fire($job, $data){
    $report = \CSVReport::where('status', CSVReport::CSVNEW)->where('id', $data['csvID'])->first();

    // prepare data and file
    if($report) {
        $report->status = 'done';
        $report->save();
    }

    $job->delete();
}
...