From 12de2aeb33315af59792e07b23e383c24e407117 Mon Sep 17 00:00:00 2001 From: Rob Frawley 2nd Date: Sun, 4 Dec 2016 19:46:13 -0500 Subject: [PATCH] memcached cache pool adapter --- .../Cache/Adapter/MemcachedAdapter.php | 80 +++++++++++++++++++ .../Tests/Adapter/MemcachedAdapterTest.php | 50 ++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php create mode 100644 src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php diff --git a/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php b/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php new file mode 100644 index 000000000000..3451dd02eb72 --- /dev/null +++ b/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +/** + * @author Rob Frawley 2nd + */ +class MemcachedAdapter extends AbstractAdapter +{ + private $client; + + public static function isSupported() + { + return extension_loaded('memcached') && version_compare(phpversion('memcached'), '2.2.0', '>='); + } + + public function __construct(\Memcached $client, $namespace = '', $defaultLifetime = 0) + { + parent::__construct($namespace, $defaultLifetime); + $this->client = $client; + } + + /** + * {@inheritdoc} + */ + protected function doSave(array $values, $lifetime) + { + return $this->client->setMulti($values, $lifetime) + && $this->client->getResultCode() === \Memcached::RES_SUCCESS; + } + + /** + * {@inheritdoc} + */ + protected function doFetch(array $ids) + { + return $this->client->getMulti($ids); + } + + /** + * {@inheritdoc} + */ + protected function doHave($id) + { + return $this->client->get($id) !== false + || $this->client->getResultCode() === \Memcached::RES_SUCCESS; + } + + /** + * {@inheritdoc} + */ + protected function doDelete(array $ids) + { + $toDelete = count($ids); + foreach ($this->client->deleteMulti($ids) as $result) { + if (\Memcached::RES_SUCCESS === $result || \Memcached::RES_NOTFOUND === $result) { + --$toDelete; + } + } + + return 0 === $toDelete; + } + + /** + * {@inheritdoc} + */ + protected function doClear($namespace) + { + return $this->client->flush(); + } +} diff --git a/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php new file mode 100644 index 000000000000..55b4dc19b145 --- /dev/null +++ b/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php @@ -0,0 +1,50 @@ + + * + * 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 Symfony\Component\Cache\Adapter\MemcachedAdapter; + +class MemcachedAdapterTest extends AdapterTestCase +{ + protected $skippedTests = array( + 'testExpiration' => 'Testing expiration slows down the test suite', + 'testHasItemReturnsFalseWhenDeferredItemIsExpired' => 'Testing expiration slows down the test suite', + 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', + ); + + private static $client; + + public static function setupBeforeClass() + { + if (!MemcachedAdapter::isSupported()) { + self::markTestSkipped('Extension memcached >=2.2.0 required.'); + } + + self::$client = new \Memcached(); + self::$client->addServers(array(array( + getenv('MEMCACHED_HOST') ?: '127.0.0.1', + getenv('MEMCACHED_PORT') ?: 11211, + ))); + + parent::setupBeforeClass(); + } + + public function createCachePool($defaultLifetime = 0) + { + return new MemcachedAdapter(self::$client, str_replace('\\', '.', __CLASS__), $defaultLifetime); + } + + public function testIsSupported() + { + $this->assertTrue(MemcachedAdapter::isSupported()); + } +}