如何在Laravel 4.2中编写多进程队列(已配置主管)



我有一个网站,用户可以在其中以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,尚无法升级。我想避免两个进程访问数据库中的同一表行的情况。如何在队列类中避免这种情况?

假设您在队列中推送作业,如下所示:

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

作业触发方法使用$data参数传递特定值,以确保作业执行特定操作。现在在导出CSV作业中,在触发方法中:

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

最新更新