From: Tim Düsterhus Date: Wed, 28 Sep 2016 15:14:38 +0000 (+0200) Subject: Allow plugins to leverage the Redis connection of the RedisCacheSource X-Git-Tag: 3.0.0_Beta_2~81 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=d597b119d6af261b46d55d19b87185f13b31f9dc;p=GitHub%2FWoltLab%2FWCF.git Allow plugins to leverage the Redis connection of the RedisCacheSource This removes the need to manually parse the Redis DSN specified by the administrator and saves socket connections by multiplexing the commands over a single connection, without being able to break the connection used by cache. --- diff --git a/wcfsetup/install/files/lib/system/cache/source/RedisCacheSource.class.php b/wcfsetup/install/files/lib/system/cache/source/RedisCacheSource.class.php index 960c0b217f..92cdb763bd 100644 --- a/wcfsetup/install/files/lib/system/cache/source/RedisCacheSource.class.php +++ b/wcfsetup/install/files/lib/system/cache/source/RedisCacheSource.class.php @@ -1,8 +1,7 @@ redis = new Redis(CACHE_SOURCE_REDIS_HOST); } - - $this->redis = new \Redis(); - - $regex = new Regex('^\[([a-z0-9\:\.]+)\](?::([0-9]{1,5}))?$', Regex::CASE_INSENSITIVE); - $host = StringUtil::trim(CACHE_SOURCE_REDIS_HOST); - $port = 6379; // default Redis port - - // check for IPv6 - if ($regex->match($host)) { - $matches = $regex->getMatches(); - $host = $matches[1]; - - if (isset($matches[2])) { - $port = $matches[2]; - } - } - else { - // IPv4 or host, try to get port - if (strpos($host, ':')) { - $parsedHost = explode(':', $host); - $host = $parsedHost[0]; - $port = $parsedHost[1]; - } + catch (\Exception $e) { + throw new SystemException('Unable to create a Redis instance', 0, '', $e); } - - if (!$this->redis->connect($host, $port)) { - throw new SystemException('Unable to connect to Redis server'); - } - - // automatically prefix key names with the WCF UUID - $this->redis->setOption(\Redis::OPT_PREFIX, WCF_UUID.':'); } /** @@ -193,4 +164,13 @@ class RedisCacheSource implements ICacheSource { return $info['redis_version']; } + + /** + * Returns the underlying Redis instance. + * + * @return Redis + */ + public function getRedis() { + return $this->redis; + } } diff --git a/wcfsetup/install/files/lib/system/database/Redis.class.php b/wcfsetup/install/files/lib/system/database/Redis.class.php new file mode 100644 index 0000000000..73fd8851e4 --- /dev/null +++ b/wcfsetup/install/files/lib/system/database/Redis.class.php @@ -0,0 +1,101 @@ + + * @package WoltLabSuite\Core\System\Database + */ +class Redis { + /** + * wrapped redis connection + * @var \Redis + */ + protected $redis = null; + + /** + * DSN string used to connect. + * @var string + */ + protected $dsn = ''; + + /** + * Connects to the redis server given by the DSN. + */ + public function __construct($dsn) { + if (!class_exists('Redis')) { + throw new \BadMethodCallException('Redis support is not enabled.'); + } + + $this->dsn = $dsn; + + $this->redis = new \Redis(); + + $regex = new Regex('^\[([a-z0-9\:\.]+)\](?::([0-9]{1,5}))?$', Regex::CASE_INSENSITIVE); + $host = StringUtil::trim($this->dsn); + $port = 6379; // default Redis port + + // check for IPv6 + if ($regex->match($host)) { + $matches = $regex->getMatches(); + $host = $matches[1]; + + if (isset($matches[2])) { + $port = $matches[2]; + } + } + else { + // IPv4 or host, try to get port + if (strpos($host, ':')) { + $parsedHost = explode(':', $host); + $host = $parsedHost[0]; + $port = $parsedHost[1]; + } + } + + if (!$this->redis->connect($host, $port)) { + throw new \RuntimeException('Unable to connect to Redis server'); + } + + // automatically prefix key names with the WCF UUID + $this->redis->setOption(\Redis::OPT_PREFIX, WCF_UUID.':'); + } + + /** + * Passes all method calls down to the underlying Redis connection. + */ + public function __call($name, array $arguments) { + switch ($name) { + case 'setOption': + case 'getOption': + + case 'open': + case 'connect': + + case 'popen': + case 'pconnect': + + case 'auth': + + case 'select': + + case 'close': + throw new \BadMethodCallException('You must not use '.$name); + } + return call_user_func_array([$this->redis, $name], $arguments); + } + + /** + * Returns a new, raw, redis instance to the same server. + * + * @return \Redis + */ + public function unwrap() { + return (new self($this->dsn))->redis; + } +}