メソッドprocessReport
は、同じ引数で並行して呼び出すことができます。processReport
ただし、2 つのプロセスが同じ $reportId で同時に呼び出した場合、処理は 1 回だけ実行する必要があります。この並行性の問題を解決するために、ヘルパー メソッドisLocked
とlock
を作成しましたunlock
。lock
$reportId の一時ファイルを作成します。isLocked
一時ファイルが存在するかどうかを確認します。ファイルが存在する場合、処理は行われません。しかし、問題は、2 つの並列プロセスprocessReport
が同じ $reportId で同時に呼び出されることです。この戦略が機能せず、処理が 2 回行われることがあります (これは明らかに、遅すぎるファイルシステムを使用しているために発生します)。プロセスはメモリを共有しないため、この並行性の問題を解決する方法がわかりません。同じ $reportId を 2 回処理しないようにする方法はありますか?
private function getLockFileName($reportId) {
return sprintf('%s/%s.lock', sys_get_temp_dir(), $reportId);
}
private function isLocked($reportId) {
return file_exists($this->getLockFileName($reportId));
}
private function lock($reportId) {
touch($this->getLockFileName($reportId));
}
private function unlock($reportId) {
unlink($this->getLockFileName($reportId));
}
public function processReport($reportId) {
if ($this->isLocked($reportId)) return;
$this->lock($reportId);
// processing should be done only once for the same $reportId
$this->unlock($reportId);
}