From d82a380d17072800cf1c5bd875235ee116904b11 Mon Sep 17 00:00:00 2001 From: Neil Carlo Sucuangco Date: Thu, 23 Oct 2025 20:25:59 +0800 Subject: [PATCH 1/6] Use separate lock directory to prevent key collisions in file cache --- config/cache.php | 2 +- src/Illuminate/Cache/FileStore.php | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/config/cache.php b/config/cache.php index 8c603805ac76..a9daa1f757b9 100644 --- a/config/cache.php +++ b/config/cache.php @@ -55,7 +55,7 @@ 'file' => [ 'driver' => 'file', 'path' => storage_path('framework/cache/data'), - 'lock_path' => storage_path('framework/cache/data'), + 'lock_path' => storage_path('framework/cache/locks'), ], 'memcached' => [ diff --git a/src/Illuminate/Cache/FileStore.php b/src/Illuminate/Cache/FileStore.php index d445f5fc7c23..9eeebebb0fff 100755 --- a/src/Illuminate/Cache/FileStore.php +++ b/src/Illuminate/Cache/FileStore.php @@ -216,10 +216,12 @@ public function forever($key, $value) */ public function lock($name, $seconds = 0, $owner = null) { - $this->ensureCacheDirectoryExists($this->lockDirectory ?? $this->directory); + $locksDir = $this->lockDirectory ?? ($this->directory.'/locks'); + + $this->ensureCacheDirectoryExists($locksDir); return new FileLock( - new static($this->files, $this->lockDirectory ?? $this->directory, $this->filePermission), + new static($this->files, $locksDir, $this->filePermission), $name, $seconds, $owner From 1a987b49d1d8a09cc6fa577cca74e3f469046496 Mon Sep 17 00:00:00 2001 From: Neil Carlo Sucuangco Date: Thu, 23 Oct 2025 22:18:09 +0800 Subject: [PATCH 2/6] Update FileCacheLockTest.php --- tests/Integration/Cache/FileCacheLockTest.php | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/Integration/Cache/FileCacheLockTest.php b/tests/Integration/Cache/FileCacheLockTest.php index 575f1220b852..23a4bbde1da9 100644 --- a/tests/Integration/Cache/FileCacheLockTest.php +++ b/tests/Integration/Cache/FileCacheLockTest.php @@ -8,6 +8,7 @@ use Illuminate\Support\Sleep; use Orchestra\Testbench\Attributes\WithConfig; use Orchestra\Testbench\TestCase; +use Throwable; #[WithConfig('cache.default', 'file')] class FileCacheLockTest extends TestCase @@ -16,6 +17,9 @@ protected function setUp(): void { parent::setUp(); + $this->app['config']->set('cache.default', 'file'); + $this->app['config']->set('cache.stores.file.lock_path', storage_path('framework/cache/locks')); + // flush lock from previous tests Cache::lock('foo')->forceRelease(); } @@ -100,6 +104,18 @@ public function testOwnerStatusCanBeCheckedAfterRestoringLock() $this->assertTrue($secondLock->isOwnedByCurrentProcess()); } + public function testCacheRememberReturnsValueWhenLockWithSameKeyExists() + { + $lock = Cache::lock('my-key', 5); + $this->assertTrue($lock->get()); + + $value = Cache::remember('my-key', 60, fn () => 'expected-value'); + + $this->assertSame('expected-value', $value); + + $lock->release(); + } + public function testOtherOwnerDoesNotOwnLockAfterRestore() { $firstLock = Cache::lock('foo', 10); @@ -123,4 +139,14 @@ public function testExceptionIfBlockCanNotAcquireLock() $this->expectException(LockTimeoutException::class); Cache::lock('foo', 10)->block(5); } + + protected function tearDown(): void + { + try { + Cache::lock('foo')->forceRelease(); + } catch (Throwable) { + } + + parent::tearDown(); + } } From c51f3ec0e4baf21cc6d1bf89fcd127370648f1de Mon Sep 17 00:00:00 2001 From: Neil Carlo Sucuangco Date: Fri, 24 Oct 2025 00:52:53 +0800 Subject: [PATCH 3/6] [12.x] Namespace file cache lock keys --- config/cache.php | 2 +- src/Illuminate/Cache/FileStore.php | 6 ++++-- tests/Integration/Cache/FileCacheLockTest.php | 3 --- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/config/cache.php b/config/cache.php index a9daa1f757b9..8c603805ac76 100644 --- a/config/cache.php +++ b/config/cache.php @@ -55,7 +55,7 @@ 'file' => [ 'driver' => 'file', 'path' => storage_path('framework/cache/data'), - 'lock_path' => storage_path('framework/cache/locks'), + 'lock_path' => storage_path('framework/cache/data'), ], 'memcached' => [ diff --git a/src/Illuminate/Cache/FileStore.php b/src/Illuminate/Cache/FileStore.php index 9eeebebb0fff..c19274cfaa61 100755 --- a/src/Illuminate/Cache/FileStore.php +++ b/src/Illuminate/Cache/FileStore.php @@ -216,13 +216,15 @@ public function forever($key, $value) */ public function lock($name, $seconds = 0, $owner = null) { - $locksDir = $this->lockDirectory ?? ($this->directory.'/locks'); + $locksDir = $this->lockDirectory ?? $this->directory; $this->ensureCacheDirectoryExists($locksDir); + $lockName = "illuminate:cache:lock:{$name}"; + return new FileLock( new static($this->files, $locksDir, $this->filePermission), - $name, + $lockName, $seconds, $owner ); diff --git a/tests/Integration/Cache/FileCacheLockTest.php b/tests/Integration/Cache/FileCacheLockTest.php index 23a4bbde1da9..c71c8aeab053 100644 --- a/tests/Integration/Cache/FileCacheLockTest.php +++ b/tests/Integration/Cache/FileCacheLockTest.php @@ -17,9 +17,6 @@ protected function setUp(): void { parent::setUp(); - $this->app['config']->set('cache.default', 'file'); - $this->app['config']->set('cache.stores.file.lock_path', storage_path('framework/cache/locks')); - // flush lock from previous tests Cache::lock('foo')->forceRelease(); } From e9b70facb55f204f8da3def0a14b11485a3b7b9d Mon Sep 17 00:00:00 2001 From: Neil Carlo Sucuangco Date: Fri, 24 Oct 2025 01:02:18 +0800 Subject: [PATCH 4/6] Update FileStore.php --- src/Illuminate/Cache/FileStore.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Illuminate/Cache/FileStore.php b/src/Illuminate/Cache/FileStore.php index c19274cfaa61..f94244ca7799 100755 --- a/src/Illuminate/Cache/FileStore.php +++ b/src/Illuminate/Cache/FileStore.php @@ -216,14 +216,12 @@ public function forever($key, $value) */ public function lock($name, $seconds = 0, $owner = null) { - $locksDir = $this->lockDirectory ?? $this->directory; - - $this->ensureCacheDirectoryExists($locksDir); + $this->ensureCacheDirectoryExists($this->lockDirectory ?? $this->directory); $lockName = "illuminate:cache:lock:{$name}"; return new FileLock( - new static($this->files, $locksDir, $this->filePermission), + new static($this->files, $this->lockDirectory ?? $this->directory, $this->filePermission), $lockName, $seconds, $owner @@ -422,4 +420,4 @@ public function getPrefix() { return ''; } -} +} \ No newline at end of file From fd2ddc1d1df7f0ff6475b7a1b027b53e88ccf06a Mon Sep 17 00:00:00 2001 From: Neil Carlo Sucuangco Date: Fri, 24 Oct 2025 09:55:15 +0800 Subject: [PATCH 5/6] Update src/Illuminate/Cache/FileStore.php Co-authored-by: Tim MacDonald --- src/Illuminate/Cache/FileStore.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Cache/FileStore.php b/src/Illuminate/Cache/FileStore.php index f94244ca7799..4266d831038c 100755 --- a/src/Illuminate/Cache/FileStore.php +++ b/src/Illuminate/Cache/FileStore.php @@ -218,7 +218,7 @@ public function lock($name, $seconds = 0, $owner = null) { $this->ensureCacheDirectoryExists($this->lockDirectory ?? $this->directory); - $lockName = "illuminate:cache:lock:{$name}"; + $lockName = "{$name}:file-store-lock"; return new FileLock( new static($this->files, $this->lockDirectory ?? $this->directory, $this->filePermission), From 6a08db8eca6876da6838a8bb2bab5390e004037a Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Fri, 24 Oct 2025 09:14:42 -0500 Subject: [PATCH 6/6] formatting --- src/Illuminate/Cache/FileStore.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Illuminate/Cache/FileStore.php b/src/Illuminate/Cache/FileStore.php index 4266d831038c..6c504bad04e5 100755 --- a/src/Illuminate/Cache/FileStore.php +++ b/src/Illuminate/Cache/FileStore.php @@ -218,11 +218,9 @@ public function lock($name, $seconds = 0, $owner = null) { $this->ensureCacheDirectoryExists($this->lockDirectory ?? $this->directory); - $lockName = "{$name}:file-store-lock"; - return new FileLock( new static($this->files, $this->lockDirectory ?? $this->directory, $this->filePermission), - $lockName, + "file-store-lock:{$name}", $seconds, $owner ); @@ -420,4 +418,4 @@ public function getPrefix() { return ''; } -} \ No newline at end of file +}