Skip to content

Commit b13e679

Browse files
committed
switch to TagAwareCacheInterface
1 parent 10fe13b commit b13e679

File tree

2 files changed

+46
-49
lines changed

2 files changed

+46
-49
lines changed

src/Symfony/Component/HttpClient/CachingHttpClient.php

Lines changed: 41 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
namespace Symfony\Component\HttpClient;
1313

14-
use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface;
1514
use Symfony\Component\HttpClient\Caching\Freshness;
1615
use Symfony\Component\HttpClient\Chunk\ErrorChunk;
1716
use Symfony\Component\HttpClient\Exception\ChunkCacheItemNotFoundException;
@@ -23,6 +22,8 @@
2322
use Symfony\Component\HttpKernel\HttpCache\HttpCache;
2423
use Symfony\Component\HttpKernel\HttpCache\StoreInterface;
2524
use Symfony\Component\HttpKernel\HttpClientKernel;
25+
use Symfony\Contracts\Cache\ItemInterface;
26+
use Symfony\Contracts\Cache\TagAwareCacheInterface;
2627
use Symfony\Contracts\HttpClient\ChunkInterface;
2728
use Symfony\Contracts\HttpClient\HttpClientInterface;
2829
use Symfony\Contracts\HttpClient\ResponseInterface;
@@ -81,7 +82,7 @@ class CachingHttpClient implements HttpClientInterface, ResetInterface
8182
*/
8283
private const MAX_HEURISTIC_FRESHNESS_TTL = 86400;
8384

84-
private TagAwareAdapterInterface|HttpCache $cache;
85+
private TagAwareCacheInterface|HttpCache $cache;
8586
private array $defaultOptions = self::OPTIONS_DEFAULTS;
8687

8788
/**
@@ -94,13 +95,13 @@ class CachingHttpClient implements HttpClientInterface, ResetInterface
9495
*/
9596
public function __construct(
9697
private HttpClientInterface $client,
97-
TagAwareAdapterInterface|StoreInterface $cache,
98+
TagAwareCacheInterface|StoreInterface $cache,
9899
array $defaultOptions = [],
99100
private readonly bool $sharedCache = true,
100101
private readonly ?int $maxTtl = null,
101102
) {
102103
if ($cache instanceof StoreInterface) {
103-
trigger_deprecation('symfony/http-client', '7.3', 'Passing a "%s" as constructor\'s 2nd argument of "%s" is deprecated, "%s" expected.', StoreInterface::class, __CLASS__, TagAwareAdapterInterface::class);
104+
trigger_deprecation('symfony/http-client', '7.3', 'Passing a "%s" as constructor\'s 2nd argument of "%s" is deprecated, "%s" expected.', StoreInterface::class, __CLASS__, TagAwareCacheInterface::class);
104105

105106
if (!class_exists(HttpClientKernel::class)) {
106107
throw new \LogicException(\sprintf('Using "%s" requires the HttpKernel component, try running "composer require symfony/http-kernel".', __CLASS__));
@@ -149,12 +150,10 @@ public function request(string $method, string $url, array $options = []): Respo
149150

150151
$requestHash = self::hash($method.$fullUrl);
151152
$varyKey = "vary_{$requestHash}";
152-
$varyItem = $this->cache->getItem($varyKey);
153-
$varyFields = $varyItem->isHit() ? $varyItem->get() : [];
153+
$varyFields = $this->cache->get($varyKey, static fn (): array => []);
154154

155155
$metadataKey = self::getMetadataKey($requestHash, $options['normalized_headers'], $varyFields);
156-
$metadataItem = $this->cache->getItem($metadataKey);
157-
$cachedData = $metadataItem->isHit() ? $metadataItem->get() : null;
156+
$cachedData = $this->cache->get($metadataKey, static fn (): null => null);
158157

159158
$freshness = null;
160159
if (\is_array($cachedData)) {
@@ -185,9 +184,8 @@ function (ChunkInterface $chunk, AsyncContext $context) use (
185184
$expiresAt,
186185
$fullUrlTag,
187186
$requestHash,
188-
$varyItem,
187+
$varyKey,
189188
&$metadataKey,
190-
$metadataItem,
191189
$cachedData,
192190
$freshness,
193191
$url,
@@ -230,13 +228,16 @@ function (ChunkInterface $chunk, AsyncContext $context) use (
230228
if (304 === $statusCode && null !== $freshness) {
231229
$maxAge = $this->determineMaxAge($headers, $cacheControl);
232230

233-
$cachedData['expires_at'] = self::calculateExpiresAt($maxAge);
234-
$cachedData['stored_at'] = time();
235-
$cachedData['initial_age'] = (int) ($headers['age'][0] ?? 0);
236-
$cachedData['headers'] = array_merge($cachedData['headers'], array_diff_key($headers, self::EXCLUDED_HEADERS));
231+
$this->cache->get($metadataKey, static function (ItemInterface $item) use ($headers, $maxAge, $cachedData, $expiresAt, $fullUrlTag): array {
232+
$item->expiresAt($expiresAt)->tag($fullUrlTag);
237233

238-
$metadataItem->set($cachedData)->expiresAt($expiresAt);
239-
$this->cache->save($metadataItem);
234+
$cachedData['expires_at'] = self::calculateExpiresAt($maxAge);
235+
$cachedData['stored_at'] = time();
236+
$cachedData['initial_age'] = (int) ($headers['age'][0] ?? 0);
237+
$cachedData['headers'] = array_merge($cachedData['headers'], array_diff_key($headers, self::EXCLUDED_HEADERS));
238+
239+
return $cachedData;
240+
}, \INF);
240241

241242
$context->passthru();
242243
$context->replaceResponse($this->createResponseFromCache($metadataKey, $cachedData, $method, $url, $options, $fullUrlTag));
@@ -292,25 +293,26 @@ function (ChunkInterface $chunk, AsyncContext $context) use (
292293
}
293294

294295
if ($chunk->isLast()) {
295-
$this->cache->saveDeferred($varyItem->set($varyFields)->tag($fullUrlTag)->expiresAt($expiresAt));
296+
$this->cache->get($varyKey, static function (ItemInterface $item) use ($varyFields, $expiresAt, $fullUrlTag): array {
297+
$item->tag($fullUrlTag)->expiresAt($expiresAt);
298+
299+
return $varyFields;
300+
}, \INF);
296301

297302
$maxAge = $this->determineMaxAge($headers, $cacheControl);
298303

299-
$this->cache->saveDeferred(
300-
$this->cache->getItem($metadataKey)
301-
->tag($fullUrlTag)
302-
->set([
303-
'status_code' => $context->getStatusCode(),
304-
'headers' => array_diff_key($headers, self::EXCLUDED_HEADERS),
305-
'initial_age' => (int) ($headers['age'][0] ?? 0),
306-
'stored_at' => time(),
307-
'expires_at' => self::calculateExpiresAt($maxAge),
308-
'chunks_count' => $chunkIndex,
309-
])
310-
->expiresAt($expiresAt)
311-
);
312-
313-
$this->cache->commit();
304+
$this->cache->get($metadataKey, static function (ItemInterface $item) use ($context, $headers, $maxAge, $expiresAt, $fullUrlTag, $chunkIndex): array {
305+
$item->tag($fullUrlTag)->expiresAt($expiresAt);
306+
307+
return [
308+
'status_code' => $context->getStatusCode(),
309+
'headers' => array_diff_key($headers, self::EXCLUDED_HEADERS),
310+
'initial_age' => (int) ($headers['age'][0] ?? 0),
311+
'stored_at' => time(),
312+
'expires_at' => self::calculateExpiresAt($maxAge),
313+
'chunks_count' => $chunkIndex,
314+
];
315+
}, \INF);
314316

315317
yield $chunk;
316318

@@ -319,12 +321,11 @@ function (ChunkInterface $chunk, AsyncContext $context) use (
319321

320322
++$chunkIndex;
321323
$chunkKey = "{$metadataKey}_chunk_{$chunkIndex}";
322-
$chunkItem = $this->cache->getItem($chunkKey)
323-
->tag($fullUrlTag)
324-
->set($chunk->getContent())
325-
->expiresAt($expiresAt);
324+
$this->cache->get($chunkKey, static function (ItemInterface $item) use ($expiresAt, $fullUrlTag, $chunk): string {
325+
$item->tag($fullUrlTag)->expiresAt($expiresAt);
326326

327-
$this->cache->save($chunkItem);
327+
return $chunk->getContent();
328+
}, \INF);
328329

329330
yield $chunk;
330331
}
@@ -684,15 +685,11 @@ private function createResponseFromCache(string $key, array $cachedData, string
684685
new MockResponse(
685686
(function () use ($key, $cachedData, $fullUrlTag): \Generator {
686687
for ($i = 0; $i <= $cachedData['chunks_count']; ++$i) {
687-
$chunkItem = $this->cache->getItem("{$key}_chunk_{$i}");
688-
689-
if (!$chunkItem->isHit()) {
688+
yield $this->cache->get("{$key}_chunk_{$i}", function (ItemInterface $item) use ($fullUrlTag): never {
690689
$this->cache->invalidateTags([$fullUrlTag]);
691690

692-
throw new ChunkCacheItemNotFoundException(\sprintf('Missing cache item for chunk with key "%s". This indicates an internal cache inconsistency.', $chunkItem->getKey()));
693-
}
694-
695-
yield $chunkItem->get();
691+
throw new ChunkCacheItemNotFoundException(\sprintf('Missing cache item for chunk with key "%s". This indicates an internal cache inconsistency.', $item->getKey()));
692+
}, 0);
696693
}
697694
})(),
698695
['http_code' => $cachedData['status_code'], 'response_headers' => ['age' => $cachedData['initial_age'] + (time() - $cachedData['stored_at'])] + $cachedData['headers']]

src/Symfony/Component/HttpClient/Tests/LegacyCachingHttpClientTest.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class LegacyCachingHttpClientTest extends TestCase
2828

2929
public function testRequestHeaders()
3030
{
31-
$this->expectDeprecation('Since symfony/http-client 7.3: Passing a "Symfony\Component\HttpKernel\HttpCache\StoreInterface" as constructor\'s 2nd argument of "Symfony\Component\HttpClient\CachingHttpClient" is deprecated, "Symfony\Component\Cache\Adapter\TagAwareAdapterInterface" expected.');
31+
$this->expectDeprecation('Since symfony/http-client 7.3: Passing a "Symfony\Component\HttpKernel\HttpCache\StoreInterface" as constructor\'s 2nd argument of "Symfony\Component\HttpClient\CachingHttpClient" is deprecated, "Symfony\Contracts\Cache\TagAwareCacheInterface" expected.');
3232

3333
$options = [
3434
'headers' => [
@@ -51,7 +51,7 @@ public function testRequestHeaders()
5151

5252
public function testDoesNotEvaluateResponseBody()
5353
{
54-
$this->expectDeprecation('Since symfony/http-client 7.3: Passing a "Symfony\Component\HttpKernel\HttpCache\StoreInterface" as constructor\'s 2nd argument of "Symfony\Component\HttpClient\CachingHttpClient" is deprecated, "Symfony\Component\Cache\Adapter\TagAwareAdapterInterface" expected.');
54+
$this->expectDeprecation('Since symfony/http-client 7.3: Passing a "Symfony\Component\HttpKernel\HttpCache\StoreInterface" as constructor\'s 2nd argument of "Symfony\Component\HttpClient\CachingHttpClient" is deprecated, "Symfony\Contracts\Cache\TagAwareCacheInterface" expected.');
5555

5656
$body = file_get_contents(__DIR__.'/Fixtures/assertion_failure.php');
5757
$response = $this->runRequest(new MockResponse($body, ['response_headers' => ['X-Body-Eval' => true]]));
@@ -63,7 +63,7 @@ public function testDoesNotEvaluateResponseBody()
6363

6464
public function testDoesNotIncludeFile()
6565
{
66-
$this->expectDeprecation('Since symfony/http-client 7.3: Passing a "Symfony\Component\HttpKernel\HttpCache\StoreInterface" as constructor\'s 2nd argument of "Symfony\Component\HttpClient\CachingHttpClient" is deprecated, "Symfony\Component\Cache\Adapter\TagAwareAdapterInterface" expected.');
66+
$this->expectDeprecation('Since symfony/http-client 7.3: Passing a "Symfony\Component\HttpKernel\HttpCache\StoreInterface" as constructor\'s 2nd argument of "Symfony\Component\HttpClient\CachingHttpClient" is deprecated, "Symfony\Contracts\Cache\TagAwareCacheInterface" expected.');
6767

6868
$file = __DIR__.'/Fixtures/assertion_failure.php';
6969

@@ -82,7 +82,7 @@ public function testDoesNotIncludeFile()
8282

8383
public function testDoesNotReadFile()
8484
{
85-
$this->expectDeprecation('Since symfony/http-client 7.3: Passing a "Symfony\Component\HttpKernel\HttpCache\StoreInterface" as constructor\'s 2nd argument of "Symfony\Component\HttpClient\CachingHttpClient" is deprecated, "Symfony\Component\Cache\Adapter\TagAwareAdapterInterface" expected.');
85+
$this->expectDeprecation('Since symfony/http-client 7.3: Passing a "Symfony\Component\HttpKernel\HttpCache\StoreInterface" as constructor\'s 2nd argument of "Symfony\Component\HttpClient\CachingHttpClient" is deprecated, "Symfony\Contracts\Cache\TagAwareCacheInterface" expected.');
8686

8787
$file = __DIR__.'/Fixtures/assertion_failure.php';
8888

@@ -99,7 +99,7 @@ public function testDoesNotReadFile()
9999

100100
public function testRemovesXContentDigest()
101101
{
102-
$this->expectDeprecation('Since symfony/http-client 7.3: Passing a "Symfony\Component\HttpKernel\HttpCache\StoreInterface" as constructor\'s 2nd argument of "Symfony\Component\HttpClient\CachingHttpClient" is deprecated, "Symfony\Component\Cache\Adapter\TagAwareAdapterInterface" expected.');
102+
$this->expectDeprecation('Since symfony/http-client 7.3: Passing a "Symfony\Component\HttpKernel\HttpCache\StoreInterface" as constructor\'s 2nd argument of "Symfony\Component\HttpClient\CachingHttpClient" is deprecated, "Symfony\Contracts\Cache\TagAwareCacheInterface" expected.');
103103

104104
$response = $this->runRequest(new MockResponse(
105105
'test', [

0 commit comments

Comments
 (0)