Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[WIP] [Cache] Allow to chain adapters #17452

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 56 additions & 11 deletions src/Symfony/Component/Cache/Adapter/AbstractAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,43 @@
namespace Symfony\Component\Cache\Adapter;

use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Cache\Exception\InvalidArgumentException;

/**
* @author Nicolas Grekas <[email protected]>
*/
abstract class AbstractAdapter implements CacheItemPoolInterface
abstract class AbstractAdapter implements AdapterInterface
{
/**
* @var string
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would remove these docblocks. They are pretty useless as IDEs should be able to infer the type from the initialisation in the constructor.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're not always looking at the code via your IDE. Imo those doc blocks are valuable until you can do a private AdapterInterface $decorated; for example.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would remove them as well. They are verbose, annoying and don't add anything useful.

private $namespace;

/**
* @var AdapterInterface
*/
private $decorated;

/**
* @var array
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. Just by looking at the default value, I know this is an array.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR has been replaced by #17556. The new one doesn't include docblocks changes anymore.

*/
private $deferred = array();

/**
* @var \Closure
*/
private $createCacheItem;

/**
* @var \Closure
*/
private $mergeByLifetime;

protected function __construct($namespace = '', $defaultLifetime = 0)
protected function __construct($namespace = '', $defaultLifetime = 0, AdapterInterface $decorated = null)
{
$this->namespace = $namespace;
$this->decorated = $decorated;
$this->createCacheItem = \Closure::bind(
function ($key, $value, $isHit) use ($defaultLifetime) {
$item = new CacheItem();
Expand Down Expand Up @@ -109,7 +129,6 @@ abstract protected function doSave(array $values, $lifetime);
public function getItem($key)
{
$id = $this->getId($key);

if ($this->deferred) {
$this->commit();
}
Expand All @@ -125,6 +144,10 @@ public function getItem($key)
$isHit = true;
}

if (!$isHit && $this->decorated) {
return $this->decorated->getItem($key);
}

return $f($key, $value, $isHit);
}

Expand Down Expand Up @@ -154,6 +177,13 @@ public function getItems(array $keys = array())

foreach ($ids as $key => $id) {
$isHit = isset($values[$id]);

if (!$isHit && $this->decorated) {
$items[$key] = $this->getItem($key);

continue;
}

$items[$key] = $f($key, $isHit ? $values[$id] : null, $isHit);
}

Expand All @@ -169,7 +199,13 @@ public function hasItem($key)
$this->commit();
}

return $this->doHave($this->getId($key));
$got = $this->doHave($this->getId($key));

if ($got || !$this->decorated) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the other places we have this condition the other way around (checking if we did not find anything and then calling the decorated adapter). For consistency, I suggest to do the same here too.

return $got;
}

return $this->decorated->hasItem($key);
}

/**
Expand All @@ -178,16 +214,19 @@ public function hasItem($key)
public function clear()
{
$this->deferred = array();
$cleared = $this->decorated ? $this->decorated->clear() : true;

return $this->doClear();
return $this->doClear() && $cleared;
}

/**
* {@inheritdoc}
*/
public function deleteItem($key)
{
return $this->deleteItems(array($key));
$deleted = $this->decorated ? $this->decorated->deleteItem($key) : true;

return $this->deleteItems(array($key)) && $deleted;
}

/**
Expand All @@ -202,7 +241,9 @@ public function deleteItems(array $keys)
unset($this->deferred[$key]);
}

return $this->doDelete($ids);
$deleted = $this->decorated ? $this->decorated->deleteItems($keys) : true;

return $this->doDelete($ids) && $deleted;
}

/**
Expand All @@ -217,7 +258,9 @@ public function save(CacheItemInterface $item)
$this->deferred[$key] = $item;
$this->commit();

return !isset($this->deferred[$key]);
$saved = $this->decorated ? $this->decorated->save($item) : true;

return !isset($this->deferred[$key]) && $saved;
}

/**
Expand All @@ -240,7 +283,7 @@ public function saveDeferred(CacheItemInterface $item)
}
$this->deferred[$item->getKey()] = $item;

return true;
return $this->decorated ? $this->decorated->saveDeferred($item) : true;
}

/**
Expand All @@ -265,7 +308,9 @@ public function commit()
}
}

return !$this->deferred = $ko;
$committed = $this->decorated ? $this->decorated->commit() : true;

return !($this->deferred = $ko) && $committed;
}

public function __destruct()
Expand Down
23 changes: 23 additions & 0 deletions src/Symfony/Component/Cache/Adapter/AdapterInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Cache\Adapter;

use Psr\Cache\CacheItemPoolInterface;

/**
* Marker interface for adapters managing \Symfony\Component\Cache\CacheItem instances.
*
* @author Kévin Dunglas <[email protected]>
*/
interface AdapterInterface extends CacheItemPoolInterface
{
}
4 changes: 2 additions & 2 deletions src/Symfony/Component/Cache/Adapter/ApcuAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@
*/
class ApcuAdapter extends AbstractAdapter
{
public function __construct($namespace = '', $defaultLifetime = 0)
public function __construct($namespace = '', $defaultLifetime = 0, AdapterInterface $decorated = null)
{
if (!function_exists('apcu_fetch') || !ini_get('apc.enabled') || ('cli' === PHP_SAPI && !ini_get('apc.enable_cli'))) {
throw new CacheException('APCu is not enabled');
}
if ('cli' === PHP_SAPI) {
ini_set('apc.use_request_time', 0);
}
parent::__construct($namespace, $defaultLifetime);
parent::__construct($namespace, $defaultLifetime, $decorated);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Component/Cache/Adapter/ArrayAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
/**
* @author Nicolas Grekas <[email protected]>
*/
class ArrayAdapter implements CacheItemPoolInterface
class ArrayAdapter implements AdapterInterface
{
private $values = array();
private $expiries = array();
Expand Down
4 changes: 2 additions & 2 deletions src/Symfony/Component/Cache/Adapter/DoctrineAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ class DoctrineAdapter extends AbstractAdapter
{
private $provider;

public function __construct(CacheProvider $provider, $defaultLifetime = null)
public function __construct(CacheProvider $provider, $defaultLifetime = null, AdapterInterface $decorated = null)
{
parent::__construct('', $defaultLifetime);
parent::__construct('', $defaultLifetime, $decorated);
$this->provider = $provider;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Component/Cache/Adapter/ProxyAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
/**
* @author Nicolas Grekas <[email protected]>
*/
class ProxyAdapter implements CacheItemPoolInterface
class ProxyAdapter implements AdapterInterface
{
private $pool;
private $createCacheItem;
Expand Down
26 changes: 26 additions & 0 deletions src/Symfony/Component/Cache/Tests/Adapter/AdapterDecoratorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Cache\Tests\Adapter;

use Cache\IntegrationTests\CachePoolTest;
use Symfony\Component\Cache\Adapter\ApcuAdapter;

/**
* @author Kévin Dunglas <[email protected]>
*/
class AdapterDecoratorTest extends CachePoolTest
{
public function createCachePool()
{
return new ApcuAdapter(__CLASS__, 0, new ApcuAdapter());
}
}