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