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;
|
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
|
* 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
|
* 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.
|
* @inheritDocs
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
protected function getValue($key)
|
protected function getValue($key)
|
||||||
{
|
{
|
||||||
@@ -130,9 +127,7 @@ class RedisCache extends Cache
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves multiple values from cache with the specified keys.
|
* @inheritDocs
|
||||||
* @param array $keys a list of keys identifying the cached values
|
|
||||||
* @return array a list of cached values indexed by the keys
|
|
||||||
*/
|
*/
|
||||||
protected function getValues($keys)
|
protected function getValues($keys)
|
||||||
{
|
{
|
||||||
@@ -146,55 +141,67 @@ class RedisCache extends Cache
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores a value identified by a key in cache.
|
* @inheritDocs
|
||||||
* 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
|
|
||||||
*/
|
*/
|
||||||
protected function setValue($key,$value,$expire)
|
protected function setValue($key, $value, $expire)
|
||||||
{
|
{
|
||||||
if ($expire == 0) {
|
if ($expire == 0) {
|
||||||
return (bool) $this->_connection->executeCommand('SET', [$key, $value]);
|
return (bool) $this->_connection->executeCommand('SET', [$key, $value]);
|
||||||
} else {
|
} else {
|
||||||
$expire = (int) ($expire * 1000);
|
$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.
|
* @inheritDocs
|
||||||
* 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
|
|
||||||
*/
|
*/
|
||||||
protected function addValue($key,$value,$expire)
|
protected function setValues($data, $expire)
|
||||||
{
|
{
|
||||||
|
$args = [];
|
||||||
|
foreach($data as $key => $value) {
|
||||||
|
$args[] = $key;
|
||||||
|
$args[] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
$failedKeys = [];
|
||||||
if ($expire == 0) {
|
if ($expire == 0) {
|
||||||
return (bool) $this->_connection->executeCommand('SETNX', [$key, $value]);
|
$this->_connection->executeCommand('MSET', $args);
|
||||||
} else {
|
} else {
|
||||||
// TODO consider requiring redis version >= 2.6.12 that supports this in one command
|
|
||||||
$expire = (int) ($expire * 1000);
|
$expire = (int) ($expire * 1000);
|
||||||
$this->_connection->executeCommand('MULTI');
|
$this->_connection->executeCommand('MULTI');
|
||||||
$this->_connection->executeCommand('SETNX', [$key, $value]);
|
$this->_connection->executeCommand('MSET', $args);
|
||||||
$this->_connection->executeCommand('PEXPIRE', [$key, $expire]);
|
$index = [];
|
||||||
$response = $this->_connection->executeCommand('EXEC');
|
foreach ($data as $key => $value) {
|
||||||
return (bool) $response[0];
|
$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('SET', [$key, $value, 'NX']);
|
||||||
|
} else {
|
||||||
|
$expire = (int) ($expire * 1000);
|
||||||
|
return (bool) $this->_connection->executeCommand('SET', [$key, $value, 'PX', $expire, 'NX']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a value with the specified key from cache
|
* @inheritDocs
|
||||||
* 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
|
|
||||||
*/
|
*/
|
||||||
protected function deleteValue($key)
|
protected function deleteValue($key)
|
||||||
{
|
{
|
||||||
@@ -202,9 +209,7 @@ class RedisCache extends Cache
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all values from cache.
|
* @inheritDocs
|
||||||
* This is the implementation of the method declared in the parent class.
|
|
||||||
* @return boolean whether the flush operation was successful.
|
|
||||||
*/
|
*/
|
||||||
protected function flushValues()
|
protected function flushValues()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,4 +37,9 @@ class ApcCacheTest extends CacheTestCase
|
|||||||
{
|
{
|
||||||
$this->markTestSkipped("APC keys are expiring only on the next request.");
|
$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']);
|
$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 = $this->getCacheInstance();
|
||||||
$cache->flush();
|
$cache->flush();
|
||||||
@@ -100,7 +111,7 @@ abstract class CacheTestCase extends TestCase
|
|||||||
'string_test' => 'string_test',
|
'string_test' => 'string_test',
|
||||||
'number_test' => 42,
|
'number_test' => 42,
|
||||||
'array_test' => ['array_test' => 'array_test'],
|
'array_test' => ['array_test' => 'array_test'],
|
||||||
]);
|
], $expiry);
|
||||||
|
|
||||||
$this->assertEquals('string_test', $cache->get('string_test'));
|
$this->assertEquals('string_test', $cache->get('string_test'));
|
||||||
|
|
||||||
@@ -170,6 +181,17 @@ abstract class CacheTestCase extends TestCase
|
|||||||
$this->assertFalse($cache->get('expire_test'));
|
$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()
|
public function testAdd()
|
||||||
{
|
{
|
||||||
$cache = $this->prepare();
|
$cache = $this->prepare();
|
||||||
|
|||||||
@@ -83,4 +83,16 @@ class DbCacheTest extends CacheTestCase
|
|||||||
static::$time++;
|
static::$time++;
|
||||||
$this->assertFalse($cache->get('expire_test'));
|
$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++;
|
static::$time++;
|
||||||
$this->assertFalse($cache->get('expire_test'));
|
$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();
|
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();
|
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'));
|
$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
|
* Store a value that is 2 times buffer size big
|
||||||
* https://github.com/yiisoft/yii2/issues/743
|
* https://github.com/yiisoft/yii2/issues/743
|
||||||
|
|||||||
Reference in New Issue
Block a user