8000 feature #18172 [Cache] Redis adapter (gcds, nicolas-grekas) · symfony/symfony@ded8491 · GitHub
[go: up one dir, main page]

Skip to content

Commit ded8491

Browse files
committed
feature #18172 [Cache] Redis adapter (gcds, nicolas-grekas)
This PR was merged into the 3.1-dev branch. Discussion ---------- [Cache] Redis adapter | Q | A | ------------- | --- | Branch | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #17441 | License | MIT | Doc PR | - Commits ------- 6b7a1fc [Cache] Finish Redis adapter 4893cbc Added RedisAdapter
2 parents f0b46d4 + 6b7a1fc commit ded8491

File tree

3 files changed

+164
-1
lines changed

3 files changed

+164
-1
lines changed

.travis.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ cache:
3131
- .phpunit
3232
- php-$MIN_PHP
3333

34-
services: mongodb
34+
services:
35+
- mongodb
36+
- redis-server
3537

3638
before_install:
3739
# Matrix lines for intermediate PHP versions are skipped for pull requests
@@ -48,6 +50,7 @@ before_install:
4850
- if [[ $TRAVIS_PHP_VERSION = 5.* && ! $deps ]]; then (cd src/Symfony/Component/Debug/Resources/ext && phpize && ./configure && make && echo extension = $(pwd)/modules/symfony_debug.so >> $INI_FILE); fi;
4951
- if [[ $TRAVIS_PHP_VERSION = 5.* ]]; then pecl install -f memcached-2.1.0; fi;
5052
- if [[ $TRAVIS_PHP_VERSION != hhvm ]]; then echo extension = ldap.so >> $INI_FILE; fi;
53+
- if [[ $TRAVIS_PHP_VERSION != hhvm ]]; then echo extension = redis.so >> $INI_FILE; fi;
5154
- if [[ $TRAVIS_PHP_VERSION != hhvm ]]; then phpenv config-rm xdebug.ini; fi;
5255
- if [[ $deps != skip ]]; then composer self-update; fi;
5356
- if [[ $deps != skip && $TRAVIS_REPO_SLUG = symfony/symfony ]]; then cp .composer/* ~/.composer/; composer global install --prefer-dist; fi;
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Cache\Adapter;
13+
14+
use Symfony\Component\Cache\Exception\InvalidArgumentException;
15+
16+
/**
17+
* @author Aurimas Niekis <aurimas@niekis.lt>
18+
*/
19+
class RedisAdapter extends AbstractAdapter
20+
{
21+
private $redis;
22+
23+
public function __construct(\Redis $redisConnection, $namespace = '', $defaultLifetime = 0)
24+
{
25+
$this->redis = $redisConnection;
26+
27+
if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) {
28+
throw new InvalidArgumentException(sprintf('RedisAdapter namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0]));
29+
}
30+
31+
parent::__construct($namespace, $defaultLifetime);
32+
}
33+
34+
/**
35+
* {@inheritdoc}
36+
*/
37+
protected function doFetch(array $ids)
38+
{
39+
$values = $this->redis->mget($ids);
40+
$index = 0;
41+
$result = [];
42+
43+
foreach ($ids as $id) {
44+
if (false !== $value = $values[$index++]) {
45+
$result[$id] = unserialize($value);
46+
}
47+
}
48+
49+
return $result;
50+
}
51+
52+
/**
53+
* {@inheritdoc}
54+
*/
55+
protected function doHave($id)
56+
{
57+
return $this->redis->exists($id);
58+
}
59+
60+
/**
61+
* {@inheritdoc}
62+
*/
63+
protected function doClear($namespace)
64+
{
65+
if (!isset($namespace[0])) {
66+
$this->redis->flushDB();
67+
} else {
68+
// As documented in Redis documentation (http://redis.io/commands/keys) using KEYS
69+
// can hang your server when it is executed against large databases (millions of items).
70+
// Whenever you hit this scale, it is advised to deploy one Redis database per cache pool
71+
// instead of using namespaces, so that the above FLUSHDB is used instead.
72+
$this->redis->eval(sprintf("local keys=redis.call('KEYS','%s*') for i=1,#keys,5000 do redis.call('DEL',unpack(keys,i,math.min(i+4999,#keys))) end", $namespace));
73+
}
74+
75+
return true;
76+
}
77+
78+
/**
79+
* {@inheritdoc}
80+
*/
81+
protected function doDelete(array $ids)
82+
{
83+
$this->redis->del($ids);
84+
85+
return true;
86+
}
87+
88+
/**
89+
* {@inheritdoc}
90+
*/
91+
protected function doSave(array $values, $lifetime)
92+
{
93+
$failed = array();
94+
95+
foreach ($values as $id => $v) {
96+
try {
97+
$values[$id] = serialize($v);
98+
} catch (\Exception $e) {
99+
$failed[] = $id;
100+
}
101+
}
102+
103+
if (!$this->redis->mSet($values)) {
104+
return false;
105+
}
106+
107+
if ($lifetime >= 1) {
108+
foreach ($values as $id => $v) {
109+
$this->redis->expire($id, $lifetime);
110+
}
111+
}
112+
113+
return $failed;
114+
}
115+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Cache\Tests\Adapter;
13+
14+
use Cache\IntegrationTests\CachePoolTest;
15+
use Symfony\Component\Cache\Adapter\RedisAdapter;
16+
17+
/**
18+
* @requires extension redis
19+
*/
20+
class RedisAdapterTest extends CachePoolTest
21+
{
22+
private static $redis;
23+
24+
public function createCachePool()
25+
{
26+
if (defined('HHVM_VERSION')) {
27+
$this->skippedTests['testDeferredSaveWithoutCommit'] = 'Fails on HHVM';
28+
}
29+
30+
return new RedisAdapter(self::$redis, str_replace('\\', '.', __CLASS__));
31+
}
32+
33+
public static function setupBeforeClass()
34+
{
35+
self::$redis = new \Redis();
36+
self::$redis->connect('127.0.0.1');
37+
self::$redis->select(1993);
38+
}
39+
40+
public static function tearDownAfterClass()
41+
{
42+
self::$redis->flushDB();
43+
self::$redis->close();
44+
}
45+
}

0 commit comments

Comments
 (0)
0