25 use Psr\Log\LoggerAwareInterface;
26 use Psr\Log\LoggerInterface;
80 if ( !class_exists(
'Redis' ) ) {
81 throw new RuntimeException(
82 __CLASS__ .
' requires a Redis client library. ' .
83 'See https://www.mediawiki.org/wiki/Redis#Setup' );
85 $this->logger = isset(
$options[
'logger'] )
87 : new \Psr\Log\NullLogger();
88 $this->connectTimeout =
$options[
'connectTimeout'];
89 $this->readTimeout =
$options[
'readTimeout'];
90 $this->persistent =
$options[
'persistent'];
91 $this->password =
$options[
'password'];
92 if ( !isset(
$options[
'serializer'] ) ||
$options[
'serializer'] ===
'php' ) {
93 $this->serializer = Redis::SERIALIZER_PHP;
94 } elseif (
$options[
'serializer'] ===
'igbinary' ) {
95 $this->serializer = Redis::SERIALIZER_IGBINARY;
96 } elseif (
$options[
'serializer'] ===
'none' ) {
97 $this->serializer = Redis::SERIALIZER_NONE;
99 throw new InvalidArgumentException(
"Invalid serializer specified." );
117 if ( !isset(
$options[
'connectTimeout'] ) ) {
120 if ( !isset(
$options[
'readTimeout'] ) ) {
123 if ( !isset(
$options[
'persistent'] ) ) {
126 if ( !isset(
$options[
'password'] ) ) {
154 if ( !isset( self::$instances[
$id] ) ) {
158 return self::$instances[
$id];
166 self::$instances = [];
183 if ( isset( $this->downServers[$server] ) ) {
185 if ( $now > $this->downServers[$server] ) {
187 unset( $this->downServers[$server] );
191 'Server "{redis_server}" is marked down for another ' .
192 ( $this->downServers[$server] - $now ) .
'seconds',
193 [
'redis_server' => $server ]
201 if ( isset( $this->connections[$server] ) ) {
202 foreach ( $this->connections[$server]
as &$connection ) {
203 if ( $connection[
'free'] ) {
204 $connection[
'free'] =
false;
208 $this, $server, $connection[
'conn'],
$logger
215 throw new InvalidArgumentException(
216 __CLASS__ .
": invalid configured server \"$server\"" );
217 } elseif ( substr( $server, 0, 1 ) ===
'/' ) {
225 if ( preg_match(
'/^\[(.+)\]:(\d+)$/', $server, $m ) ) {
226 list( $host, $port ) = [ $m[1], (int)$m[2] ];
227 } elseif ( preg_match(
'/^([^:]+):(\d+)$/', $server, $m ) ) {
228 list( $host, $port ) = [ $m[1], (int)$m[2] ];
230 list( $host, $port ) = [ $server, 6379 ];
236 if ( $this->persistent ) {
237 $result = $conn->pconnect( $host, $port, $this->connectTimeout, $this->
id );
239 $result = $conn->connect( $host, $port, $this->connectTimeout );
243 'Could not connect to server "{redis_server}"',
244 [
'redis_server' => $server ]
251 if ( $this->password !==
null ) {
252 if ( !$conn->auth( $this->password ) ) {
254 'Authentication error connecting to "{redis_server}"',
255 [
'redis_server' => $server ]
259 }
catch ( RedisException
$e ) {
262 'Redis exception connecting to "{redis_server}"',
264 'redis_server' => $server,
273 $conn->setOption( Redis::OPT_READ_TIMEOUT, $this->readTimeout );
274 $conn->setOption( Redis::OPT_SERIALIZER, $this->serializer );
275 $this->connections[$server][] = [
'conn' => $conn,
'free' =>
false ];
293 foreach ( $this->connections[$server]
as &$connection ) {
294 if ( $connection[
'conn'] === $conn && !$connection[
'free'] ) {
295 $connection[
'free'] =
true;
310 if ( $this->idlePoolSize <=
count( $this->connections ) ) {
314 foreach ( $this->connections
as &$serverConnections ) {
315 foreach ( $serverConnections
as $key => &$connection ) {
316 if ( $connection[
'free'] ) {
317 unset( $serverConnections[$key] );
318 if ( --$this->idlePoolSize <=
count( $this->connections ) ) {
337 $this->logger->error(
338 'Redis exception on server "{redis_server}"',
340 'redis_server' => $server,
344 foreach ( $this->connections[$server]
as $key => $connection ) {
346 $this->idlePoolSize -= $connection[
'free'] ? 1 : 0;
347 unset( $this->connections[$server][$key] );
370 if ( $this->password !==
null ) {
371 if ( !$conn->auth( $this->password ) ) {
372 $this->logger->error(
373 'Authentication error connecting to "{redis_server}"',
374 [
'redis_server' => $server ]
391 $conn->setOption( Redis::OPT_READ_TIMEOUT, $timeout ?: $this->readTimeout );
398 foreach ( $this->connections
as $server => &$serverConnections ) {
399 foreach ( $serverConnections
as $key => &$connection ) {
401 $conn = $connection[
'conn'];