Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

RedisCache driver implementation #109

Merged
merged 4 commits into from

5 participants

Osman Üngür Benjamin Eberlei Guilherme Blanco Marco Pivetta Henrik Westphal
Osman Üngür
o commented

This class implements Redis key-value store (https://github.com/antirez/redis) as cache driver.

It uses redis php extension (https://github.com/nicolasff/phpredis) for communicating with Redis.

Running tests

To pass tests, you need to install redis to your box.

From source

wget http://download.redis.io/redis-stable.tar.gz
tar xvzf redis-stable.tar.gz
cd redis-stable
make

From apt-get

apt-get install redis-server

From homebrew

brew install redis

Then run redis-server and phpunit.

o added some commits
Osman Üngür o Added redis cache implementation
This class implements Redis key-value store (https://github.com/antirez/redis) as cache driver.

It uses phpredis extension (https://github.com/nicolasff/phpredis) for communicating with Redis.
68e48f9
Osman Üngür o Added tests 43ec9bb
Marco Pivetta Ocramius commented on the diff
lib/Doctrine/Common/Cache/RedisCache.php
((30 lines not shown))
+ * @since 2.2
+ * @author Osman Ungur <osmanungur@gmail.com>
+ */
+class RedisCache extends CacheProvider
+{
+ /**
+ * @var Redis
+ */
+ private $redis;
+
+ /**
+ * Sets the redis instance to use.
+ *
+ * @param Redis $redis
+ */
+ public function setRedis(Redis $redis)
Marco Pivetta Owner

An instance of Redis is a hard dependency of this class. To avoid confusion, you should add a constructor that accepts an instance of Redis as a required parameter.

Osman Üngür
o added a note

I know Redis class is the hard dependency of RedisCache.
But, for avoid confusion, i used same convention with MemcacheCache driver.
https://github.com/doctrine/common/blob/master/lib/Doctrine/Common/Cache/MemcacheCache.php#L49

Marco Pivetta Owner

Hmm... Yeah, makes sense, but I don't like that either... Also, modifying the MemcacheCache adapter would break BC... :(

Marco Pivetta Owner

Could you eventually add a __construct($redis = null) constructor and check if the passed in $redis is a Redis instance? That would probably fix also my request :)

Osman Üngür
o added a note

Hi Marco,
For keeping conventions same, also should add this check to MemcachedDriver.

I think we can solve this problem in another discussion/pr :)

Marco Pivetta Owner
Ocramius added a note

Yeah, I will eventually do that :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Benjamin Eberlei
Owner

I like it, didn't verify the tests work yet though.

@guilhermeblanco what do you think?

Guilherme Blanco

@beberlei to me it seems good! If all tests pass, merge

o added some commits
Osman Üngür o Fixed a problem with serializer.
With this commit, cache driver uses igbinary as default serializer. Other serializer options fails with ClassMetadata like object data.
57e46ca
Osman Üngür o Added a simple test case about serializing/unserializing objects in c…
…ache drivers.
35d68ce
Osman Üngür
o commented

Hi, tests was passed for me. Under Mac OS X 10.7.3, PHP 5.4.0, Redis 2.4

Doctrine\Tests\Common\Cache\RedisCache
 [x] Basics
 [x] Delete all
 [x] Flush all
 [x] Namespace
 [x] Get stats

Last night i committed a little serializer option fix, because phpredis SERIALIZER_PHP fails with PHP 5.4.0,
Also added a very simple test case about serializing objects.
Current tests not covers storing/fetching non-scalar (like ClassMetadata cache, QueryResult cache..) values in cache drivers.

Benjamin Eberlei beberlei merged commit 6739b28 into from
Osman Üngür o referenced this pull request from a commit in o/doctrine2
Osman Üngür o New cache driver definition for Doctrine running in non-dev mode and …
…cache driver is not set.

This cache driver was added with doctrine/common#109
4fc7389
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 29, 2012
  1. Osman Üngür

    Added redis cache implementation

    o authored
    This class implements Redis key-value store (https://github.com/antirez/redis) as cache driver.
    
    It uses phpredis extension (https://github.com/nicolasff/phpredis) for communicating with Redis.
  2. Osman Üngür

    Added tests

    o authored
Commits on Mar 18, 2012
  1. Osman Üngür

    Fixed a problem with serializer.

    o authored
    With this commit, cache driver uses igbinary as default serializer. Other serializer options fails with ClassMetadata like object data.
Commits on Mar 19, 2012
  1. Osman Üngür
This page is out of date. Refresh to see the latest.
119 lib/Doctrine/Common/Cache/RedisCache.php
View
@@ -0,0 +1,119 @@
+<?php
+
+/*
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This software consists of voluntary contributions made by many individuals
+ * and is licensed under the LGPL. For more information, see
+ * <http://www.doctrine-project.org>.
+ */
+
+namespace Doctrine\Common\Cache;
+
+use Redis;
+
+/**
+ * Redis cache provider.
+ *
+ * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
+ * @link www.doctrine-project.org
+ * @since 2.2
+ * @author Osman Ungur <osmanungur@gmail.com>
+ */
+class RedisCache extends CacheProvider
+{
+ /**
+ * @var Redis
+ */
+ private $redis;
+
+ /**
+ * Sets the redis instance to use.
+ *
+ * @param Redis $redis
+ */
+ public function setRedis(Redis $redis)
Marco Pivetta Owner

An instance of Redis is a hard dependency of this class. To avoid confusion, you should add a constructor that accepts an instance of Redis as a required parameter.

Osman Üngür
o added a note

I know Redis class is the hard dependency of RedisCache.
But, for avoid confusion, i used same convention with MemcacheCache driver.
https://github.com/doctrine/common/blob/master/lib/Doctrine/Common/Cache/MemcacheCache.php#L49

Marco Pivetta Owner

Hmm... Yeah, makes sense, but I don't like that either... Also, modifying the MemcacheCache adapter would break BC... :(

Marco Pivetta Owner

Could you eventually add a __construct($redis = null) constructor and check if the passed in $redis is a Redis instance? That would probably fix also my request :)

Osman Üngür
o added a note

Hi Marco,
For keeping conventions same, also should add this check to MemcachedDriver.

I think we can solve this problem in another discussion/pr :)

Marco Pivetta Owner
Ocramius added a note

Yeah, I will eventually do that :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ {
+ $redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_IGBINARY);
+ $this->redis = $redis;
+ }
+
+ /**
+ * Gets the redis instance used by the cache.
+ *
+ * @return Redis
+ */
+ public function getRedis()
+ {
+ return $this->redis;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doFetch($id)
+ {
+ return $this->redis->get($id);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doContains($id)
+ {
+ return $this->redis->exists($id);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave($id, $data, $lifeTime = 0)
+ {
+ $result = $this->redis->set($id, $data);
+ if ($lifeTime > 0) {
+ $this->redis->expire($id, $lifeTime);
+ }
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDelete($id)
+ {
+ return $this->redis->delete($id);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doFlush()
+ {
+ return $this->redis->flushDB();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doGetStats()
+ {
+ $info = $this->redis->info();
+ return array(
+ Cache::STATS_HITS => false,
+ Cache::STATS_MISSES => false,
+ Cache::STATS_UPTIME => $info['uptime_in_seconds'],
+ Cache::STATS_MEMORY_USAGE => $info['used_memory'],
+ Cache::STATS_MEMORY_AVAILIABLE => false
+ );
+ }
+}
6 tests/Doctrine/Tests/Common/Cache/CacheTest.php
View
@@ -18,11 +18,15 @@ public function testBasics()
// Test fetch
$this->assertEquals('testing this out', $cache->fetch('test_key'));
-
+
// Test delete
$cache->save('test_key2', 'test2');
$cache->delete('test_key2');
$this->assertFalse($cache->contains('test_key2'));
+
+ // Fetch/save test with objects (Is cache driver serializes/unserializes objects correctly ?)
+ $cache->save('test_object_key', new \ArrayObject());
+ $this->assertTrue($cache->fetch('test_object_key') instanceof \ArrayObject);
}
public function testDeleteAll()
30 tests/Doctrine/Tests/Common/Cache/RedisCacheTest.php
View
@@ -0,0 +1,30 @@
+<?php
+
+namespace Doctrine\Tests\Common\Cache;
+
+use Doctrine\Common\Cache\RedisCache;
+
+class RedisCacheTest extends CacheTest
+{
+ private $_redis;
+
+ public function setUp()
+ {
+ if (extension_loaded('redis')) {
+ $this->_redis = new \Redis();
+ $ok = @$this->_redis->connect('127.0.0.1');
+ if (!$ok) {
+ $this->markTestSkipped('The ' . __CLASS__ .' requires the use of redis');
+ }
+ } else {
+ $this->markTestSkipped('The ' . __CLASS__ .' requires the use of redis');
+ }
+ }
+
+ protected function _getCacheDriver()
+ {
+ $driver = new RedisCache();
+ $driver->setRedis($this->_redis);
+ return $driver;
+ }
+}
Something went wrong with that request. Please try again.