diff --git a/administrator/components/com_config/model/form/application.xml b/administrator/components/com_config/model/form/application.xml index a620e7993fa9b..bc0beb7b7040d 100644 --- a/administrator/components/com_config/model/form/application.xml +++ b/administrator/components/com_config/model/form/application.xml @@ -143,6 +143,17 @@ + + delete($this->_getCacheId($id, $group)); + return static::$_redis->del($this->_getCacheId($id, $group))>0; } /** @@ -320,12 +320,12 @@ public function clean($group, $mode = null) { if (strpos($key, $secret . '-cache-' . $group . '-') === 0 && $mode == 'group') { - static::$_redis->delete($key); + static::$_redis->del($key); } if (strpos($key, $secret . '-cache-' . $group . '-') !== 0 && $mode != 'group') { - static::$_redis->delete($key); + static::$_redis->del($key); } } diff --git a/libraries/joomla/cache/storage/rediscluster.php b/libraries/joomla/cache/storage/rediscluster.php new file mode 100644 index 0000000000000..a086b78d9c099 --- /dev/null +++ b/libraries/joomla/cache/storage/rediscluster.php @@ -0,0 +1,103 @@ +getConnection(); + } + } + /** + * Create the Redis Cluster connection + * + * @return Redis|boolean Redis connection object on success, boolean on failure + * + * @since 3.4 + * @note As of 4.0 this method will throw a JCacheExceptionConnecting object on connection failure + */ + protected function getConnection() + { + if (static::isSupported() == false) + { + return false; + } + $app = JFactory::getApplication(); + + $string = $app->get('redis_server_cluster_host_port'); + $string = str_replace(' ', '', $string); + $arr = explode(",",$string); + if (empty($arr)) { + return false; + } + + static::$_redis = new RedisCluster(NULL, $arr); + + // The default option, only send commands to master nodes + static::$_redis->setOption(RedisCluster::OPT_SLAVE_FAILOVER, RedisCluster::FAILOVER_NONE); + + // In the event we can't reach a master, and it has slaves, failover for read commands + static::$_redis->setOption(RedisCluster::OPT_SLAVE_FAILOVER, RedisCluster::FAILOVER_ERROR); + + // Always distribute readonly commands between masters and slaves, at random + static::$_redis->setOption(RedisCluster::OPT_SLAVE_FAILOVER, RedisCluster::FAILOVER_DISTRIBUTE); + + try + { + static::$_redis->ping(); + } + catch (RedisClusterException $e) + { + static::$_redis = null; + if ($app->isClient('administrator')) + { + JError::raiseWarning(500, 'Redis Cluster ping failed'); + } + return false; + } + return static::$_redis; + } + /** + * Test to see if the storage handler is available. + * + * @return boolean + * + * @since 3.4 + */ + public static function isSupported() + { + return class_exists('RedisCluster'); + } + /** + * Test to see if the Redis Cluster connection is available. + * + * @return boolean + * + * @since 3.4 + */ + public static function isConnected() + { + return static::$_redis instanceof RedisCluster; + } +} \ No newline at end of file diff --git a/tests/unit/suites/libraries/joomla/cache/storage/JCacheStorageRedisclusterTest.php b/tests/unit/suites/libraries/joomla/cache/storage/JCacheStorageRedisclusterTest.php new file mode 100644 index 0000000000000..f898399c140e9 --- /dev/null +++ b/tests/unit/suites/libraries/joomla/cache/storage/JCacheStorageRedisclusterTest.php @@ -0,0 +1,40 @@ +markTestSkipped('The Redis Cluster cache handler is not supported on this system.'); + } + parent::setUp(); + // Mock the returns on JApplicationCms::get() to use the default values + JFactory::$application->expects($this->any()) + ->method('get') + ->willReturnArgument(1); + $this->handler = new JCacheStorageRediscluster; + // This adapter doesn't throw an Exception on a connection failure so we'll have to use Reflection to get into the class to check it + if (!(TestReflection::getValue($this->handler, '_rediscluster') instanceof RedisCluster)) + { + $this->markTestSkipped('Failed to connect to Redis Cluster'); + } + // Override the lifetime because the JCacheStorage API multiplies it by 60 (converts minutes to seconds) + $this->handler->_lifetime = 2; + } +} \ No newline at end of file