function VariationCache::getMultiple
Overrides VariationCacheInterface::getMultiple
File
-
core/
lib/ Drupal/ Core/ Cache/ VariationCache.php, line 61
Class
- VariationCache
- Wraps a regular cache backend to make it support cache contexts.
Namespace
Drupal\Core\CacheCode
public function getMultiple(array $items) : array {
// This method does not use ::getRedirectChain() like ::get() does, because
// we are looking for multiple cache entries and can therefore optimize the
// following of redirect chains by calling ::getMultiple() on the underlying
// cache backend.
//
// However, ::getRedirectChain() has an internal cache that we could both
// benefit from and contribute to whenever we call this function. So any use
// or manipulation of $this->redirectChainCache below is for optimization
// purposes. A description of the internal cache structure is on the
// property documentation of $this->redirectChainCache.
//
// Create a map of CIDs with their associated $items index and cache keys.
$cid_map = [];
foreach ($items as $index => [
$keys,
$cacheability,
]) {
// Try to optimize based on the cached redirect chain.
if ($chain = $this->getValidatedCachedRedirectChain($keys, $cacheability)) {
$last_item = end($chain);
// Immediately skip processing the CID for cache misses.
if ($last_item === FALSE) {
continue;
}
// We do not need to calculate the initial CID as its part of the chain.
$initial_cid = array_key_first($chain);
// Prime the CID map with the last known redirect for the initial CID.
assert($last_item->data instanceof CacheRedirect);
$cid = $this->createCacheIdFast($keys, $last_item->data);
}
else {
$cid = $initial_cid = $this->createCacheIdFast($keys, $cacheability);
}
$cid_map[$cid] = [
'index' => $index,
'keys' => $keys,
'initial' => $initial_cid,
];
}
// Go over all CIDs and update the map according to found redirects. If the
// map is empty, it means we've followed all CIDs to their final result or
// lack thereof.
$results = [];
while (!empty($cid_map)) {
$new_cid_map = [];
$fetch_cids = array_keys($cid_map);
foreach ($this->cacheBackend
->getMultiple($fetch_cids) as $cid => $result) {
$info = $cid_map[$cid];
// Add redirects to the next CID map, so the next iteration can look
// them all up in one ::getMultiple() call to the cache backend.
if ($result->data instanceof CacheRedirect) {
$redirect_cid = $this->createCacheIdFast($info['keys'], $result->data);
$new_cid_map[$redirect_cid] = $info;
$this->redirectChainCache[$info['initial']][$cid] = $result;
continue;
}
$results[$info['index']] = $result;
}
// Any CID that did not get a cache hit is still in $fetch_cids. Add them
// to the internal redirect chain cache as a miss.
foreach ($fetch_cids as $fetch_cid) {
$info = $cid_map[$fetch_cid];
$this->redirectChainCache[$info['initial']][$fetch_cid] = FALSE;
}
$cid_map = $new_cid_map;
}
return $results;
}
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.