redis-8.x-1.x-dev/src/Cache/RedisCacheTagsChecksum.php
src/Cache/RedisCacheTagsChecksum.php
<?php
namespace Drupal\redis\Cache;
use Drupal\Core\Cache\CacheTagsChecksumInterface;
use Drupal\Core\Cache\CacheTagsChecksumPreloadInterface;
use Drupal\Core\Cache\CacheTagsChecksumTrait;
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
use Drupal\redis\ClientFactory;
use Drupal\redis\ClientInterface;
use Drupal\redis\RedisPrefixTrait;
// BC for Drupal 11.1 and earlier.
interface RedisCacheTagsChecksumPreloadInterface {}
if (!interface_exists(CacheTagsChecksumPreloadInterface::class)) {
// @phpstan-ignore-next-line
class_alias(RedisCacheTagsChecksumPreloadInterface::class, CacheTagsChecksumPreloadInterface::class);
}
/**
* Cache tags invalidations checksum implementation that uses redis.
*/
class RedisCacheTagsChecksum implements CacheTagsChecksumInterface, CacheTagsInvalidatorInterface, CacheTagsChecksumPreloadInterface {
use RedisPrefixTrait;
use CacheTagsChecksumTrait;
/**
* Contains already loaded cache invalidations from the database.
*
* @var array
*/
protected $tagCache = [];
/**
* A list of tags that have already been invalidated in this request.
*
* Used to prevent the invalidation of the same cache tag multiple times.
*
* @var array
*/
protected $invalidatedTags = [];
/**
* {@inheritdoc}
*/
protected ClientInterface $client;
/**
* @var string
*/
protected $clientType;
/**
* Creates a Redis cache backend.
*/
public function __construct(ClientFactory $factory) {
$this->client = $factory->getClient();
$this->clientType = $factory->getClientName();
}
/**
* {@inheritdoc}
*/
public function doInvalidateTags(array $tags) {
$keys = array_map([$this, 'getTagKey'], $tags);
$this->client->pipeline();
foreach ($keys as $key) {
$this->client->incr($key);
}
$this->client->exec();
}
/**
* {@inheritdoc}
*/
protected function getTagInvalidationCounts(array $tags) {
// Do not use MGET for a single key as Relay does not support in-memory
// caching for MGET misses.
if (count($tags) == 1) {
$tag = reset($tags);
return [$tag => (int) $this->client->get($this->getTagKey($tag))];
}
$keys = array_map([$this, 'getTagKey'], $tags);
// The mget command returns the values as an array with numeric keys,
// combine it with the tags array to get the expected return value and run
// it through intval() to convert to integers and FALSE to 0.
$values = $this->client->mget($keys);
return $values ? array_map('intval', array_combine($tags, $values)) : [];
}
/**
* Return the key for the given cache tag.
*
* @param string $tag
* The cache tag.
*
* @return string
* The prefixed cache tag.
*/
protected function getTagKey($tag) {
return $this->getPrefix() . ':cachetags:' . $tag;
}
/**
* {@inheritdoc}
*/
protected function getDatabaseConnection() {
// This is not injected to avoid a dependency on the database in the
// critical path. It is only needed during cache tag invalidations.
// @phpstan-ignore-next-line
return \Drupal::database();
}
}
