Created
December 27, 2023 21:19
-
-
Save tazzytazzy/40deb7788166f9bbd1d42e762385432e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// For mediawiki 1.41.0 - includes/libs/redis/RedisConnectionPool.php | |
/** | |
* Get a connection to a redis server. Based on code in RedisBagOStuff.php. | |
* | |
* @param string $server A hostname/port combination or the absolute path of a UNIX socket. | |
* If a hostname is specified but no port, port 6379 will be used. | |
* @param LoggerInterface|null $logger PSR-3 logger instance. [optional] | |
* @return RedisConnRef|Redis|false Returns false on failure | |
* @throws InvalidArgumentException | |
*/ | |
public function getConnection( $server, LoggerInterface $logger = null ) { | |
// See: https://www.mediawiki.org/wiki/Talk:Redis | |
global $wgRedisDatabase; | |
if (is_null($wgRedisDatabase)) { | |
$wgRedisDatabase = 0; | |
} | |
// The above @return also documents 'Redis' for convenience with IDEs. | |
// RedisConnRef uses PHP magic methods, which wouldn't be recognised. | |
$logger = $logger ?: $this->logger; | |
// Check the listing "dead" servers which have had a connection errors. | |
// Servers are marked dead for a limited period of time, to | |
// avoid excessive overhead from repeated connection timeouts. | |
if ( isset( $this->downServers[$server] ) ) { | |
$now = time(); | |
if ( $now > $this->downServers[$server] ) { | |
// Dead time expired | |
unset( $this->downServers[$server] ); | |
} else { | |
// Server is dead | |
$logger->debug( | |
'Server "{redis_server}" is marked down for another ' . | |
( $this->downServers[$server] - $now ) . ' seconds', | |
[ 'redis_server' => $server ] | |
); | |
return false; | |
} | |
} | |
// Check if a connection is already free for use | |
if ( isset( $this->connections[$server] ) ) { | |
foreach ( $this->connections[$server] as &$connection ) { | |
if ( $connection['free'] ) { | |
$connection['free'] = false; | |
--$this->idlePoolSize; | |
return new RedisConnRef( | |
$this, $server, $connection['conn'], $logger | |
); | |
} | |
} | |
} | |
if ( !$server ) { | |
throw new InvalidArgumentException( | |
__CLASS__ . ": invalid configured server \"$server\"" ); | |
} elseif ( substr( $server, 0, 1 ) === '/' ) { | |
// UNIX domain socket | |
// These are required by the redis extension to start with a slash, but | |
// we still need to set the port to a special value to make it work. | |
$host = $server; | |
$port = 0; | |
} else { | |
// TCP connection | |
if ( preg_match( '/^\[(.+)\]:(\d+)$/', $server, $m ) ) { | |
// (ip, port) | |
[ $host, $port ] = [ $m[1], (int)$m[2] ]; | |
} elseif ( preg_match( '/^((?:[\w]+\:\/\/)?[^:]+):(\d+)$/', $server, $m ) ) { | |
// (ip, uri or path, port) | |
[ $host, $port ] = [ $m[1], (int)$m[2] ]; | |
if ( | |
substr( $host, 0, 6 ) === 'tls://' | |
&& version_compare( phpversion( 'redis' ), '5.0.0' ) < 0 | |
) { | |
throw new RuntimeException( | |
'A newer version of the Redis client library is required to use TLS. ' . | |
'See https://www.mediawiki.org/wiki/Redis#Setup' ); | |
} | |
} else { | |
// (ip or path, port) | |
[ $host, $port ] = [ $server, 6379 ]; | |
} | |
} | |
$conn = new Redis(); | |
try { | |
if ( $this->persistent ) { | |
$result = $conn->pconnect( $host, $port, $this->connectTimeout, $this->id ); | |
} else { | |
$result = $conn->connect( $host, $port, $this->connectTimeout ); | |
} | |
if ( !$result ) { | |
$logger->error( | |
'Could not connect to server "{redis_server}"', | |
[ 'redis_server' => $server ] | |
); | |
// Mark server down for some time to avoid further timeouts | |
$this->downServers[$server] = time() + self::SERVER_DOWN_TTL; | |
return false; | |
} | |
if ( ( $this->password !== null ) && !$conn->auth( $this->password ) ) { | |
$logger->error( | |
'Authentication error connecting to "{redis_server}"', | |
[ 'redis_server' => $server ] | |
); | |
} | |
} catch ( RedisException $e ) { | |
$this->downServers[$server] = time() + self::SERVER_DOWN_TTL; | |
$logger->error( | |
'Redis exception connecting to "{redis_server}"', | |
[ | |
'redis_server' => $server, | |
'exception' => $e, | |
] | |
); | |
return false; | |
} | |
$conn->select($wgRedisDatabase); | |
$conn->setOption( Redis::OPT_READ_TIMEOUT, $this->readTimeout ); | |
$conn->setOption( Redis::OPT_SERIALIZER, $this->serializer ); | |
$this->connections[$server][] = [ 'conn' => $conn, 'free' => false ]; | |
return new RedisConnRef( $this, $server, $conn, $logger ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment