From bdaf96941f08b647b828cc41e1cde93527399597 Mon Sep 17 00:00:00 2001 From: Omar Adel Brikaa Date: Sat, 2 Sep 2023 16:38:09 +0300 Subject: [PATCH] Use flock to avoid race conditions on views-count file (#67) --- src/CounterFileRepository.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/CounterFileRepository.php b/src/CounterFileRepository.php index c634a2b..eac2871 100644 --- a/src/CounterFileRepository.php +++ b/src/CounterFileRepository.php @@ -57,8 +57,18 @@ final class CounterFileRepository implements private function incrementViewsCount(Username $username): void { $counterFilePath = $this->getCounterFilePath($username); + // Need to open the file in "c" mode to avoid truncating before acquiring the lock and before reading + $counterFile = fopen($counterFilePath, "c"); - file_put_contents($counterFilePath, $this->getViewsCountByUsername($username) + 1); + // Acquire an exclusive lock to avoid two requests causing a write at the same time + flock($counterFile, LOCK_EX); + $incremented = $this->getViewsCountByUsername($username) + 1; + ftruncate($counterFile, 0); + fwrite($counterFile, "$incremented\n"); + fflush($counterFile); + // Release the exclusive lock + flock($counterFile, LOCK_UN); + fclose($counterFile); } private function getViewsFilePath(Username $username): string