Skip to content

Commit 63fba2a

Browse files
authored
feat(metadata): cache operation metadata factory (#7516)
1 parent 390056f commit 63fba2a

File tree

3 files changed

+84
-1
lines changed

3 files changed

+84
-1
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace ApiPlatform\Metadata\Operation\Factory;
15+
16+
use ApiPlatform\Metadata\Operation;
17+
use Psr\Cache\CacheException;
18+
use Psr\Cache\CacheItemPoolInterface;
19+
20+
/**
21+
* Caches operation metadata.
22+
*
23+
* @author Antoine Bluchet <[email protected]>
24+
*/
25+
final class CacheOperationMetadataFactory implements OperationMetadataFactoryInterface
26+
{
27+
public const CACHE_KEY_PREFIX = 'operation_metadata_';
28+
private array $localCache = [];
29+
30+
public function __construct(private readonly CacheItemPoolInterface $cacheItemPool, private readonly OperationMetadataFactoryInterface $decorated)
31+
{
32+
}
33+
34+
/**
35+
* {@inheritdoc}
36+
*/
37+
public function create(string $uriTemplate, array $context = []): ?Operation
38+
{
39+
$cacheKey = self::CACHE_KEY_PREFIX.hash('xxh3', $uriTemplate);
40+
if (\array_key_exists($cacheKey, $this->localCache)) {
41+
return $this->localCache[$cacheKey];
42+
}
43+
44+
try {
45+
$cacheItem = $this->cacheItemPool->getItem($cacheKey);
46+
} catch (CacheException) {
47+
$operation = $this->decorated->create($uriTemplate, $context);
48+
$this->localCache[$cacheKey] = $operation;
49+
50+
return $operation;
51+
}
52+
53+
if ($cacheItem->isHit()) {
54+
$this->localCache[$cacheKey] = $cacheItem->get();
55+
56+
return $this->localCache[$cacheKey];
57+
}
58+
59+
$operation = $this->decorated->create($uriTemplate, $context);
60+
$this->localCache[$cacheKey] = $operation;
61+
$cacheItem->set($this->localCache[$cacheKey]);
62+
$this->cacheItemPool->save($cacheItem);
63+
64+
return $operation;
65+
}
66+
}

src/Metadata/Operation/Factory/OperationMetadataFactory.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,23 @@
1919

2020
final class OperationMetadataFactory implements OperationMetadataFactoryInterface
2121
{
22+
private array $localCache = [];
23+
2224
public function __construct(private readonly ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory, private readonly ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory)
2325
{
2426
}
2527

2628
public function create(string $uriTemplate, array $context = []): ?Operation
2729
{
30+
if (isset($this->localCache[$uriTemplate])) {
31+
return $this->localCache[$uriTemplate];
32+
}
33+
2834
foreach ($this->resourceNameCollectionFactory->create() as $resourceClass) {
2935
foreach ($this->resourceMetadataCollectionFactory->create($resourceClass) as $resource) {
3036
foreach ($resource->getOperations() as $operation) {
3137
if ($operation->getUriTemplate() === $uriTemplate || $operation->getName() === $uriTemplate) {
32-
return $operation;
38+
return $this->localCache[$uriTemplate] = $operation;
3339
}
3440
}
3541
}

src/Symfony/Bundle/Resources/config/metadata/operation.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,15 @@
2323
]);
2424

2525
$services->alias('ApiPlatform\Metadata\Operation\Factory\OperationMetadataFactoryInterface', 'api_platform.metadata.operation.metadata_factory');
26+
27+
$services->set('api_platform.metadata.operation.metadata_factory.cached', 'ApiPlatform\Metadata\Operation\Factory\CacheOperationMetadataFactory')
28+
->decorate('api_platform.metadata.operation.metadata_factory', null, -10)
29+
->args([
30+
service('api_platform.cache.metadata.operation'),
31+
service('api_platform.metadata.operation.metadata_factory.cached.inner'),
32+
]);
33+
34+
$services->set('api_platform.cache.metadata.operation')
35+
->parent('cache.system')
36+
->tag('cache.pool');
2637
};

0 commit comments

Comments
 (0)