如何在Laravel 4.2中编写多进程队列(配置了超级用户)?

时间:2019-04-01 13:31:52

标签: php laravel supervisord laravel-4.2 laravel-queue

我有一个网站,用户可以在其中导出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 个答案:

答案 0 :(得分:1)

假设您将Job推入队列:

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

Job fire方法使用$data参数传递特定值,以确保Job执行特定操作。现在,在ExportCSV作业中,采用开火方法:

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

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

    $job->delete();
}

这样,每个作业将在其$ data中序列化CSVReport ID,在主管执行该操作时,该作业将仅在数据库中处理其特定的CVSReport ID。

无论何种情况,您仍可以检查状态是否完成:

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();
}