From 6cb23b04699e190790c7c4b0fea240ff86b55540 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 1 Sep 2026 18:13:36 +0700 Subject: [PATCH 1/4] [Caching] Use atomic rename() on non-Windows in FileCacheStorage to avoid partially written cache reads on parallel run --- .../ValueObject/Storage/FileCacheStorage.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Caching/ValueObject/Storage/FileCacheStorage.php b/src/Caching/ValueObject/Storage/FileCacheStorage.php index b883cb4b9ae..6e659cf20f5 100644 --- a/src/Caching/ValueObject/Storage/FileCacheStorage.php +++ b/src/Caching/ValueObject/Storage/FileCacheStorage.php @@ -70,10 +70,21 @@ public function save(string $key, string $variableKey, mixed $data): void // for performance reasons we don't use SmartFileSystem FileSystem::write($tmpPath, \sprintf(" Date: Wed, 2 Sep 2026 15:36:07 +0700 Subject: [PATCH 2/4] add see link to php-src issue about rename on windows --- src/Caching/ValueObject/Storage/FileCacheStorage.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Caching/ValueObject/Storage/FileCacheStorage.php b/src/Caching/ValueObject/Storage/FileCacheStorage.php index 6e659cf20f5..ef91c9d7ee2 100644 --- a/src/Caching/ValueObject/Storage/FileCacheStorage.php +++ b/src/Caching/ValueObject/Storage/FileCacheStorage.php @@ -74,14 +74,13 @@ public function save(string $key, string $variableKey, mixed $data): void /** * @see https://github.com/rectorphp/rector/issues/9876 * @see https://github.com/rectorphp/rector/issues/8432 + * @see https://github.com/php/php-src/issues/7910 * * Cover compatibility for Windows and Unix systems */ $writeSuccess = \DIRECTORY_SEPARATOR === '/' ? @\rename($tmpPath, $filePath) : @\copy($tmpPath, $filePath); - - // already moved by rename() on success, then unlink() is no-op on it @\unlink($tmpPath); if ($writeSuccess) { From 805a62a88ae9e02e23298601abea01ef1bfb30e5 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 2 Sep 2026 19:39:47 +0700 Subject: [PATCH 3/4] rename early, copy later --- .../ValueObject/Storage/FileCacheStorage.php | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/Caching/ValueObject/Storage/FileCacheStorage.php b/src/Caching/ValueObject/Storage/FileCacheStorage.php index ef91c9d7ee2..853333614de 100644 --- a/src/Caching/ValueObject/Storage/FileCacheStorage.php +++ b/src/Caching/ValueObject/Storage/FileCacheStorage.php @@ -73,23 +73,32 @@ public function save(string $key, string $variableKey, mixed $data): void /** * @see https://github.com/rectorphp/rector/issues/9876 + * + * Try the atomic write first, as rename() also works on unaffected Windows PHP versions + */ + $renameSuccess = @\rename($tmpPath, $filePath); + if ($renameSuccess) { + return; + } + + if (\DIRECTORY_SEPARATOR === '/') { + throw new CachingException(\sprintf('Could not write data to cache file %s.', $filePath)); + } + + /** * @see https://github.com/rectorphp/rector/issues/8432 * @see https://github.com/php/php-src/issues/7910 * - * Cover compatibility for Windows and Unix systems + * Fall back only on affected Windows PHP versions where rename() failed */ - $writeSuccess = \DIRECTORY_SEPARATOR === '/' - ? @\rename($tmpPath, $filePath) - : @\copy($tmpPath, $filePath); + $copySuccess = @\copy($tmpPath, $filePath); @\unlink($tmpPath); - if ($writeSuccess) { + if ($copySuccess) { return; } - if (\DIRECTORY_SEPARATOR === '/' || ! \file_exists($filePath)) { - throw new CachingException(\sprintf('Could not write data to cache file %s.', $filePath)); - } + throw new CachingException(\sprintf('Could not write data to cache file %s.', $filePath)); } public function clean(string $key): void From 5bdef29f56f7aba1fb4fdfbb32b1e89c3092155a Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Wed, 2 Sep 2026 19:41:31 +0700 Subject: [PATCH 4/4] rename early, copy later --- src/Caching/ValueObject/Storage/FileCacheStorage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Caching/ValueObject/Storage/FileCacheStorage.php b/src/Caching/ValueObject/Storage/FileCacheStorage.php index 853333614de..dae01ec34a9 100644 --- a/src/Caching/ValueObject/Storage/FileCacheStorage.php +++ b/src/Caching/ValueObject/Storage/FileCacheStorage.php @@ -81,7 +81,7 @@ public function save(string $key, string $variableKey, mixed $data): void return; } - if (\DIRECTORY_SEPARATOR === '/') { + if (\DIRECTORY_SEPARATOR === '/' || ! \file_exists($filePath)) { throw new CachingException(\sprintf('Could not write data to cache file %s.', $filePath)); }