Added MemoryCacheStorage and use it in `ChangedFilesDetectorTest` (#525)

Co-authored-by: Markus Staab <markus.staab@redaxo.de>
This commit is contained in:
Markus Staab 2021-07-28 08:53:49 +02:00 committed by GitHub
parent a7f111e201
commit 687a77765f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 123 additions and 20 deletions

View File

@ -2,6 +2,7 @@
declare(strict_types=1);
use Rector\Caching\ValueObject\Storage\MemoryCacheStorage;
use Rector\Core\Configuration\Option;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
@ -29,4 +30,11 @@ return static function (ContainerConfigurator $containerConfigurator): void {
// cache
$parameters->set(Option::CACHE_DIR, sys_get_temp_dir() . '/rector_cached_files');
// use faster in-memory cache in CI.
// CI always starts from scratch, therefore IO intensive caching is not worth it
$runsInGithubAction = getenv('GITHUB_ACTION');
if (false !== $runsInGithubAction) {
$parameters->set(Option::CACHE_CLASS, MemoryCacheStorage::class);
}
};

View File

@ -2,10 +2,12 @@
declare(strict_types=1);
use Rector\Caching\ValueObject\Storage\MemoryCacheStorage;
use Rector\Core\Configuration\Option;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::CACHE_DIR, sys_get_temp_dir() . '/_rector_cached_files_test');
$parameters->set(Option::CACHE_CLASS, MemoryCacheStorage::class);
};

View File

@ -4,12 +4,12 @@ declare(strict_types=1);
namespace Rector\Caching;
use Rector\Caching\ValueObject\Storage\FileCacheStorage;
use Rector\Caching\ValueObject\Storage\CacheStorageInterface;
final class Cache
{
public function __construct(
private FileCacheStorage $fileCacheStorage
private CacheStorageInterface $cacheStorage
) {
}
@ -18,7 +18,7 @@ final class Cache
*/
public function load(string $key, string $variableKey)
{
return $this->fileCacheStorage->load($key, $variableKey);
return $this->cacheStorage->load($key, $variableKey);
}
/**
@ -26,16 +26,16 @@ final class Cache
*/
public function save(string $key, string $variableKey, $data): void
{
$this->fileCacheStorage->save($key, $variableKey, $data);
$this->cacheStorage->save($key, $variableKey, $data);
}
public function clear(): void
{
$this->fileCacheStorage->clear();
$this->cacheStorage->clear();
}
public function clean(string $cacheKey): void
{
$this->fileCacheStorage->clean($cacheKey);
$this->cacheStorage->clean($cacheKey);
}
}

View File

@ -4,7 +4,9 @@ declare(strict_types=1);
namespace Rector\Caching;
use Rector\Caching\ValueObject\Storage\CacheStorageInterface;
use Rector\Caching\ValueObject\Storage\FileCacheStorage;
use Rector\Caching\ValueObject\Storage\MemoryCacheStorage;
use Rector\Core\Configuration\Option;
use Symplify\PackageBuilder\Parameter\ParameterProvider;
use Symplify\SmartFileSystem\SmartFileSystem;
@ -21,12 +23,21 @@ final class CacheFactory
{
$cacheDirectory = $this->parameterProvider->provideStringParameter(Option::CACHE_DIR);
// ensure cache directory exists
if (! $this->smartFileSystem->exists($cacheDirectory)) {
$this->smartFileSystem->mkdir($cacheDirectory);
$cacheClass = FileCacheStorage::class;
if ($this->parameterProvider->hasParameter(Option::CACHE_CLASS)) {
$cacheClass = $this->parameterProvider->provideStringParameter(Option::CACHE_CLASS);
}
$fileCacheStorage = new FileCacheStorage($cacheDirectory, $this->smartFileSystem);
return new Cache($fileCacheStorage);
if ($cacheClass === FileCacheStorage::class) {
// ensure cache directory exists
if (! $this->smartFileSystem->exists($cacheDirectory)) {
$this->smartFileSystem->mkdir($cacheDirectory);
}
$fileCacheStorage = new FileCacheStorage($cacheDirectory, $this->smartFileSystem);
return new Cache($fileCacheStorage);
}
return new Cache(new MemoryCacheStorage());
}
}

View File

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace Rector\Caching\ValueObject\Storage;
/**
* inspired by https://github.com/phpstan/phpstan-src/blob/560652088406d7461c2c4ad4897784e33f8ab312/src/Cache/CacheStorage.php
*/
interface CacheStorageInterface
{
/**
* @return mixed|null
*/
public function load(string $key, string $variableKey);
/**
* @param mixed $data
*/
public function save(string $key, string $variableKey, $data): void;
public function clean(string $key): void;
public function clear(): void;
}

View File

@ -14,7 +14,7 @@ use Symplify\SmartFileSystem\SmartFileSystem;
/**
* Inspired by https://github.com/phpstan/phpstan-src/blob/1e7ceae933f07e5a250b61ed94799e6c2ea8daa2/src/Cache/FileCacheStorage.php
*/
final class FileCacheStorage
final class FileCacheStorage implements CacheStorageInterface
{
public function __construct(
private string $directory,
@ -22,9 +22,6 @@ final class FileCacheStorage
) {
}
/**
* @return mixed|null
*/
public function load(string $key, string $variableKey)
{
return (function (string $key, string $variableKey) {
@ -45,9 +42,6 @@ final class FileCacheStorage
})($key, $variableKey);
}
/**
* @param mixed $data
*/
public function save(string $key, string $variableKey, $data): void
{
$cacheFilePaths = $this->getCacheFilePaths($key);
@ -79,9 +73,9 @@ final class FileCacheStorage
}
}
public function clean(string $cacheKey): void
public function clean(string $key): void
{
$cacheFilePaths = $this->getCacheFilePaths($cacheKey);
$cacheFilePaths = $this->getCacheFilePaths($key);
$this->smartFileSystem->remove([
$cacheFilePaths->getFirstDirectory(),

View File

@ -0,0 +1,47 @@
<?php declare(strict_types = 1);
namespace Rector\Caching\ValueObject\Storage;
use Rector\Caching\ValueObject\CacheItem;
/**
* inspired by https://github.com/phpstan/phpstan-src/blob/560652088406d7461c2c4ad4897784e33f8ab312/src/Cache/MemoryCacheStorage.php
*/
class MemoryCacheStorage implements CacheStorageInterface
{
/** @var array<string, CacheItem> */
private array $storage = [];
public function load(string $key, string $variableKey)
{
if (!isset($this->storage[$key])) {
return null;
}
$item = $this->storage[$key];
if (!$item->isVariableKeyValid($variableKey)) {
return null;
}
return $item->getData();
}
public function save(string $key, string $variableKey, $data): void
{
$this->storage[$key] = new CacheItem($variableKey, $data);
}
public function clean(string $key): void
{
if (!isset($this->storage[$key])) {
return;
}
unset($this->storage[$key]);
}
public function clear(): void
{
$this->storage = [];
}
}

View File

@ -511,6 +511,12 @@ parameters:
- '#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#'
# internal contract, not meant for re-use at rector consumer level
-
message: '#Interface must be located in "Contract" namespace#'
paths:
- packages/Caching/ValueObject/Storage/CacheStorageInterface.php
# resolve later
-
message: '#Use explicit names over dynamic ones#'

View File

@ -5,6 +5,8 @@ declare(strict_types=1);
namespace Rector\Core\Configuration;
use JetBrains\PhpStorm\Immutable;
use Rector\Caching\ValueObject\Storage\CacheStorageInterface;
use Rector\Caching\ValueObject\Storage\FileCacheStorage;
use Symplify\Skipper\ValueObject\Option as SkipperOption;
#[Immutable]
@ -111,6 +113,14 @@ final class Option
*/
public const CACHE_DIR = 'cache_dir';
/**
* Cache backend. Most of the time we cache in files, but in ephemeral environment (e.g. CI), a faster `MemoryCacheStorage` can be usefull.
*
* @var class-string<CacheStorageInterface>
* @internal
*/
public const CACHE_CLASS = FileCacheStorage::class;
/**
* @var string
*/