mirror of
https://github.com/yiisoft/yii2.git
synced 2025-11-20 16:38:22 +08:00
refactored redis cache, added mset()
This commit is contained in:
@@ -10,7 +10,7 @@ namespace yii\caching;
|
||||
use yii\redis\Connection;
|
||||
|
||||
/**
|
||||
* RedisCache implements a cache application component based on [redis](http://redis.io/) version 2.6 or higher.
|
||||
* RedisCache implements a cache application component based on [redis](http://redis.io/) version 2.6.12 or higher.
|
||||
*
|
||||
* RedisCache needs to be configured with [[hostname]], [[port]] and [[database]] of the server
|
||||
* to connect to. By default RedisCache assumes there is a redis server running on localhost at
|
||||
@@ -119,10 +119,7 @@ class RedisCache extends Cache
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a value from cache with a specified key.
|
||||
* This is the implementation of the method declared in the parent class.
|
||||
* @param string $key a unique key identifying the cached value
|
||||
* @return string|boolean the value stored in cache, false if the value is not in the cache or expired.
|
||||
* @inheritDocs
|
||||
*/
|
||||
protected function getValue($key)
|
||||
{
|
||||
@@ -130,9 +127,7 @@ class RedisCache extends Cache
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves multiple values from cache with the specified keys.
|
||||
* @param array $keys a list of keys identifying the cached values
|
||||
* @return array a list of cached values indexed by the keys
|
||||
* @inheritDocs
|
||||
*/
|
||||
protected function getValues($keys)
|
||||
{
|
||||
@@ -146,14 +141,7 @@ class RedisCache extends Cache
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a value identified by a key in cache.
|
||||
* This is the implementation of the method declared in the parent class.
|
||||
*
|
||||
* @param string $key the key identifying the value to be cached
|
||||
* @param string $value the value to be cached
|
||||
* @param float $expire the number of seconds in which the cached value will expire. 0 means never expire.
|
||||
* This can be a floating point number to specify the time in milliseconds.
|
||||
* @return boolean true if the value is successfully stored into cache, false otherwise
|
||||
* @inheritDocs
|
||||
*/
|
||||
protected function setValue($key, $value, $expire)
|
||||
{
|
||||
@@ -161,40 +149,59 @@ class RedisCache extends Cache
|
||||
return (bool) $this->_connection->executeCommand('SET', [$key, $value]);
|
||||
} else {
|
||||
$expire = (int) ($expire * 1000);
|
||||
return (bool) $this->_connection->executeCommand('PSETEX', [$key, $expire, $value]);
|
||||
return (bool) $this->_connection->executeCommand('SET', [$key, $value, 'PX', $expire]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a value identified by a key into cache if the cache does not contain this key.
|
||||
* This is the implementation of the method declared in the parent class.
|
||||
*
|
||||
* @param string $key the key identifying the value to be cached
|
||||
* @param string $value the value to be cached
|
||||
* @param float $expire the number of seconds in which the cached value will expire. 0 means never expire.
|
||||
* This can be a floating point number to specify the time in milliseconds.
|
||||
* @return boolean true if the value is successfully stored into cache, false otherwise
|
||||
* @inheritDocs
|
||||
*/
|
||||
protected function setValues($data, $expire)
|
||||
{
|
||||
$args = [];
|
||||
foreach($data as $key => $value) {
|
||||
$args[] = $key;
|
||||
$args[] = $value;
|
||||
}
|
||||
|
||||
$failedKeys = [];
|
||||
if ($expire == 0) {
|
||||
$this->_connection->executeCommand('MSET', $args);
|
||||
} else {
|
||||
$expire = (int) ($expire * 1000);
|
||||
$this->_connection->executeCommand('MULTI');
|
||||
$this->_connection->executeCommand('MSET', $args);
|
||||
$index = [];
|
||||
foreach ($data as $key => $value) {
|
||||
$this->_connection->executeCommand('PEXPIRE', [$key, $expire]);
|
||||
$index[] = $key;
|
||||
}
|
||||
$result = $this->_connection->executeCommand('EXEC');
|
||||
array_shift($result);
|
||||
foreach($result as $i => $r) {
|
||||
if ($r != 1) {
|
||||
$failedKeys[] = $index[$i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $failedKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDocs
|
||||
*/
|
||||
protected function addValue($key, $value, $expire)
|
||||
{
|
||||
if ($expire == 0) {
|
||||
return (bool) $this->_connection->executeCommand('SETNX', [$key, $value]);
|
||||
return (bool) $this->_connection->executeCommand('SET', [$key, $value, 'NX']);
|
||||
} else {
|
||||
// TODO consider requiring redis version >= 2.6.12 that supports this in one command
|
||||
$expire = (int) ($expire * 1000);
|
||||
$this->_connection->executeCommand('MULTI');
|
||||
$this->_connection->executeCommand('SETNX', [$key, $value]);
|
||||
$this->_connection->executeCommand('PEXPIRE', [$key, $expire]);
|
||||
$response = $this->_connection->executeCommand('EXEC');
|
||||
return (bool) $response[0];
|
||||
return (bool) $this->_connection->executeCommand('SET', [$key, $value, 'PX', $expire, 'NX']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a value with the specified key from cache
|
||||
* This is the implementation of the method declared in the parent class.
|
||||
* @param string $key the key of the value to be deleted
|
||||
* @return boolean if no error happens during deletion
|
||||
* @inheritDocs
|
||||
*/
|
||||
protected function deleteValue($key)
|
||||
{
|
||||
@@ -202,9 +209,7 @@ class RedisCache extends Cache
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all values from cache.
|
||||
* This is the implementation of the method declared in the parent class.
|
||||
* @return boolean whether the flush operation was successful.
|
||||
* @inheritDocs
|
||||
*/
|
||||
protected function flushValues()
|
||||
{
|
||||
|
||||
@@ -37,4 +37,9 @@ class ApcCacheTest extends CacheTestCase
|
||||
{
|
||||
$this->markTestSkipped("APC keys are expiring only on the next request.");
|
||||
}
|
||||
|
||||
public function testExpireAdd()
|
||||
{
|
||||
$this->markTestSkipped("APC keys are expiring only on the next request.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,18 @@ abstract class CacheTestCase extends TestCase
|
||||
$this->assertEquals('array_test', $array['array_test']);
|
||||
}
|
||||
|
||||
public function testMset()
|
||||
/**
|
||||
* @return array testing mset with and without expiry
|
||||
*/
|
||||
public function msetExpiry()
|
||||
{
|
||||
return [[0], [2]];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider msetExpiry
|
||||
*/
|
||||
public function testMset($expiry)
|
||||
{
|
||||
$cache = $this->getCacheInstance();
|
||||
$cache->flush();
|
||||
@@ -100,7 +111,7 @@ abstract class CacheTestCase extends TestCase
|
||||
'string_test' => 'string_test',
|
||||
'number_test' => 42,
|
||||
'array_test' => ['array_test' => 'array_test'],
|
||||
]);
|
||||
], $expiry);
|
||||
|
||||
$this->assertEquals('string_test', $cache->get('string_test'));
|
||||
|
||||
@@ -170,6 +181,17 @@ abstract class CacheTestCase extends TestCase
|
||||
$this->assertFalse($cache->get('expire_test'));
|
||||
}
|
||||
|
||||
public function testExpireAdd()
|
||||
{
|
||||
$cache = $this->getCacheInstance();
|
||||
|
||||
$this->assertTrue($cache->add('expire_testa', 'expire_testa', 2));
|
||||
usleep(500000);
|
||||
$this->assertEquals('expire_testa', $cache->get('expire_testa'));
|
||||
usleep(2500000);
|
||||
$this->assertFalse($cache->get('expire_testa'));
|
||||
}
|
||||
|
||||
public function testAdd()
|
||||
{
|
||||
$cache = $this->prepare();
|
||||
|
||||
@@ -83,4 +83,16 @@ class DbCacheTest extends CacheTestCase
|
||||
static::$time++;
|
||||
$this->assertFalse($cache->get('expire_test'));
|
||||
}
|
||||
|
||||
public function testExpireAdd()
|
||||
{
|
||||
$cache = $this->getCacheInstance();
|
||||
|
||||
static::$time = \time();
|
||||
$this->assertTrue($cache->add('expire_testa', 'expire_testa', 2));
|
||||
static::$time++;
|
||||
$this->assertEquals('expire_testa', $cache->get('expire_testa'));
|
||||
static::$time++;
|
||||
$this->assertFalse($cache->get('expire_testa'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,4 +33,16 @@ class FileCacheTest extends CacheTestCase
|
||||
static::$time++;
|
||||
$this->assertFalse($cache->get('expire_test'));
|
||||
}
|
||||
|
||||
public function testExpireAdd()
|
||||
{
|
||||
$cache = $this->getCacheInstance();
|
||||
|
||||
static::$time = \time();
|
||||
$this->assertTrue($cache->add('expire_testa', 'expire_testa', 2));
|
||||
static::$time++;
|
||||
$this->assertEquals('expire_testa', $cache->get('expire_testa'));
|
||||
static::$time++;
|
||||
$this->assertFalse($cache->get('expire_testa'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,4 +34,12 @@ class MemCacheTest extends CacheTestCase
|
||||
}
|
||||
parent::testExpire();
|
||||
}
|
||||
|
||||
public function testExpireAdd()
|
||||
{
|
||||
if (getenv('TRAVIS') == 'true') {
|
||||
$this->markTestSkipped('Can not reliably test memcache expiry on travis-ci.');
|
||||
}
|
||||
parent::testExpireAdd();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,4 +34,12 @@ class MemCachedTest extends CacheTestCase
|
||||
}
|
||||
parent::testExpire();
|
||||
}
|
||||
|
||||
public function testExpireAdd()
|
||||
{
|
||||
if (getenv('TRAVIS') == 'true') {
|
||||
$this->markTestSkipped('Can not reliably test memcached expiry on travis-ci.');
|
||||
}
|
||||
parent::testExpireAdd();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,17 @@ class RedisCacheTest extends CacheTestCase
|
||||
$this->assertFalse($cache->get('expire_test_ms'));
|
||||
}
|
||||
|
||||
public function testExpireAddMilliseconds()
|
||||
{
|
||||
$cache = $this->getCacheInstance();
|
||||
|
||||
$this->assertTrue($cache->add('expire_testa_ms', 'expire_testa_ms', 0.2));
|
||||
usleep(100000);
|
||||
$this->assertEquals('expire_testa_ms', $cache->get('expire_testa_ms'));
|
||||
usleep(300000);
|
||||
$this->assertFalse($cache->get('expire_testa_ms'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a value that is 2 times buffer size big
|
||||
* https://github.com/yiisoft/yii2/issues/743
|
||||
|
||||
Reference in New Issue
Block a user