From c32801fcc17f7a4e349486e92126d1e056ea47eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Letord?= Date: Tue, 4 Feb 2025 10:20:59 +0100 Subject: [PATCH 1/4] Use latest doctrine-cache-extension --- composer.json | 2 +- phpunit.xml.dist | 25 ++++++++++--------- .../Impl/Cache/DoctrineCacheHandler.php | 4 +-- .../Mock/Cache/DoctrineCacheHandlerMock.php | 6 ++--- .../Impl/Lock/SymfonyLockHandlerTest.php | 4 +++ .../LegacyCacheInterceptorTest.php | 7 +++++- 6 files changed, 28 insertions(+), 20 deletions(-) diff --git a/composer.json b/composer.json index 621b44a..af04213 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,7 @@ }, "require-dev": { "phpunit/phpunit": "^9.5", - "openclassrooms/doctrine-cache-extension": "1.0.*@dev", + "openclassrooms/doctrine-cache-extension": "dev-dcotrine_cache_two", "phpstan/phpstan": "^1.9", "phpstan/phpstan-strict-rules": "^1.4", "phpstan/phpstan-deprecation-rules": "^1.1", diff --git a/phpunit.xml.dist b/phpunit.xml.dist index b5c4278..b95c57e 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,19 +1,20 @@ - - - + + + + ./src + + + ./tests + ./vendor + + ./tests/ - - - ./src - - ./tests - ./vendor - - - diff --git a/src/Handler/Impl/Cache/DoctrineCacheHandler.php b/src/Handler/Impl/Cache/DoctrineCacheHandler.php index 60c4d5a..c5230bf 100644 --- a/src/Handler/Impl/Cache/DoctrineCacheHandler.php +++ b/src/Handler/Impl/Cache/DoctrineCacheHandler.php @@ -8,8 +8,8 @@ use OpenClassrooms\DoctrineCacheExtension\CacheProviderDecorator; use OpenClassrooms\ServiceProxy\Handler\Contract\CacheHandler; use OpenClassrooms\ServiceProxy\Handler\Impl\ConfigurableHandler; -use OpenClassrooms\ServiceProxy\Util\ArrayCache; use Psr\Cache\CacheItemInterface; +use Symfony\Component\Cache\Adapter\ArrayAdapter; /** * @deprecated use SymfonyCacheHandler instead @@ -22,7 +22,7 @@ final class DoctrineCacheHandler implements CacheHandler public function __construct(?CacheProviderDecorator $cacheProvider = null, ?string $name = null) { - $this->cacheProvider = $cacheProvider ?? new CacheProviderDecorator(new ArrayCache()); + $this->cacheProvider = $cacheProvider ?? new CacheProviderDecorator(new ArrayAdapter()); $this->name = $name; } diff --git a/tests/Double/Mock/Cache/DoctrineCacheHandlerMock.php b/tests/Double/Mock/Cache/DoctrineCacheHandlerMock.php index 4612d0a..b51d278 100644 --- a/tests/Double/Mock/Cache/DoctrineCacheHandlerMock.php +++ b/tests/Double/Mock/Cache/DoctrineCacheHandlerMock.php @@ -7,8 +7,8 @@ use OpenClassrooms\DoctrineCacheExtension\CacheProviderDecorator; use OpenClassrooms\ServiceProxy\Handler\Contract\CacheHandler; use OpenClassrooms\ServiceProxy\Handler\Impl\Cache\DoctrineCacheHandler; -use OpenClassrooms\ServiceProxy\Util\ArrayCache; use Psr\Cache\CacheItemInterface; +use Symfony\Component\Cache\Adapter\ArrayAdapter; final class DoctrineCacheHandlerMock implements CacheHandler { @@ -16,8 +16,6 @@ final class DoctrineCacheHandlerMock implements CacheHandler private CacheHandler $wrappedHandler; - private CacheProviderDecorator $cacheProvider; - private bool $default; private string $name; @@ -27,7 +25,7 @@ public function __construct(?string $name = null, bool $default = true) $this->name = $name ?? 'array'; $this->default = $default; - $cacheProvider = new CacheProviderDecorator(new ArrayCache()); + $cacheProvider = new CacheProviderDecorator(new ArrayAdapter()); $this->wrappedHandler = new DoctrineCacheHandler($cacheProvider, $name); } diff --git a/tests/Handler/Impl/Lock/SymfonyLockHandlerTest.php b/tests/Handler/Impl/Lock/SymfonyLockHandlerTest.php index b1f0ad0..1eb963a 100644 --- a/tests/Handler/Impl/Lock/SymfonyLockHandlerTest.php +++ b/tests/Handler/Impl/Lock/SymfonyLockHandlerTest.php @@ -11,6 +11,10 @@ class SymfonyLockHandlerTest extends TestCase { + private SymfonyLockHandler $handler1; + + private SymfonyLockHandler $handler2; + protected function setUp(): void { $factory1 = new LockFactory(new FlockStore()); diff --git a/tests/Interceptor/LegacyCacheInterceptorTest.php b/tests/Interceptor/LegacyCacheInterceptorTest.php index 5b5cd4e..ea78cbf 100644 --- a/tests/Interceptor/LegacyCacheInterceptorTest.php +++ b/tests/Interceptor/LegacyCacheInterceptorTest.php @@ -95,7 +95,12 @@ public function testInCacheWithNamespaceReturnData(): void $inCacheData = 'InCacheData'; $this->cacheHandlerMock->save( 'default', - md5(CacheAnnotatedClass::class . '::cacheWithNamespace'), + md5('test-namespace'), + '12345' + ); + $this->cacheHandlerMock->save( + 'default', + '12345' . md5(CacheAnnotatedClass::class . '::cacheWithNamespace'), $inCacheData ); $data = $this->proxy->cacheWithNamespace(); From 2bfa3eb85ee581248cce781dab30f980c9a78cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Letord?= Date: Tue, 4 Feb 2025 15:38:37 +0100 Subject: [PATCH 2/4] Dont store serialmized data in default legacy cache --- src/Handler/Impl/Cache/DoctrineCacheHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Handler/Impl/Cache/DoctrineCacheHandler.php b/src/Handler/Impl/Cache/DoctrineCacheHandler.php index c5230bf..e46cf6a 100644 --- a/src/Handler/Impl/Cache/DoctrineCacheHandler.php +++ b/src/Handler/Impl/Cache/DoctrineCacheHandler.php @@ -22,7 +22,7 @@ final class DoctrineCacheHandler implements CacheHandler public function __construct(?CacheProviderDecorator $cacheProvider = null, ?string $name = null) { - $this->cacheProvider = $cacheProvider ?? new CacheProviderDecorator(new ArrayAdapter()); + $this->cacheProvider = $cacheProvider ?? new CacheProviderDecorator(new ArrayAdapter(storeSerialized: false)); $this->name = $name; } From 6bd2923f8bcf7f2432a30d81e5f479fed8d40ec1 Mon Sep 17 00:00:00 2001 From: sidux Date: Tue, 4 Feb 2025 15:40:32 +0100 Subject: [PATCH 3/4] feat(cache): remove dependency on openclassrooms/doctrine-cache --- composer.json | 1 - .../Impl/Cache/CacheProviderDecorator.php | 181 ++++++++++++++++++ 2 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 src/Handler/Impl/Cache/CacheProviderDecorator.php diff --git a/composer.json b/composer.json index 621b44a..78797cf 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,6 @@ }, "require-dev": { "phpunit/phpunit": "^9.5", - "openclassrooms/doctrine-cache-extension": "1.0.*@dev", "phpstan/phpstan": "^1.9", "phpstan/phpstan-strict-rules": "^1.4", "phpstan/phpstan-deprecation-rules": "^1.1", diff --git a/src/Handler/Impl/Cache/CacheProviderDecorator.php b/src/Handler/Impl/Cache/CacheProviderDecorator.php new file mode 100644 index 0000000..ed0d029 --- /dev/null +++ b/src/Handler/Impl/Cache/CacheProviderDecorator.php @@ -0,0 +1,181 @@ +cacheProvider = $cacheProvider; + $this->defaultLifetime = $defaultLifetime; + } + + /** + * {@inheritdoc} + */ + public function __call($name, $arguments) + { + return $this->getCacheProvider()->$name(...$arguments); + } + + public function getCacheProvider(): CacheProvider + { + return $this->cacheProvider; + } + + /** + * Fetches an entry from the cache. + * + * @param string $id The id of the cache entry to fetch. + * @param string $namespaceId The id of the namespace entry to fetch. + * + * @return mixed The cached data or FALSE, if no cache entry exists for the given namespace and id. + */ + public function fetchWithNamespace($id, $namespaceId = null) + { + if (null !== $namespaceId) { + $namespace = $this->fetch($namespaceId); + $id = $namespace . $id; + } + + return $this->fetch($id); + } + + /** + * Invalidate a namespace. + * + * @param string $namespaceId The id of the namespace to invalidate. + * + * @return bool TRUE if the namespace entry was successfully regenerated, FALSE otherwise. + */ + public function invalidate($namespaceId) + { + $namespace = $this->fetch($namespaceId); + + if (false === $namespace) { + return false; + } + + $newNamespace = rand(0, 10000); + // @codeCoverageIgnoreStart + while ($namespace === $newNamespace) { + $newNamespace = rand(0, 10000); + } + + // @codeCoverageIgnoreEnd + return $this->save($namespaceId, $namespaceId . '_' . $newNamespace . '_', 0); + } + + /** + * Puts data into the cache. + * + * @param string $id The cache id. + * @param mixed $data The cache entry/data. + * @param int $lifeTime The cache lifetime. + * If != 0, sets a specific lifetime for this cache entry (0 => infinite lifeTime). + * + * @return bool TRUE if the entry was successfully stored in the cache, FALSE otherwise. + */ + public function save($id, $data, $lifeTime = null) + { + if (null === $lifeTime) { + $lifeTime = $this->getDefaultLifetime(); + } + + return parent::save($id, $data, $lifeTime); + } + + /** + * @return int + */ + public function getDefaultLifetime() + { + return $this->defaultLifetime; + } + + /** + * Puts data into the cache. + * + * @param string $id The cache id. + * @param mixed $data The cache entry/data. + * @param string $namespaceId The namespace id. + * @param int $lifeTime The cache lifetime. + * If != 0, sets a specific lifetime for this cache entry (0 => infinite lifeTime). + * + * @return bool TRUE if the entry was successfully stored in the cache, FALSE otherwise. + */ + public function saveWithNamespace($id, $data, $namespaceId = null, $lifeTime = null) + { + if (null !== $namespaceId) { + $namespace = $this->fetch($namespaceId); + if (!$namespace) { + $namespace = $namespaceId . '_' . rand(0, 10000); + $this->save($namespaceId, $namespace, 0); + } + $id = $namespace . $id; + } + + return $this->save($id, $data, $lifeTime); + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + return $this->getCacheProvider()->doContains($id); + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + return $this->getCacheProvider()->doDelete($id); + } + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + return $this->getCacheProvider()->doFetch($id); + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + return $this->getCacheProvider()->doFlush(); + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + return $this->getCacheProvider()->doGetStats(); + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + return $this->getCacheProvider()->doSave($id, $data, $lifeTime); + } +} From 3d2b9de89cd5cd790789f3ab94b22be96be5c7f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Letord?= Date: Wed, 5 Feb 2025 17:09:42 +0100 Subject: [PATCH 4/4] Fix cs --- .../Impl/Cache/DoctrineCacheHandler.php | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Handler/Impl/Cache/DoctrineCacheHandler.php b/src/Handler/Impl/Cache/DoctrineCacheHandler.php index 15ed962..964d0e9 100644 --- a/src/Handler/Impl/Cache/DoctrineCacheHandler.php +++ b/src/Handler/Impl/Cache/DoctrineCacheHandler.php @@ -33,33 +33,20 @@ public function fetch(string $poolName, string $id): CacheItemInterface return $this->fetchWithNamespace($id, $tags[0] ?? null); } - private function fetchWithNamespace(string $id, string $namespaceId = null): CacheItemInterface - { - if (null !== $namespaceId) { - $namespace = $this->doFetch($namespaceId); - - if ($namespace->isHit()) { - $id = $namespace->get().$id; - } - } - - return $this->doFetch($id); - } - public function save(string $poolName, string $id, $data, ?int $lifeTime = null, array $tags = []): void { $namespaceId = $tags[0] ?? null; - if (null !== $namespaceId) { + if ($namespaceId !== null) { $namespace = $this->doFetch($namespaceId); - if (! $namespace->isHit()) { - $namespace->set($namespaceId.'_'.rand(0, 1000000)) + if (!$namespace->isHit()) { + $namespace->set($namespaceId . '_' . mt_rand(0, 1000000)) // 7 days as no expiration can prevent cache eviction forever (like redis) ->expiresAfter(7 * 24 * 60 * 60); $this->pool->save($namespace); } - $id = $namespace->get().$id; + $id = $namespace->get() . $id; } $item = $this->doFetch($id); @@ -75,13 +62,26 @@ public function invalidateTags(string $poolName, array $tags): void throw new \BadMethodCallException('Cache provider does not support tags invalidation'); } - private function doFetch(string $id): CacheItemInterface + public function getName(): string { - return $this->pool->getItem(rawurlencode($id)); + return $this->name ?? 'doctrine_array'; } - public function getName(): string + private function fetchWithNamespace(string $id, string $namespaceId = null): CacheItemInterface { - return $this->name ?? 'doctrine_array'; + if ($namespaceId !== null) { + $namespace = $this->doFetch($namespaceId); + + if ($namespace->isHit()) { + $id = $namespace->get() . $id; + } + } + + return $this->doFetch($id); + } + + private function doFetch(string $id): CacheItemInterface + { + return $this->pool->getItem(rawurlencode($id)); } }