Skip to content

Commit

Permalink
Sync FileCacheStorage with changes from phpstan-src (#498)
Browse files Browse the repository at this point in the history
* perf optimize FileCacheStorage

* sync FIleCacheStorage impl with upstream phpstan

* update comment

* Update FileCacheStorage.php

* use Rector\Caching\ValueObject\CacheItem

* fix phpstan: use CachingException

* fix phpstan: use smartFileSystem

* re-added nearly everything again

* Update FileCacheStorage.php

* remove String::substring()

* Update FileCacheStorage.php

* ignore phpstan errors

* fix path

* Update phpstan.neon

Co-authored-by: Markus Staab <m.staab@complex-it.de>
  • Loading branch information
staabm and clxmstaab committed Jul 26, 2021
1 parent b47f2c9 commit 6478ec1
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 45 deletions.
86 changes: 43 additions & 43 deletions packages/Caching/ValueObject/Storage/FileCacheStorage.php
Expand Up @@ -5,15 +5,14 @@
namespace Rector\Caching\ValueObject\Storage;

use Nette\Utils\Random;
use Nette\Utils\Strings;
use Rector\Caching\ValueObject\CacheFilePaths;
use Rector\Caching\ValueObject\CacheItem;
use Symplify\EasyCodingStandard\Caching\Exception\CachingException;
use PHPStan\File\FileWriter;
use Symplify\SmartFileSystem\SmartFileSystem;
use Symplify\EasyCodingStandard\Caching\Exception\CachingException;

/**
* Inspired by
* https://github.com/phpstan/phpstan-src/commit/4df7342f3a0aaef4bcd85456dd20ca88d38dd90d#diff-6dc14f6222bf150e6840ca44a7126653052a1cedc6a149b4e5c1e1a2c80eacdc
* Inspired by https://github.com/phpstan/phpstan-src/blob/1e7ceae933f07e5a250b61ed94799e6c2ea8daa2/src/Cache/FileCacheStorage.php
*/
final class FileCacheStorage
{
Expand All @@ -24,59 +23,60 @@ public function __construct(
}

/**
* @param string $key
* @param string $variableKey
* @return mixed|null
*/
public function load(string $key, string $variableKey)
{
$cacheFilePaths = $this->getCacheFilePaths($key);

$filePath = $cacheFilePaths->getFilePath();
if (! is_file($filePath)) {
return null;
}

$cacheItem = require $filePath;
if (! $cacheItem instanceof CacheItem) {
return null;
}

if (! $cacheItem->isVariableKeyValid($variableKey)) {
return null;
}

return $cacheItem->getData();
return (function (string $key, string $variableKey) {
$cacheFilePaths = $this->getCacheFilePaths($key);

$filePath = $cacheFilePaths->getFilePath();
if (!\is_file($filePath)) {
return null;
}
$cacheItem = (require $filePath);
if (!$cacheItem instanceof CacheItem) {
return null;
}
if (!$cacheItem->isVariableKeyValid($variableKey)) {
return null;
}
return $cacheItem->getData();
})($key, $variableKey);
}

/**
* @param string $key
* @param string $variableKey
* @param mixed $data
* @return void
*/
public function save(string $key, string $variableKey, $data): void
public function save(string $key, string $variableKey, $data) : void
{
$cacheFilePaths = $this->getCacheFilePaths($key);

$this->smartFileSystem->mkdir($cacheFilePaths->getFirstDirectory());
$this->smartFileSystem->mkdir($cacheFilePaths->getSecondDirectory());
$path = $cacheFilePaths->getFilePath();

$tmpPath = sprintf('%s/%s.tmp', $this->directory, Random::generate());
$errorBefore = error_get_last();
$exported = @var_export(new CacheItem($variableKey, $data), true);
$errorAfter = error_get_last();

$tmpPath = \sprintf('%s/%s.tmp', $this->directory, Random::generate());
$errorBefore = \error_get_last();
$exported = @\var_export(new CacheItem($variableKey, $data), true);
$errorAfter = \error_get_last();
if ($errorAfter !== null && $errorBefore !== $errorAfter) {
$errorMessage = sprintf(
'Error occurred while saving item "%s" ("%s") to cache: "%s"',
$key,
$variableKey,
$errorAfter['message']
);
throw new CachingException($errorMessage);
throw new CachingException(\sprintf('Error occurred while saving item %s (%s) to cache: %s', $key, $variableKey, $errorAfter['message']));
}
// for performance reasons we don't use SmartFileSystem
FileWriter::write($tmpPath, \sprintf("<?php declare(strict_types = 1);\n\nreturn %s;", $exported));
$renameSuccess = @\rename($tmpPath, $path);
if ($renameSuccess) {
return;
}
@\unlink($tmpPath);
if (\DIRECTORY_SEPARATOR === '/' || !\file_exists($path)) {
throw new CachingException(\sprintf('Could not write data to cache file %s.', $path));
}

$variableFileContent = sprintf("<?php declare(strict_types = 1);\n\nreturn %s;", $exported);
$this->smartFileSystem->dumpFile($tmpPath, $variableFileContent);

$this->smartFileSystem->rename($tmpPath, $cacheFilePaths->getFilePath(), true);
$this->smartFileSystem->remove($tmpPath);
}

public function clean(string $cacheKey): void
Expand All @@ -98,8 +98,8 @@ public function clear(): void
private function getCacheFilePaths(string $key): CacheFilePaths
{
$keyHash = sha1($key);
$firstDirectory = sprintf('%s/%s', $this->directory, Strings::substring($keyHash, 0, 2));
$secondDirectory = sprintf('%s/%s', $firstDirectory, Strings::substring($keyHash, 2, 2));
$firstDirectory = sprintf('%s/%s', $this->directory, substr($keyHash, 0, 2));
$secondDirectory = sprintf('%s/%s', $firstDirectory, substr($keyHash, 2, 2));
$filePath = sprintf('%s/%s.php', $secondDirectory, $keyHash);

return new CacheFilePaths($firstDirectory, $secondDirectory, $filePath);
Expand Down
26 changes: 24 additions & 2 deletions phpstan.neon
Expand Up @@ -459,8 +459,6 @@ parameters:
message: '#Access to an undefined property PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocChildNode\:\:\$value#'
path: packages/BetterPhpDocParser/PhpDocInfo/PhpDocInfo.php #348

- '#"@var_export\(new \\Rector\\Caching\\ValueObject\\CacheItem\(\$variableKey, \$data\), true\)" is forbidden to use#'

-
message: '#Class with base "StaticTypeMapper" name is already used in "Rector\\PHPStanStaticTypeMapper\\TypeMapper\\StaticTypeMapper", "Rector\\StaticTypeMapper\\StaticTypeMapper"\. Use unique name to make classes easy to recognize#'
path: packages/StaticTypeMapper/StaticTypeMapper.php #31
Expand Down Expand Up @@ -528,3 +526,27 @@ parameters:
- '#Method "refactorParamType\(\)" returns bool type, so the name should start with is/has/was#'
- '#Method "decorateReturnWithSpecificType\(\)" returns bool type, so the name should start with is/has/was#'
- '#Method "resolveObjectType\(\)" returns bool type, so the name should start with is/has/was#'

# resolve later
-
message: '#Use explicit names over dynamic ones#'
paths:
- packages/Caching/ValueObject/Storage/FileCacheStorage.php

# native filesystem calls, required for performance reasons
-
message: '#"@\\unlink\(\$tmpPath\)" is forbidden to use#'
paths:
- packages/Caching/ValueObject/Storage/FileCacheStorage.php
-
message: '#"@\\rename\(\$tmpPath, \$path\)" is forbidden to use#'
paths:
- packages/Caching/ValueObject/Storage/FileCacheStorage.php
-
message: '#"%s" in sprintf\(\) format must be quoted#'
paths:
- packages/Caching/ValueObject/Storage/FileCacheStorage.php
-
message: '#"@\\var_export\(new \\Rector\\Caching\\ValueObject\\CacheItem\(\$variableKey, \$data\), true\)" is forbidden to use#'
paths:
- packages/Caching/ValueObject/Storage/FileCacheStorage.php

0 comments on commit 6478ec1

Please sign in to comment.