[Cache] boost perf by wrapping keys validity checks with assert()

This commit is contained in:
Nicolas Grekas 2021-02-26 12:00:53 +01:00
parent 60ce52f503
commit 8f03a1f555
15 changed files with 145 additions and 93 deletions

View File

@ -39,10 +39,11 @@ abstract class AbstractAdapter implements AdapterInterface, CacheInterface, Logg
protected function __construct(string $namespace = '', int $defaultLifetime = 0)
{
$this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).static::NS_SEPARATOR;
$this->defaultLifetime = $defaultLifetime;
if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) {
throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s").', $this->maxIdLength - 24, \strlen($namespace), $namespace));
}
$this->createCacheItem = \Closure::bind(
self::$createCacheItem ?? self::$createCacheItem = \Closure::bind(
static function ($key, $value, $isHit) {
$item = new CacheItem();
$item->key = $key;
@ -63,9 +64,8 @@ abstract class AbstractAdapter implements AdapterInterface, CacheInterface, Logg
null,
CacheItem::class
);
$getId = \Closure::fromCallable([$this, 'getId']);
$this->mergeByLifetime = \Closure::bind(
static function ($deferred, $namespace, &$expiredIds) use ($getId, $defaultLifetime) {
self::$mergeByLifetime ?? self::$mergeByLifetime = \Closure::bind(
static function ($deferred, $namespace, &$expiredIds, $getId, $defaultLifetime) {
$byLifetime = [];
$now = microtime(true);
$expiredIds = [];
@ -147,8 +147,7 @@ abstract class AbstractAdapter implements AdapterInterface, CacheInterface, Logg
public function commit()
{
$ok = true;
$byLifetime = $this->mergeByLifetime;
$byLifetime = $byLifetime($this->deferred, $this->namespace, $expiredIds);
$byLifetime = (self::$mergeByLifetime)($this->deferred, $this->namespace, $expiredIds, \Closure::fromCallable([$this, 'getId']), $this->defaultLifetime);
$retry = $this->deferred = [];
if ($expiredIds) {

View File

@ -40,10 +40,11 @@ abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagA
protected function __construct(string $namespace = '', int $defaultLifetime = 0)
{
$this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':';
$this->defaultLifetime = $defaultLifetime;
if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) {
throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s").', $this->maxIdLength - 24, \strlen($namespace), $namespace));
}
$this->createCacheItem = \Closure::bind(
self::$createCacheItem ?? self::$createCacheItem = \Closure::bind(
static function ($key, $value, $isHit) {
$item = new CacheItem();
$item->key = $key;
@ -68,10 +69,8 @@ abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagA
null,
CacheItem::class
);
$getId = \Closure::fromCallable([$this, 'getId']);
$tagPrefix = self::TAGS_PREFIX;
$this->mergeByLifetime = \Closure::bind(
static function ($deferred, &$expiredIds) use ($getId, $tagPrefix, $defaultLifetime) {
self::$mergeByLifetime ?? self::$mergeByLifetime = \Closure::bind(
static function ($deferred, &$expiredIds, $getId, $tagPrefix, $defaultLifetime) {
$byLifetime = [];
$now = microtime(true);
$expiredIds = [];
@ -175,8 +174,7 @@ abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagA
public function commit(): bool
{
$ok = true;
$byLifetime = $this->mergeByLifetime;
$byLifetime = $byLifetime($this->deferred, $expiredIds);
$byLifetime = (self::$mergeByLifetime)($this->deferred, $expiredIds, \Closure::fromCallable([$this, 'getId']), self::TAGS_PREFIX, $this->defaultLifetime);
$retry = $this->deferred = [];
if ($expiredIds) {

View File

@ -33,11 +33,12 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
private $storeSerialized;
private $values = [];
private $expiries = [];
private $createCacheItem;
private $defaultLifetime;
private $maxLifetime;
private $maxItems;
private static $createCacheItem;
/**
* @param bool $storeSerialized Disabling serialization can lead to cache corruptions when storing mutable values but increases performance otherwise
*/
@ -55,7 +56,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
$this->storeSerialized = $storeSerialized;
$this->maxLifetime = $maxLifetime;
$this->maxItems = $maxItems;
$this->createCacheItem = \Closure::bind(
self::$createCacheItem ?? self::$createCacheItem = \Closure::bind(
static function ($key, $value, $isHit) {
$item = new CacheItem();
$item->key = $key;
@ -111,7 +112,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
return true;
}
CacheItem::validateKey($key);
\assert('' !== CacheItem::validateKey($key));
return isset($this->expiries[$key]) && !$this->deleteItem($key);
}
@ -131,9 +132,8 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
} else {
$value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key];
}
$f = $this->createCacheItem;
return $f($key, $value, $isHit);
return (self::$createCacheItem)($key, $value, $isHit);
}
/**
@ -141,13 +141,9 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
*/
public function getItems(array $keys = [])
{
foreach ($keys as $key) {
if (!\is_string($key) || !isset($this->expiries[$key])) {
CacheItem::validateKey($key);
}
}
\assert(self::validateKeys($keys));
return $this->generateItems($keys, microtime(true), $this->createCacheItem);
return $this->generateItems($keys, microtime(true), self::$createCacheItem);
}
/**
@ -157,9 +153,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
*/
public function deleteItem($key)
{
if (!\is_string($key) || !isset($this->expiries[$key])) {
CacheItem::validateKey($key);
}
\assert('' !== CacheItem::validateKey($key));
unset($this->values[$key], $this->expiries[$key]);
return true;
@ -395,4 +389,15 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter
return $value;
}
private function validateKeys(array $keys): bool
{
foreach ($keys as $key) {
if (!\is_string($key) || !isset($this->expiries[$key])) {
CacheItem::validateKey($key);
}
}
return true;
}
}

View File

@ -35,7 +35,9 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
private $adapters = [];
private $adapterCount;
private $syncItem;
private $defaultLifetime;
private static $syncItem;
/**
* @param CacheItemPoolInterface[] $adapters The ordered list of adapters used to fetch cached items
@ -62,9 +64,10 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
}
}
$this->adapterCount = \count($this->adapters);
$this->defaultLifetime = $defaultLifetime;
$this->syncItem = \Closure::bind(
static function ($sourceItem, $item, $sourceMetadata = null) use ($defaultLifetime) {
self::$syncItem ?? self::$syncItem = \Closure::bind(
static function ($sourceItem, $item, $defaultLifetime, $sourceMetadata = null) {
$sourceItem->isTaggable = false;
$sourceMetadata = $sourceMetadata ?? $sourceItem->metadata;
unset($sourceMetadata[CacheItem::METADATA_TAGS]);
@ -105,7 +108,7 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
$value = $this->doGet($adapter, $key, $callback, $beta, $metadata);
}
if (null !== $item) {
($this->syncItem)($lastItem = $lastItem ?? $item, $item, $metadata);
(self::$syncItem)($lastItem = $lastItem ?? $item, $item, $this->defaultLifetime, $metadata);
}
return $value;
@ -119,7 +122,7 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
*/
public function getItem($key)
{
$syncItem = $this->syncItem;
$syncItem = self::$syncItem;
$misses = [];
foreach ($this->adapters as $i => $adapter) {
@ -127,7 +130,7 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
if ($item->isHit()) {
while (0 <= --$i) {
$this->adapters[$i]->save($syncItem($item, $misses[$i]));
$this->adapters[$i]->save($syncItem($item, $misses[$i], $this->defaultLifetime));
}
return $item;
@ -164,13 +167,13 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
}
if ($missing) {
$syncItem = $this->syncItem;
$syncItem = self::$syncItem;
$adapter = $this->adapters[$adapterIndex];
$items = $this->generateItems($nextAdapter->getItems($missing), $nextAdapterIndex);
foreach ($items as $k => $item) {
if ($item->isHit()) {
$adapter->save($syncItem($item, $misses[$k]));
$adapter->save($syncItem($item, $misses[$k], $this->defaultLifetime));
}
yield $k => $item;

View File

@ -20,19 +20,19 @@ use Symfony\Contracts\Cache\CacheInterface;
*/
class NullAdapter implements AdapterInterface, CacheInterface
{
private $createCacheItem;
private static $createCacheItem;
public function __construct()
{
$this->createCacheItem = \Closure::bind(
function ($key) {
self::$createCacheItem ?? self::$createCacheItem = \Closure::bind(
static function ($key) {
$item = new CacheItem();
$item->key = $key;
$item->isHit = false;
return $item;
},
$this,
null,
CacheItem::class
);
}
@ -44,7 +44,7 @@ class NullAdapter implements AdapterInterface, CacheInterface
{
$save = true;
return $callback(($this->createCacheItem)($key), $save);
return $callback((self::$createCacheItem)($key), $save);
}
/**
@ -52,9 +52,7 @@ class NullAdapter implements AdapterInterface, CacheInterface
*/
public function getItem($key)
{
$f = $this->createCacheItem;
return $f($key);
return (self::$createCacheItem)($key);
}
/**
@ -145,7 +143,7 @@ class NullAdapter implements AdapterInterface, CacheInterface
private function generateItems(array $keys)
{
$f = $this->createCacheItem;
$f = self::$createCacheItem;
foreach ($keys as $key) {
yield $key => $f($key);

View File

@ -37,8 +37,8 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte
private $file;
private $keys;
private $values;
private $createCacheItem;
private static $createCacheItem;
private static $valuesCache = [];
/**
@ -49,7 +49,7 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte
{
$this->file = $file;
$this->pool = $fallbackPool;
$this->createCacheItem = \Closure::bind(
self::$createCacheItem ?? self::$createCacheItem = \Closure::bind(
static function ($key, $value, $isHit) {
$item = new CacheItem();
$item->key = $key;
@ -142,9 +142,7 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte
}
}
$f = $this->createCacheItem;
return $f($key, $value, $isHit);
return (self::$createCacheItem)($key, $value, $isHit);
}
/**
@ -407,7 +405,7 @@ EOF;
private function generateItems(array $keys): \Generator
{
$f = $this->createCacheItem;
$f = self::$createCacheItem;
$fallbackKeys = [];
foreach ($keys as $key) {

View File

@ -28,22 +28,26 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
use ContractsTrait;
use ProxyTrait;
private $namespace;
private $namespace = '';
private $namespaceLen;
private $createCacheItem;
private $setInnerItem;
private $poolHash;
private $defaultLifetime;
private static $createCacheItem;
private static $setInnerItem;
public function __construct(CacheItemPoolInterface $pool, string $namespace = '', int $defaultLifetime = 0)
{
$this->pool = $pool;
$this->poolHash = $poolHash = spl_object_hash($pool);
$this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace);
if ('' !== $namespace) {
\assert('' !== CacheItem::validateKey($namespace));
$this->namespace = $namespace;
}
$this->namespaceLen = \strlen($namespace);
$this->defaultLifetime = $defaultLifetime;
$this->createCacheItem = \Closure::bind(
static function ($key, $innerItem) use ($poolHash) {
self::$createCacheItem ?? self::$createCacheItem = \Closure::bind(
static function ($key, $innerItem, $poolHash) {
$item = new CacheItem();
$item->key = $key;
@ -74,7 +78,7 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
null,
CacheItem::class
);
$this->setInnerItem = \Closure::bind(
self::$setInnerItem ?? self::$setInnerItem = \Closure::bind(
/**
* @param array $item A CacheItem cast to (array); accessing protected properties requires adding the "\0*\0" PHP prefix
*/
@ -105,9 +109,9 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
}
return $this->pool->get($this->getId($key), function ($innerItem, bool &$save) use ($key, $callback) {
$item = ($this->createCacheItem)($key, $innerItem);
$item = (self::$createCacheItem)($key, $innerItem, $this->poolHash);
$item->set($value = $callback($item, $save));
($this->setInnerItem)($innerItem, (array) $item);
(self::$setInnerItem)($innerItem, (array) $item);
return $value;
}, $beta, $metadata);
@ -118,10 +122,9 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
*/
public function getItem($key)
{
$f = $this->createCacheItem;
$item = $this->pool->getItem($this->getId($key));
return $f($key, $item);
return (self::$createCacheItem)($key, $item, $this->poolHash);
}
/**
@ -233,33 +236,32 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa
} elseif ($this->pool instanceof AdapterInterface) {
// this is an optimization specific for AdapterInterface implementations
// so we can save a round-trip to the backend by just creating a new item
$f = $this->createCacheItem;
$innerItem = $f($this->namespace.$item["\0*\0key"], null);
$innerItem = (self::$createCacheItem)($this->namespace.$item["\0*\0key"], null, $this->poolHash);
} else {
$innerItem = $this->pool->getItem($this->namespace.$item["\0*\0key"]);
}
($this->setInnerItem)($innerItem, $item);
(self::$setInnerItem)($innerItem, $item);
return $this->pool->$method($innerItem);
}
private function generateItems(iterable $items)
{
$f = $this->createCacheItem;
$f = self::$createCacheItem;
foreach ($items as $key => $item) {
if ($this->namespaceLen) {
$key = substr($key, $this->namespaceLen);
}
yield $key => $f($key, $item);
yield $key => $f($key, $item, $this->poolHash);
}
}
private function getId($key): string
{
CacheItem::validateKey($key);
\assert('' !== CacheItem::validateKey($key));
return $this->namespace.$key;
}

View File

@ -31,20 +31,21 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
use ProxyTrait;
private $deferred = [];
private $createCacheItem;
private $setCacheItemTags;
private $getTagsByKey;
private $invalidateTags;
private $tags;
private $knownTagVersions = [];
private $knownTagVersionsTtl;
private static $createCacheItem;
private static $setCacheItemTags;
private static $getTagsByKey;
private static $invalidateTags;
public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null, float $knownTagVersionsTtl = 0.15)
{
$this->pool = $itemsPool;
$this->tags = $tagsPool ?: $itemsPool;
$this->knownTagVersionsTtl = $knownTagVersionsTtl;
$this->createCacheItem = \Closure::bind(
self::$createCacheItem ?? self::$createCacheItem = \Closure::bind(
static function ($key, $value, CacheItem $protoItem) {
$item = new CacheItem();
$item->key = $key;
@ -57,7 +58,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
null,
CacheItem::class
);
$this->setCacheItemTags = \Closure::bind(
self::$setCacheItemTags ?? self::$setCacheItemTags = \Closure::bind(
static function (CacheItem $item, $key, array &$itemTags) {
$item->isTaggable = true;
if (!$item->isHit) {
@ -78,7 +79,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
null,
CacheItem::class
);
$this->getTagsByKey = \Closure::bind(
self::$getTagsByKey ?? self::$getTagsByKey = \Closure::bind(
static function ($deferred) {
$tagsByKey = [];
foreach ($deferred as $key => $item) {
@ -91,7 +92,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
null,
CacheItem::class
);
$this->invalidateTags = \Closure::bind(
self::$invalidateTags ?? self::$invalidateTags = \Closure::bind(
static function (AdapterInterface $tagsAdapter, array $tags) {
foreach ($tags as $v) {
$v->expiry = 0;
@ -114,7 +115,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
$tagsByKey = [];
$invalidatedTags = [];
foreach ($tags as $tag) {
CacheItem::validateKey($tag);
\assert('' !== CacheItem::validateKey($tag));
$invalidatedTags[$tag] = 0;
}
@ -127,13 +128,12 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
}
}
$f = $this->getTagsByKey;
$tagsByKey = $f($items);
$tagsByKey = (self::$getTagsByKey)($items);
$this->deferred = [];
}
$tagVersions = $this->getTagVersions($tagsByKey, $invalidatedTags);
$f = $this->createCacheItem;
$f = self::$createCacheItem;
foreach ($tagsByKey as $key => $tags) {
$this->pool->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key]));
@ -141,8 +141,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
$ok = $this->pool->commit() && $ok;
if ($invalidatedTags) {
$f = $this->invalidateTags;
$ok = $f($this->tags, $invalidatedTags) && $ok;
$ok = (self::$invalidateTags)($this->tags, $invalidatedTags) && $ok;
}
return $ok;
@ -329,7 +328,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac
private function generateItems(iterable $items, array $tagKeys)
{
$bufferedItems = $itemTags = [];
$f = $this->setCacheItemTags;
$f = self::$setCacheItemTags;
foreach ($items as $key => $item) {
if (!$tagKeys) {

View File

@ -59,7 +59,7 @@ class EarlyExpirationHandler implements MessageHandlerInterface
static $setMetadata;
$setMetadata = $setMetadata ?? \Closure::bind(
$setMetadata ?? $setMetadata = \Closure::bind(
function (CacheItem $item, float $startTime) {
if ($item->expiry > $endTime = microtime(true)) {
$item->newMetadata[CacheItem::METADATA_EXPIRY] = $item->expiry;

View File

@ -45,7 +45,12 @@ class Psr16Cache implements CacheInterface, PruneableInterface, ResettableInterf
static function ($key, $value, $allowInt = false) use (&$cacheItemPrototype) {
$item = clone $cacheItemPrototype;
$item->poolHash = $item->innerItem = null;
$item->key = $allowInt && \is_int($key) ? (string) $key : CacheItem::validateKey($key);
if ($allowInt && \is_int($key)) {
$item->key = (string) $key;
} else {
\assert('' !== CacheItem::validateKey($key));
$item->key = $key;
}
$item->value = $value;
$item->isHit = false;

View File

@ -28,6 +28,16 @@ abstract class AdapterTestCase extends CachePoolTest
if (!\array_key_exists('testPrune', $this->skippedTests) && !$this->createCachePool() instanceof PruneableInterface) {
$this->skippedTests['testPrune'] = 'Not a pruneable cache pool.';
}
try {
\assert(false === true, new \Exception());
$this->skippedTests['testGetItemInvalidKeys'] =
$this->skippedTests['testGetItemsInvalidKeys'] =
$this->skippedTests['testHasItemInvalidKeys'] =
$this->skippedTests['testDeleteItemInvalidKeys'] =
$this->skippedTests['testDeleteItemsInvalidKeys'] = 'Keys are checked only when assert() is enabled.';
} catch (\Exception $e) {
}
}
public function testGet()

View File

@ -10,6 +10,26 @@ use Symfony\Component\Cache\Psr16Cache;
class Psr16CacheProxyTest extends SimpleCacheTest
{
protected function setUp(): void
{
parent::setUp();
try {
\assert(false === true, new \Exception());
$this->skippedTests['testGetInvalidKeys'] =
$this->skippedTests['testGetMultipleInvalidKeys'] =
$this->skippedTests['testGetMultipleNoIterable'] =
$this->skippedTests['testSetInvalidKeys'] =
$this->skippedTests['testSetMultipleInvalidKeys'] =
$this->skippedTests['testSetMultipleNoIterable'] =
$this->skippedTests['testHasInvalidKeys'] =
$this->skippedTests['testDeleteInvalidKeys'] =
$this->skippedTests['testDeleteMultipleInvalidKeys'] =
$this->skippedTests['testDeleteMultipleNoIterable'] = 'Keys are checked only when assert() is enabled.';
} catch (\Exception $e) {
}
}
public function createSimpleCache(int $defaultLifetime = 0): CacheInterface
{
return new Psr16Cache(new ProxyAdapter(new ArrayAdapter($defaultLifetime), 'my-namespace.'));

View File

@ -38,6 +38,21 @@ class Psr16CacheTest extends SimpleCacheTest
if (!$pool instanceof PruneableInterface) {
$this->skippedTests['testPrune'] = 'Not a pruneable cache pool.';
}
try {
\assert(false === true, new \Exception());
$this->skippedTests['testGetInvalidKeys'] =
$this->skippedTests['testGetMultipleInvalidKeys'] =
$this->skippedTests['testGetMultipleNoIterable'] =
$this->skippedTests['testSetInvalidKeys'] =
$this->skippedTests['testSetMultipleInvalidKeys'] =
$this->skippedTests['testSetMultipleNoIterable'] =
$this->skippedTests['testHasInvalidKeys'] =
$this->skippedTests['testDeleteInvalidKeys'] =
$this->skippedTests['testDeleteMultipleInvalidKeys'] =
$this->skippedTests['testDeleteMultipleNoIterable'] = 'Keys are checked only when assert() is enabled.';
} catch (\Exception $e) {
}
}
public function createSimpleCache(int $defaultLifetime = 0): CacheInterface

View File

@ -28,14 +28,15 @@ trait AbstractAdapterTrait
/**
* @var \Closure needs to be set by class, signature is function(string <key>, mixed <value>, bool <isHit>)
*/
private $createCacheItem;
private static $createCacheItem;
/**
* @var \Closure needs to be set by class, signature is function(array <deferred>, string <namespace>, array <&expiredIds>)
*/
private $mergeByLifetime;
private static $mergeByLifetime;
private $namespace;
private $namespace = '';
private $defaultLifetime;
private $namespaceVersion = '';
private $versioningIsEnabled = false;
private $deferred = [];
@ -212,7 +213,6 @@ trait AbstractAdapterTrait
}
$id = $this->getId($key);
$f = $this->createCacheItem;
$isHit = false;
$value = null;
@ -221,12 +221,12 @@ trait AbstractAdapterTrait
$isHit = true;
}
return $f($key, $value, $isHit);
return (self::$createCacheItem)($key, $value, $isHit);
} catch (\Exception $e) {
CacheItem::log($this->logger, 'Failed to fetch key "{key}": '.$e->getMessage(), ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]);
}
return $f($key, null, false);
return (self::$createCacheItem)($key, null, false);
}
/**
@ -336,7 +336,7 @@ trait AbstractAdapterTrait
private function generateItems(iterable $items, array &$keys): iterable
{
$f = $this->createCacheItem;
$f = self::$createCacheItem;
try {
foreach ($items as $id => $value) {
@ -376,7 +376,7 @@ trait AbstractAdapterTrait
if (\is_string($key) && isset($this->ids[$key])) {
return $this->namespace.$this->namespaceVersion.$this->ids[$key];
}
CacheItem::validateKey($key);
\assert('' !== CacheItem::validateKey($key));
$this->ids[$key] = $key;
if (null === $this->maxIdLength) {

View File

@ -57,7 +57,7 @@ trait ContractsTrait
static $setMetadata;
$setMetadata = $setMetadata ?? \Closure::bind(
$setMetadata ?? $setMetadata = \Closure::bind(
static function (CacheItem $item, float $startTime, ?array &$metadata) {
if ($item->expiry > $endTime = microtime(true)) {
$item->newMetadata[CacheItem::METADATA_EXPIRY] = $metadata[CacheItem::METADATA_EXPIRY] = $item->expiry;