8000 [Cache] Cleanups by nicolas-grekas · Pull Request #18687 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Cache] Cleanups #18687

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

Merged
merged 1 commit into from
May 2, 2016
Merged
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
8000
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Symfony/Component/Cache/Adapter/AbstractAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,15 @@ public function getItems(array $keys = array())
$ids = array();

foreach ($keys as $key) {
$ids[$key] = $this->getId($key);
$ids[] = $this->getId($key);
}
try {
$items = $this->doFetch($ids);
} catch (\Exception $e) {
CacheItem::log($this->logger, 'Failed to fetch requested items', array('keys' => $keys, 'exception' => $e));
$items = array();
}
$ids = array_flip($ids);
$ids = array_combine($ids, $keys);

return $this->generateItems($items, $ids);
}
Expand Down
69 changes: 37 additions & 32 deletions src/Symfony/Component/Cache/Adapter/RedisAdapter.php
10000
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ class RedisAdapter extends AbstractAdapter
);
private $redis;

public function __construct(\Redis $redisConnection, $namespace = '', $defaultLifetime = 0)
public function __construct(\Redis $redisClient, $namespace = '', $defaultLifetime = 0)
{
parent::__construct($namespace, $defaultLifetime);

if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) {
throw new InvalidArgumentException(sprintf('RedisAdapter namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0]));
}
$this->redis = $redisConnection;

parent::__construct($namespace, $defaultLifetime);
$this->redis = $redisClient;
}

/**
Expand Down Expand Up @@ -86,26 +86,29 @@ public static function createConnection($dsn, array $options = array())
$params += $query;
}
$params += $options + self::$defaultConnectionOptions;
$class = $params['class'];

if (\Redis::class !== $params['class'] && !is_subclass_of($params['class'], \Redis::class)) {
throw new InvalidArgumentException(sprintf('"%s" is not a subclass of "Redis"', $params['class']));
}
$connect = empty($params['persistent']) ? 'connect' : 'pconnect';
$redis = new $params['class']();
@$redis->{$connect}($params['host'], $params['port'], $params['timeout'], null, $params['retry_interval']);
if (is_a($class, \Redis::class, true)) {
$connect = empty($params['persistent']) ? 'connect' : 'pconnect';
$redis = new $class();
@$redis->{$connect}($params['host'], $params['port'], $params['timeout'], null, $params['retry_interval']);

if (@!$redis->isConnected()) {
$e = ($e = error_get_last()) && preg_match('/^Redis::p?connect\(\): (.*)/', $e['message'], $e) ? sprintf(' (%s)', $e[1]) : '';
throw new InvalidArgumentException(sprintf('Redis connection failed%s: %s', $e, $dsn));
}
if (@!$redis->isConnected()) {
$e = ($e = error_get_last()) && preg_match('/^Redis::p?connect\(\): (.*)/', $e['message'], $e) ? sprintf(' (%s)', $e[1]) : '';
throw new InvalidArgumentException(sprintf('Redis connection failed%s: %s', $e, $dsn));
}

if ((null !== $auth && !$redis->auth($auth))
|| ($params['dbindex'] && !$redis->select($params['dbindex']))
|| ($params['read_timeout'] && !$redis->setOption(\Redis::OPT_READ_TIMEOUT, $params['read_timeout']))
) {
$e = preg_replace('/^ERR /', '', $redis->getLastError());
$redis->close();
throw new InvalidArgumentException(sprintf('Redis connection failed (%s): %s', $e, $dsn));
if ((null !== $auth && !$redis->auth($auth))
|| ($params['dbindex'] && !$redis->select($params['dbindex']))
|| ($params['read_timeout'] && !$redis->setOption(\Redis::OPT_READ_TIMEOUT, $params['read_timeout']))
) {
$e = preg_replace('/^ERR /', '', $redis->getLastError());
throw new InvalidArgumentException(sprintf('Redis connection failed (%s): %s', $e, $dsn));
}
} elseif (class_exists($class, false)) {
throw new InvalidArgumentException(sprintf('"%s" is not a subclass of "Redis"', $class));
} else {
throw new InvalidArgumentException(sprintf('Class "%s" does not exist', $class));
}

return $redis;
Expand All @@ -119,10 +122,10 @@ protected function doFetch(array $ids)
$result = array();

if ($ids) {
$values = $this->redis->mget($ids);
$values = $this->redis->mGet($ids);
$index = 0;
foreach ($ids as $id) {
if (false !== $value = $values[$index++]) {
if ($value = $values[$index++]) {
$result[$id] = unserialize($value);
}
}
Expand All @@ -144,14 +147,16 @@ protected function doHave($id)
*/
protected function doClear($namespace)
{
// As documented in Redis documentation (http://redis.io/commands/keys) using KEYS
// can hang your server when it is executed against large databases (millions of items).
// Whenever you hit this scale, it is advised to deploy one Redis database per cache pool
// instead of using namespaces, so that FLUSHDB is used instead.
$lua = "local keys=redis.call('KEYS',ARGV[1]..'*') for i=1,#keys,5000 do redis.call('DEL',unpack(keys,i,math.min(i+4999,#keys))) end";
Copy link
Member

Choose a reason for hiding this comment

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

this should stay inside the else IMO

Copy link
Member Author

Choose a reason for hiding this comment

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

see #18689

Copy link
Member

Choose a reason for hiding this comment

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

Well, this other PR is changing the code anyway, so this does not forbid keeping this inside the else clause.


if (!isset($namespace[0])) {
$this->redis->flushDB();
$this->redis->flushDb();
} else {
// As documented in Redis documentation (http://redis.io/commands/keys) using KEYS
// can hang your server when it is executed against large databases (millions of items).
// Whenever you hit this scale, it is advised to deploy one Redis database per cache pool
// instead of using namespaces, so that the above FLUSHDB is used instead.
$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));
$this->redis->eval($lua, array($namespace), 0);
}

return true;
Expand Down Expand Up @@ -189,11 +194,11 @@ protected function doSave(array $values, $lifetime)
return $failed;
}
if ($lifetime > 0) {
$pipe = $this->redis->multi(\Redis::PIPELINE);
$this->redis->multi(\Redis::PIPELINE);
foreach ($serialized as $id => $value) {
$pipe->setEx($id, $lifetime, $value);
$this->redis->setEx($id, $lifetime, $value);
}
if (!$pipe->exec()) {
if (!$this->redis->exec()) {
return false;
}
} elseif (!$this->redis->mSet($serialized)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public static function tearDownAfterClass()
public function testCreateConnection()
{
$redis = RedisAdapter::createConnection('redis://localhost');
$this->assertInstanceOf(\Redis::class, $redis);
$this->assertTrue($redis->isConnected());
$this->assertSame(0, $redis->getDbNum());

Expand Down
0