Skip to content

Commit

Permalink
Use NullCacheItemPool when using a Paginator.
Browse files Browse the repository at this point in the history
This fixes a bug where Doctrine would recreate the DQL to SQL parsing
cache on every request which would fill up OPCache with duplicates.
We now use a "Null" cache implementation instead of calling
Query::expireQueryCache().
@see doctrine#9917
  • Loading branch information
Charles Megard committed Oct 4, 2022
1 parent cbf141f commit 89722a6
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 1 deletion.
59 changes: 59 additions & 0 deletions lib/Doctrine/ORM/Cache/NullCacheItem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);

namespace Doctrine\ORM\Cache;

use Psr\Cache\CacheItemInterface;

/**
* @internal this class is used as a workaround for a cache issue.
*
* @see https://github.com/doctrine/orm/pull/10095
*/
final class NullCacheItem implements CacheItemInterface
{
public function getKey(): string
{
return '';
}

/**
* {@inheritdoc}
*
* @return mixed
*/
public function get()
{
return null;
}

public function isHit(): bool
{
return false;
}

/**
* {@inheritdoc}
*/
public function set($value): self
{
return $this;
}

/**
* {@inheritdoc}
*/
public function expiresAt($expiration): self
{
return $this;
}

/**
* {@inheritdoc}
*/
public function expiresAfter($time): self
{
return $this;
}
}
107 changes: 107 additions & 0 deletions lib/Doctrine/ORM/Cache/NullCacheItemPool.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

declare(strict_types=1);

namespace Doctrine\ORM\Cache;

use Closure;
use Doctrine\Common\Cache\Psr6\CacheItem;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
use Traversable;

/**
* @internal this class is used as a workaround for a cache issue.
*
* @see https://github.com/doctrine/orm/pull/10095
*/
final class NullCacheItemPool implements CacheItemPoolInterface
{
/** @var Closure|null */
private static $createCacheItem;

public function __construct()
{
self::$createCacheItem ?? self::$createCacheItem = Closure::bind(
static function (string $key) {
return new NullCacheItem();
},
null,
CacheItem::class
);
}

/**
* {@inheritdoc}
*/
public function getItem($key): CacheItemInterface
{
return (self::$createCacheItem)($key);
}

/**
* {@inheritdoc}
*/
public function getItems(array $keys = []): Traversable
{
return $this->generateItems($keys);
}

/**
* {@inheritdoc}
*/
public function hasItem($key): bool
{
return false;
}

public function clear(string $prefix = ''): bool
{
return true;
}

/**
* {@inheritdoc}
*/
public function deleteItem($key): bool
{
return true;
}

/**
* {@inheritdoc}
*/
public function deleteItems(array $keys): bool
{
return true;
}

public function save(CacheItemInterface $item): bool
{
return true;
}

public function saveDeferred(CacheItemInterface $item): bool
{
return true;
}

public function commit(): bool
{
return true;
}

/**
* @param array<string> $keys
*
* @return Traversable<CacheItem>
*/
private function generateItems(array $keys): Traversable
{
$f = self::$createCacheItem;

foreach ($keys as $key) {
yield $key => $f($key);
}
}
}
3 changes: 2 additions & 1 deletion lib/Doctrine/ORM/Tools/Pagination/Paginator.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use ArrayIterator;
use Countable;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Cache\NullCacheItemPool;
use Doctrine\ORM\Internal\SQLResultCasing;
use Doctrine\ORM\NoResultException;
use Doctrine\ORM\Query;
Expand Down Expand Up @@ -160,7 +161,7 @@ public function getIterator()
$whereInQuery->setFirstResult(0)->setMaxResults(null);
$whereInQuery->setParameter(WhereInWalker::PAGINATOR_ID_ALIAS, $ids);
$whereInQuery->setCacheable($this->query->isCacheable());
$whereInQuery->expireQueryCache();
$whereInQuery->setQueryCache(new NullCacheItemPool());

$result = $whereInQuery->getResult($this->query->getHydrationMode());
} else {
Expand Down

0 comments on commit 89722a6

Please sign in to comment.